In 2025, 70% of server breaches stem from default settings + weak passwords + delayed updates. This article isn't a long list of theoretical best practices — it's 10 steps we actually apply on every server we manage.
1. Change the default SSH port
Bots scanning the internet try port 22. Change it (to 2222 or 5022) and 95% of automated attacks stop.
# /etc/ssh/sshd_config
Port 5022
PermitRootLogin no
PasswordAuthentication no
Disabling PasswordAuthentication is critical: use SSH keys only. Still using passwords? You're vulnerable to brute-force.
2. Enable UFW Firewall
Ubuntu's firewall — simple and effective. Rule: deny all, allow only what you need.
ufw default deny incoming
ufw default allow outgoing
ufw allow 5022/tcp # SSH
ufw allow 80/tcp # HTTP
ufw allow 443/tcp # HTTPS
ufw enable
If you have another service (e.g., database on 3306), don't open it to the public. Bind to 127.0.0.1 only.
3. Use Fail2Ban against brute-force
Fail2Ban watches the SSH log (and any service) and bans IPs that fail multiple times.
apt install fail2ban
# /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 5022
maxretry = 3
bantime = 3600
After 3 failed attempts, IP is banned for an hour. Increase bantime to 24h if you prefer.
4. Update packages weekly
Vulnerabilities are discovered daily. Monthly updates leave you exposed.
# /etc/cron.weekly/auto-update
apt update
apt upgrade -y
apt autoremove -y
Or use unattended-upgrades for automatic security updates:
apt install unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades
5. Close unneeded services
Every running service = open port = breach potential. List running services:
ss -tlnp
Stop and disable any you don't need:
systemctl stop postfix
systemctl disable postfix
6. HTTPS only (with HSTS)
Use Let's Encrypt for free certificates:
apt install certbot python3-certbot-nginx
certbot --nginx -d example.com
Then enable HSTS in nginx config:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
HSTS forces browsers to refuse HTTP entirely, even if the user types http://.
7. Automate backups + test them
Untested backups = illusion. Rules:
- Daily backup of /etc, /var/www, /home, /var/lib/mysql.
- Weekly full server snapshot.
- Monthly: restore backup to a test server.
Store backups on a different server (not the same one). If budget allows, on cloud (S3, Backblaze B2).
8. Enable 2FA for SSH
Even if SSH key is stolen, attacker needs an OTP too.
apt install libpam-google-authenticator
google-authenticator # set up for each user
Then in /etc/ssh/sshd_config:
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
9. Monitor logs
Use logwatch or rsyslog + central log server. Important logs:
- /var/log/auth.log (login attempts).
- /var/log/nginx/access.log and error.log.
- /var/log/mysql/error.log.
- /var/log/fail2ban.log.
For critical servers, set up alerting (email or Telegram bot) for:
- Failed root login attempts.
- Sudden traffic spikes.
- Disk full.
10. Use AIDE or Lynis for periodic audits
AIDE (Advanced Intrusion Detection Environment) tracks file changes:
apt install aide
aideinit
cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
# after a week:
aide --check
Lynis is an excellent audit tool that reports vulnerabilities:
apt install lynis
lynis audit system
Run Lynis monthly and review warnings.
ROI of hardening
Securing a server with these 10 steps = a day's work. Cost: your time only. Benefits:
- Reduce breach probability by 90%.
- Detect breaches (if they occur) quickly.
- Quick recovery from any issue.
- Comply with GDPR and Egyptian Data Protection Law.
One client had 500 SSH attempts daily before hardening. After: zero. Not magic — just closing open doors.
Bottom line
Server hardening isn't a goal, it's an ongoing process. Start with 5 steps (port, firewall, fail2ban, updates, backups) today. Finish the rest within a month. Then review quarterly.
Need help securing your server? We offer a comprehensive security audit with a vulnerabilities report and remediation steps.