Your server is only as strong as its weakest setting. A misconfigured SSH port or an open firewall can hand attackers a free pass. This server security checklist covers the 8 steps that matter most, plus the 9 mistakes that keep coming up in support tickets.
Use this guide as a working document. Run the commands, check the configs, and fix the gaps before an incident happens.
Step 1: Update Everything and Patch Regularly
Outdated packages are the easiest door for automated scanners. Attackers scan for known vulnerabilities in old kernels, libraries, and web servers. You need a repeatable update routine, not a one-time fix.
Run your package manager update command at least weekly. On Debian or Ubuntu:
sudo apt update && sudo apt upgrade -y
On RHEL, AlmaLinux, or CentOS:
sudo dnf update -y
Schedule a weekly cron job so updates apply without manual work. Reboot only when a kernel update lands. Test critical services after any patch batch.
In support tickets I handled, the usual culprit was a stale kernel. A reboot after the update closed the gap.
Step 2: Harden SSH Access
SSH is the primary entry point for most Linux servers. Default settings invite brute force attacks. Change the port, disable root login, and enforce key-based auth.
Edit /etc/ssh/sshd_config and set these values:
Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
Restart the service:
sudo systemctl restart sshd
Generate keys on your local machine, copy the public key to the server, and verify access before closing password login. Keep a backup terminal open while you test.
Step 3: Disable Unused Services
Every running service expands the attack surface. A web server does not need a mail daemon. A database box does not need a print server.
List active services:
systemctl list-units --type=service --state=running
Disable anything you do not need:
sudo systemctl disable --now cups.service
Check what started automatically:
systemctl list-unit-files --state=enabled
Remove unused packages with your package manager. Leave only the services that serve your actual workload.
Step 4: Configure a Firewall
A firewall is your first line of defense. It drops unwanted traffic before it reaches your applications. Use ufw on Debian/Ubuntu or firewalld on RHEL-family systems.
On Ubuntu with ufw:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
On CentOS/AlmaLinux with firewalld:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Never allow all traffic. Lock down to the ports your services actually need.
Step 5: Set Up Fail2ban
Brute force attacks on SSH and login panels are common. Fail2ban monitors logs and bans IPs that show malicious behavior. It is a simple layer that stops most automated attempts.
Install fail2ban:
sudo apt install fail2ban
Copy the default config and add a local override:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Edit jail.local and set:
[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
Restart the service:
sudo systemctl restart fail2ban
Check active bans:
sudo fail2ban-client status sshd
Step 6: Harden File Permissions
Wrong permissions let users read, write, or execute files they should not touch. Web roots, config files, and scripts need tight controls.
Set the web root to 755 and files to 644:
sudo find /var/www/html -type d -exec chmod 755 {} +
sudo find /var/www/html -type f -exec chmod 644 {} +
Protect sensitive files like .env or wp-config.php with 640 or 600:
sudo chmod 640 /var/www/html/wp-config.php
Ensure the web server user owns only what it needs:
sudo chown -R www-data:www-data /var/www/html
Check for world-writable files:
find / -perm -222 -type d
Step 7: Secure PHP and Application Configs
For WordPress and PHP sites, configuration errors are a top risk. Expose debug errors only in staging. Disable dangerous functions. Keep file uploads restricted.
In php.ini, disable dangerous settings:
display_errors = Off
expose_php = Off
allow_url_include = Off
For WordPress, limit XML-RPC if not needed. It is a common target for brute force and DDoS attacks. Remove it or restrict it with a plugin or server rule.
Keep application files outside the web root when possible. Back up configs separately. Never commit secrets to version control.
Step 8: Monitor Logs and Set Up Alerts
You cannot fix what you do not see. Centralize logs and watch for failed logins, permission changes, and suspicious commands.
Install and enable auditd for file access monitoring:
sudo apt install auditd
sudo systemctl enable --now auditd
Watch auth logs:
sudo tail -f /var/log/auth.log
Set up a log shipper or alerting tool. Get notified on repeated failed logins, new user accounts, or config changes. Early warning stops small issues from becoming outages.
The 9 Common Mistakes
1. Leaving Root Login Enabled
Root login is the most targeted account. Disable it and use a regular user with sudo.
2. Running Services as Root
Launch daemons under a dedicated user. Never run a web server or database as root.
3. Using Default SSH Port
Default port 22 is scanned constantly. Change it to a non-standard port.
4. Allowing Password Authentication
Keys are harder to crack. Disable password auth once key setup is verified.
5. Skipping Firewall Rules
n A permissive firewall defeats the purpose of hardening. Deny by default and allow only needed ports.
6. Ignoring Package Updates
Unpatched software is an open invitation. Schedule regular updates and reboots.
7. Overly Permissive File Modes
World-writable files let attackers modify your site. Check and fix permissions regularly.
8. No Log Monitoring
Silence hides attacks. Watch logs and alert on anomalies.
9. Weak Application Passwords
Database and admin accounts need strong, unique passwords. Use a password manager or vault.
So What If the Port Is Open but SSH Still Refuses?
This is the classic chase. The port is open, the firewall allows traffic, but the connection drops. Check the SSH daemon config. Verify the port matches the client command. Ensure the service restarted after the edit. Look at /var/log/auth.log for auth failures. The issue is usually a config mismatch or a missing key, not the firewall.
What to Check First
Start with SSH and the firewall. These two settings block the most common attacks. Then move to updates, permissions, and monitoring. Fix the 9 mistakes, keep the checklist handy, and your Linux host will stay locked down.
