Skip to content
MetaCode Innovations

Linux Server Hardening Checklist: 15 Steps for a New Server

A practical Linux server hardening checklist for Ubuntu and Debian: SSH, firewall, updates, Fail2ban, users, services, logging, backups and monitoring, with the commands for each step.

By Muhammad Ammar, Founder & Lead EngineerUpdated 5 min read
Security operations dashboard on a monitor

A new server on a public IP address gets its first SSH login attempts within minutes. Most of them are automated and simple, so a few basic steps stop nearly all of them. This checklist is the baseline we apply to every Linux server we manage, in the order we do it.

The commands are for Ubuntu and Debian. Run them as a user with sudo.

Before you start

Keep a second SSH session open while you change SSH or firewall settings. If a change locks you out, you can still fix it from the open session. Most cloud providers also offer a web console as a last resort.

1. Update everything

sudo apt update && sudo apt full-upgrade -y
sudo reboot

Reboot if the kernel was updated. A server running an old kernel is still exposed to the bugs the update fixed.

2. Create a named admin user

Don't work as root. A named user makes the logs show who did what, and lets you remove one person's access without touching anyone else's.

sudo adduser alice
sudo usermod -aG sudo alice

3. Use SSH keys, then turn off passwords

On your own computer, create a key if you don't have one and copy it to the server:

ssh-keygen -t ed25519 -C "alice@company"
ssh-copy-id alice@203.0.113.10

Log in with the key in a new terminal to confirm it works. Then create /etc/ssh/sshd_config.d/10-hardening.conf on the server:

PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LoginGraceTime 30
X11Forwarding no
AllowUsers alice

Check the config and reload SSH:

sudo sshd -t && sudo systemctl reload ssh

sshd -t prints nothing when the config is valid. Test a new login before you close your current session.

4. Turn on a default-deny firewall

Allow only what the server actually serves. For a web server:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80,443/tcp
sudo ufw enable
sudo ufw status verbose

If only your office or VPN needs SSH, limit it to that address with sudo ufw allow from 198.51.100.7 to any port 22 proto tcp, then delete the general OpenSSH rule.

Your cloud provider's firewall (AWS security groups, DigitalOcean or Hetzner cloud firewalls) adds a second layer in front of the server. Use both.

5. Install automatic security updates

sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure --priority=low unattended-upgrades

This installs security patches every day. To reboot automatically at a quiet hour when an update needs it, set these in /etc/apt/apt.conf.d/50unattended-upgrades:

Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";

6. Block brute-force attempts with Fail2ban

sudo apt install fail2ban -y

Create /etc/fail2ban/jail.local:

[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5

[sshd]
enabled = true
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

Add jails for Nginx, Postfix or your application's login page once those are installed.

7. Remove services you don't use

List everything listening on a network port:

sudo ss -tulpn

Each line should be something you can explain. Stop and disable the rest, for example:

sudo systemctl disable --now cups

Databases such as MySQL, PostgreSQL and Redis should listen on 127.0.0.1 only, unless another server needs to reach them over a private network.

8. Check sudo access and accounts

getent group sudo
sudo awk -F: '$3 == 0 {print $1}' /etc/passwd

The first command lists who can use sudo. The second must print only root; any other account with user ID 0 has full root access. Lock accounts that shouldn't log in with sudo usermod -L username.

9. Secure shared memory and temporary files

Stop programs being run from /tmp and /dev/shm, a common trick in web exploits. Add to /etc/fstab:

tmpfs /dev/shm tmpfs defaults,noexec,nosuid,nodev 0 0

Then run sudo mount -o remount /dev/shm. If /tmp is a separate partition, mount it with the same options. Test your application afterwards: a few installers expect to run scripts from /tmp.

10. Apply safe kernel network settings

Create /etc/sysctl.d/99-hardening.conf:

net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
fs.protected_hardlinks = 1
fs.protected_symlinks = 1

Load it with sudo sysctl --system. Leave out the rp_filter line on servers that route traffic, such as VPN gateways.

11. Keep time in sync

Logs, TLS certificates and two-factor codes all depend on the correct time.

timedatectl status

Check that it shows System clock synchronized: yes. If not, run sudo timedatectl set-ntp true.

12. Keep logs, and keep them somewhere else

Logs on a hacked server can be deleted by the attacker. Make the system journal persistent, and send copies to a separate log service or server:

sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald

For a record of who ran what and which sensitive files changed, install auditd. To read failed logins quickly:

sudo journalctl -u ssh --since "24 hours ago" | grep -i "failed"

13. Watch for file changes

A file integrity checker records a fingerprint of system files and reports when one changes. AIDE is the standard tool:

sudo apt install aide -y
sudo aideinit

Run it daily from cron and email the report. On web servers, also watch the website folders for new PHP files, which is how most web shells arrive.

14. Take backups you have tested

Back up the data and the configuration (/etc, web server and database config), not just the website files. Store at least one copy off the server and outside the same cloud account, so one compromised login can't delete both.

A backup you have never restored is a guess. Restore to a test server at least once a quarter.

15. Monitor the server

At a minimum, get alerts for:

  • the server or website going down
  • disk space above 80%
  • sustained high CPU or memory usage
  • failed SSH logins and Fail2ban bans
  • changes to system files or new admin users

Alerts only help if someone reads them, including at night and at weekends.

Check your work

Run a free audit tool to catch anything you missed:

sudo apt install lynis -y
sudo lynis audit system

Lynis prints a hardening index and a list of suggestions. Not every suggestion fits every server, so read them rather than applying them all.

When to bring in help

The checklist is the starting point. Keeping it in place is the harder part: updates that need a reboot, new users, expiring certificates, and alerts at 3 a.m. That is the work our Linux server management plans cover, with 24/7 security monitoring for failed logins, file changes and malware.

Frequently Asked Questions

How soon after creating a server should I harden it?
Immediately. Automated scanners find new public IP addresses within minutes and start trying SSH passwords straight away. Do steps 1 to 5 of this checklist before you install your application.
Is changing the SSH port worth it?
It cuts the noise from automated scans in your logs, but it isn't real protection: a targeted attacker will find the new port in seconds. Key-only login and Fail2ban matter far more. If you do change the port, open the new one in the firewall before restarting SSH.
Does this checklist work for CentOS, Rocky or AlmaLinux?
The steps are the same, but some tools differ. Use dnf instead of apt, firewalld instead of UFW, dnf-automatic instead of unattended-upgrades, and keep SELinux in enforcing mode rather than disabling it.
Do I need antivirus on a Linux server?
Not usually for the server itself. It is useful if the server stores files uploaded by users or hosts websites, where a scanner such as ClamAV or a malware scanner for PHP can catch infected uploads and web shells.
How often should I review a hardened server?
Updates should apply automatically every day. Review users, open ports, SSH keys and firewall rules at least once a quarter, and after anyone with access leaves the team.

Muhammad Ammar

Founder & Lead Engineer, MetaCode Innovations

Muhammad Ammar is the founder of MetaCode Innovations. He is a DevOps and Linux engineer with 4+ years of hands-on work running production servers, control panels, AWS and container platforms, and holds the EC-Council Certified SOC Analyst credential.

Let an Engineer Handle It.

Describe what is happening and send the address. We will reply with next steps and a quote.