Every compromised server I've investigated shared the same pattern: basic hardening steps were skipped. The entry point was usually SSH brute-force, an unpatched service, or a wide-open firewall rule left from a quick test months earlier.
This checklist covers eleven server security best practices that stop most attacks before they start. Each step is something you can implement today, whether you run a single VPS or manage a fleet of dedicated boxes.
1. Disable password authentication for SSH
Passwords are guessable. Key-based authentication is not.
Generate an SSH key pair on your local machine if you don't have one:
ssh-keygen -t ed25519 -C "[email protected]"
Copy the public key to your server:
ssh-copy-id user@server-ip
Then edit /etc/ssh/sshd_config and set:
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password
Restart the SSH daemon:
systemctl restart sshd
Test your key login from a new terminal before you close the current session. I've seen admins lock themselves out by skipping this step.
2. Change the default SSH port
Port 22 gets hammered by automated scanners. Moving SSH to a high port (above 1024) cuts noise in your auth logs by an order of magnitude.
In /etc/ssh/sshd_config:
Port 2849
Pick a random number between 10000 and 65535. Update your firewall rules first, then restart SSH. Security through obscurity isn't a defense by itself, but it does reduce log clutter and failed login attempts.
3. Configure a firewall with default-deny
Your firewall should block everything except the services you explicitly need.
On Linux, use ufw for simplicity:
ufw default deny incoming
ufw default allow outgoing
ufw allow 2849/tcp # your SSH port
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
For more control, use iptables or firewalld. On Windows Server, configure Windows Defender Firewall with the same principle: inbound blocked by default, outbound allowed, explicit rules for needed ports.
Check your current rules:
ufw status verbose
Every open port is a potential attack surface. Close what you don't need.
4. Set up automatic security updates
Patching is not optional. Most breaches exploit known vulnerabilities that already have fixes.
On Debian/Ubuntu, enable unattended-upgrades:
apt install unattended-upgrades
dpkg-reconfigure -plow unattended-upgrades
Edit /etc/apt/apt.conf.d/50unattended-upgrades to control what gets updated automatically. At minimum, enable security updates.
On RHEL/Rocky/AlmaLinux, use dnf-automatic:
dnf install dnf-automatic
systemctl enable --now dnf-automatic.timer
For Windows, enable automatic updates through Group Policy or Windows Update settings. Schedule them for a maintenance window if you need uptime predictability, but don't skip them.
Check your last update date right now:
stat /var/log/apt/history.log # Debian/Ubuntu
dnf history # RHEL family
If it's been more than two weeks, you're behind.
5. Install and configure fail2ban
Fail2ban watches your logs for repeated failed login attempts and bans the source IP automatically.
Install it:
apt install fail2ban # Debian/Ubuntu
dnf install fail2ban # RHEL family
Create /etc/fail2ban/jail.local:
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
[sshd]
enabled = true
port = 2849
logpath = /var/log/auth.log
Start the service:
systemctl enable --now fail2ban
Check banned IPs:
fail2ban-client status sshd
In support tickets I handled, fail2ban stopped brute-force attacks within minutes of installation. The configuration above bans an IP for one hour after five failed attempts in ten minutes.
6. Disable unused services and remove unnecessary packages
Every running service is a potential exploit target.
List active services:
systemctl list-units --type=service --state=running
Disable anything you don't recognize or use:
systemctl disable --now service-name
Common candidates: cups (printing), avahi-daemon (network discovery), bluetooth. If your server doesn't need it, turn it off.
Remove packages you don't need:
apt autoremove
A smaller attack surface is a more secure one.
7. Enable and monitor audit logging
Audit logs tell you who did what and when. You need them for incident response and compliance.
On Linux, use auditd:
apt install auditd
systemctl enable --now auditd
Add rules to watch sensitive files and directories. Example:
auditctl -w /etc/passwd -p wa -k passwd_changes
auditctl -w /etc/shadow -p wa -k shadow_changes
auditctl -w /var/log/auth.log -p wa -k auth_log_changes
Make rules persistent by adding them to /etc/audit/rules.d/audit.rules.
Search audit logs:
ausearch -k passwd_changes
On Windows, enable auditing through Group Policy and review the Security event log regularly. Focus on logon events, account changes, and privilege escalations.
Ship your logs to a central location. If an attacker gets root, they'll erase local logs.
8. Harden kernel parameters with sysctl
The Linux kernel has tunable parameters that improve security.
Edit /etc/sysctl.conf or create /etc/sysctl.d/99-hardening.conf:
# Ignore ICMP ping requests
net.ipv4.icmp_echo_ignore_all = 1
# Disable IP forwarding
net.ipv4.ip_forward = 0
# Enable SYN cookies (DDoS protection)
net.ipv4.tcp_syncookies = 1
# Ignore ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
# Disable source packet routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# Log martians (packets with impossible addresses)
net.ipv4.conf.all.log_martians = 1
Apply the changes:
sysctl -p
These settings reduce the risk of network-based attacks and information leakage.
9. Use a file integrity monitoring tool
File integrity monitoring detects unauthorized changes to system files and configurations.
Install AIDE (Advanced Intrusion Detection Environment):
apt install aide
Initialize the database:
aideinit
This creates a snapshot of your filesystem. Run checks regularly:
aide --check
AIDE will report any modified, added, or deleted files. Schedule it in cron:
0 3 * * * /usr/bin/aide --check | mail -s "AIDE Report" [email protected]
Alternatively, use Tripwire or OSSEC for more features.
10. Restrict user privileges and use sudo
Never run services as root. Never log in as root for daily tasks.
Create a regular user account if you haven't:
adduser adminuser
usermod -aG sudo adminuser # Debian/Ubuntu
usermod -aG wheel adminuser # RHEL family
Then enforce root login restrictions in /etc/ssh/sshd_config:
PermitRootLogin no
Use sudo for administrative tasks. Configure /etc/sudoers carefully:
visudo
Grant only the permissions each user needs. Avoid ALL=(ALL:ALL) ALL unless absolutely necessary.
For services, create dedicated users with no shell:
useradd -r -s /usr/sbin/nologin serviceuser
Run the service under that user account.
11. Schedule regular security audits
Automation catches most issues, but manual reviews catch the rest.
Run Lynis, an open-source security auditing tool:
git clone https://github.com/CISOfy/lynis
cd lynis
./lynis audit system
Lynis produces a detailed report with warnings and suggestions. Review it quarterly at minimum.
Check for:
- Unnecessary open ports: netstat -tuln or ss -tuln
- World-writable files: find / -xdev -type f -perm -0002
- Files without an owner: find / -xdev -nouser -o -nogroup
- SUID/SGID binaries: find / -perm /6000 -type f
Audit your user accounts:
cat /etc/passwd
Remove old accounts and disable unused ones:
usermod -L username # lock the account
Document what you find and fix issues on a schedule.
What if you're already compromised?
If you suspect a breach, act fast. Isolate the server from the network, preserve logs, snapshot the disk, and rebuild from a known-good backup.
Don't try to clean an infected system in place. Rootkits and backdoors persist through partial cleanups. A full rebuild is faster and more reliable.
After rebuilding, walk through this checklist before you bring the server back online.
Start with SSH and the firewall
If you do nothing else today, disable SSH password authentication and configure a default-deny firewall. Those two steps stop the majority of automated attacks.
The rest of this checklist builds defense in depth. No single control is perfect, but together they make your server a hard target. Walk through each step, test your changes, and document what you did. Your future self will thank you when the next vulnerability drops.
![Server Security Best Practices: 11 Steps [2026 Update]](/images/blog/server-security-best-practices-11-steps-2026-update.jpg)