Got a fresh Linux server? You're most vulnerable in the first few hours. These 8 steps protect your server from the most common attacks — from brute-force to data leaks.
01 — No Passwords: SSH Keys Instead of Login
ssh-keygen -t ed25519 -C "your@email.com"
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@YOUR-SERVER-IP
PasswordAuthentication no
PermitRootLogin prohibit-password
PubkeyAuthentication yes
sudo systemctl restart ssh
02 — Don't Work as Root: Create a Deploy User
sudo adduser deploy
sudo usermod -aG sudo deploy
sudo mkdir -p /home/deploy/.ssh
sudo cp /root/.ssh/authorized_keys /home/deploy/.ssh/
sudo chown -R deploy:deploy /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh && sudo chmod 600 /home/deploy/.ssh/authorized_keys
03 — Enable Firewall: Configure ufw
sudo apt install ufw -y
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
04 — Automatic Updates: unattended-upgrades
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades
sudo unattended-upgrades --dry-run --debug
05 — Fail2ban: Block Brute-Force
sudo apt install fail2ban -y
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
[DEFAULT]
maxretry = 5
bantime = 3600
findtime = 600
[sshd]
enabled = true
sudo systemctl enable fail2ban && sudo systemctl start fail2ban
sudo fail2ban-client status sshd
06 — Never Commit .env: Keep Secrets Out of Git
cat >> .gitignore << 'EOF'
.env
.env.local
*.pem
*.key
EOF
chmod 600 /opt/myapp/.env
chown deploy:deploy /opt/myapp/.env
07 — HTTPS with Certbot: Let's Encrypt SSL
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.com
sudo certbot renew --dry-run
sudo certbot certificates
08 — Automate Backups: restic + 3-2-1 Rule
sudo apt install restic -y
restic init --repo sftp:uXXXXXX@uXXXXXX.your-storagebox.de:/backups/myapp
#!/bin/bash
export RESTIC_REPOSITORY="sftp:uXXXXXX@uXXXXXX.your-storagebox.de:/backups/myapp"
export RESTIC_PASSWORD_FILE="/root/.restic-password" # File with chmod 600, NEVER inline in the script!
restic backup /opt/myapp /etc/nginx --exclude="*.log" --exclude="node_modules"
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic check
(crontab -l 2>/dev/null; echo "0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1") | crontab -
restic snapshots
Checklist
- ✅ SSH key configured, password login disabled
- ✅ Deploy user created, root login restricted
- ✅ UFW enabled, only required ports open
- ✅ unattended-upgrades running
- ✅ Fail2ban protecting SSH from brute-force
- ✅ .env in .gitignore, no secrets in code
- ✅ HTTPS active, Certbot auto-renewal configured
- ✅ Backup running daily, restore tested
These 8 steps cover the most common attack vectors. No system is 100% secure — but you make it significantly harder for attackers. For 99% of automated scans that's enough to move on.

