Cybersecurity

Linux Server Hardening Checklist: SSH, Firewall, Updates, Users and Logging

A production-safe Linux server hardening checklist covering SSH, firewall rules, updates, users, file permissions, logging, monitoring and verification. Follow the workflow without locking out administrators or overlooking cloud network controls.

Published 3 Oct 2026 · Digital Reality Studio
Linux Server Hardening Checklist: SSH, Firewall, Updates, Users and Logging

Linux server hardening checklist

A secure Linux server is not created by running one hardening script. It is created by reducing unnecessary exposure, limiting administrative access, applying updates, recording important activity and verifying that the controls continue to work.

This guide presents a practical baseline for Ubuntu and Debian-style servers, including many cloud VPS deployments. Some commands and configuration paths differ on Red Hat Enterprise Linux, Rocky Linux, AlmaLinux and other distributions, so check your distribution documentation before applying changes to production. The NIST Guide to General Server Security treats server security as a combination of access control, configuration management, maintenance, audit and accountability, incident response and system integrity—not as a single setting.

Important: make one change at a time, keep an existing administrative session open, and test a second session before closing the first. For remote servers, confirm that your hosting provider offers console, serial or recovery access before changing SSH or firewall settings.

1. Establish a safe change and rollback process

Before hardening the server, document how it is currently used. Record the operating system and release, public and private IP addresses, listening services, expected inbound ports, administrator accounts, backup status and cloud firewall rules.

cat /etc/os-release
uname -a
sudo ss -tulpen
systemctl --type=service --state=running

Save a copy of important configuration files before editing them.

sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.before-hardening
sudo cp -a /etc/default/ufw /etc/default/ufw.before-hardening

If the server hosts an application, record how to test it before making changes. A hardening change is not complete until you can verify both security and availability. Also confirm that backups are usable; a backup that has never been restored is an assumption, not a recovery plan.

2. Update the operating system and plan reboots

Install current security updates before changing other controls. On Ubuntu, the standard package workflow is:

sudo apt update
sudo apt upgrade
sudo apt autoremove

Ubuntu documents unattended-upgrades as the mechanism for automatically applying updates, with configuration in /etc/apt/apt.conf.d/ and logs under /var/log/unattended-upgrades/. Security updates are enabled by default on supported Ubuntu installations, but administrators should still verify the configuration and review failures rather than assuming updates succeeded.

sudo apt install unattended-upgrades
sudo systemctl status unattended-upgrades
sudo tail -n 100 /var/log/unattended-upgrades/unattended-upgrades.log

Check whether a reboot or service restart is required. Kernel and low-level library updates may not protect running processes until the affected service or system is restarted. On Ubuntu systems, needrestart can help identify processes using outdated libraries.

sudo needrestart

For production systems, define a maintenance window, test updates on a representative system where practical, and monitor whether critical services return successfully. Automatic updates reduce delay, but they do not replace inventory, testing, rollback planning or fleet-level reporting. The official Ubuntu automatic updates documentation explains repository selection, logging, reboot behavior and package exceptions.

3. Harden SSH without locking yourself out

SSH is often the main administrative entry point, so treat its configuration as a high-risk change. Create or confirm a named administrator account with the required privileges before restricting root or password access.

sudo adduser adminuser
sudo usermod -aG sudo adminuser

From your workstation, install and test a public key for that account. Do not disable password authentication until key-based login works in a separate terminal.

ssh-copy-id adminuser@server.example.com
ssh adminuser@server.example.com

Use a small configuration snippet rather than repeatedly editing the main file when your distribution supports /etc/ssh/sshd_config.d/. A reasonable baseline for a server managed with SSH keys may include:

sudo tee /etc/ssh/sshd_config.d/ hardening.conf > /dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AllowGroups sshlogin
X11Forwarding no
EOF

The exact settings should match your authentication design. For example, disabling password authentication can break environments that depend on passwords, directory services or emergency access methods. The OpenSSH configuration reference documents options such as PermitRootLogin, authentication methods and user restrictions.

Create an access group only after confirming that your intended administrator belongs to it:

sudo groupadd --system sshlogin
sudo usermod -aG sshlogin adminuser
id adminuser

Validate the configuration before reloading SSH:

sudo sshd -t
sudo systemctl reload ssh

Keep the original session open and test a new session:

ssh -o PreferredAuthentications=publickey adminuser@server.example.com

Ubuntu’s OpenSSH server documentation describes the supported configuration locations. Its user-management guidance also warns that locking a user password does not necessarily remove SSH access when authorized keys remain in the account’s .ssh/authorized_keys file. When removing access, review both account status and authorized keys.

4. Apply least privilege to users and sudo

Use individual named accounts instead of sharing root or a common administrator account. Individual accounts make access reviews, logging and offboarding more reliable. Remove unused accounts and review who has administrative privileges.

getent passwd
getent group sudo
sudo find /home -maxdepth 3 -type f -name authorized_keys -ls

For an account that should no longer log in, expire or lock it according to your operating procedure, then remove its SSH keys and review active sessions. Do not assume that locking a password alone removes key-based access.

sudo passwd --lock username
sudo chage -E 0 username
sudo pkill -u username

Review sudo rules in /etc/sudoers and /etc/sudoers.d/. Use visudo to validate edits because a syntax error can prevent administrative access.

sudo visudo
sudo find /etc/sudoers.d -type f -maxdepth 1 -ls

Grant only the commands and privileges required for a role. Avoid broad rules such as unrestricted access to every command unless there is a documented operational reason. Remember that some commands can launch shells or modify system files, so command-level restrictions require careful review.

5. Configure the host firewall and cloud firewall together

Start with an inventory of listening services, then permit only traffic that the server needs. On Ubuntu, ufw is the default simplified firewall management tool and supports IPv4 and IPv6 host-based rules.

sudo ufw status verbose
sudo ufw app list
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status numbered

Replace the example administrator address with a trusted management network, VPN range or other controlled source. Do not open SSH to the entire internet when a narrower source is practical. If administrators have changing addresses, consider VPN or identity-aware access rather than repeatedly widening the SSH rule.

Do not blindly copy the example rules. A database server may need no public database port; an internal application may need private-subnet access; and a web server may require only TCP 80 and 443 from a load balancer or internet-facing proxy. Confirm the actual service dependencies before denying traffic.

Cloud providers add another firewall layer. AWS security groups control inbound and outbound traffic for instances, while Azure network security groups contain inbound and outbound rules applied at the subnet or network-interface level. A connection may fail because of the cloud rule, the host firewall, routing, the service binding address or the application itself. Review both layers and test from the real source network. See the AWS security group documentation and Microsoft’s explanation of Azure network security groups.

6. Remove unnecessary software and services

Every installed service increases maintenance and attack-surface requirements. Remove packages that are not needed, disable services that should not start automatically and avoid exposing administration interfaces publicly.

sudo systemctl --type=service --state=running
sudo ss -tulpen
apt list --installed 2>/dev/null | less

For each listening port, identify the owning process and answer three questions: Is it required? Who should reach it? How is it authenticated and patched? If the answer is unclear, investigate before changing it.

sudo lsof -nP -iTCP -sTCP:LISTEN
sudo systemctl cat service-name

Do not stop an unfamiliar service solely because it sounds unnecessary. It may support networking, monitoring, backups or cloud integration. Use a maintenance window and document the rollback command when disabling services.

7. Protect files, secrets and application data

Review ownership and permissions on SSH keys, service configuration, backups, scripts and files containing credentials. Private keys should not be readable by unrelated users.

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
sudo find /etc -type f -perm /o+w -ls
sudo find /var/www -type f -name '*.env' -o -name '*secret*'

Use service accounts for applications instead of running every process as root. Give each service access only to the directories, sockets and network destinations it requires. Store secrets in a dedicated secrets-management system when practical, and prevent them from appearing in source repositories, shell history, process arguments and logs.

File permissions are not a substitute for encryption and backups. Protect backup credentials, restrict backup destinations and test restoration. A compromised server should not automatically provide unrestricted access to every backup copy.

8. Enable useful logging and make it durable

Logging should answer who accessed the server, what changed, which services failed and whether suspicious authentication activity occurred. At minimum, review SSH authentication, sudo activity, service logs, firewall events and update results.

sudo journalctl -u ssh --since today
sudo journalctl -p warning..alert --since today
sudo journalctl -u unattended-upgrades --since yesterday
sudo last
sudo lastb

journalctl reads logs collected by systemd-journald. If logs are stored only in volatile memory, they may disappear after reboot. Configure persistent journal storage according to your distribution’s policy and available disk space, then confirm that records survive a controlled restart.

sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald
journalctl --disk-usage
sudo journalctl --flush

The systemd journalctl documentation describes persistent journal directories and the --flush operation. Set retention and size limits so logging cannot consume the root filesystem. Forward important logs to a separate system or managed log service when possible. NIST notes that centralized logging can support analysis, retention and investigation because an attacker who controls one host should not be able to quietly erase every copy of its logs.

Protect log access and monitor for events such as repeated failed logins, unexpected new users, changes to sudo rules, disabled security services, unusual outbound connections and unexpected configuration changes. Automated blocking tools can help in some environments, but they should be tested carefully because aggressive bans can block legitimate administrators or shared networks.

9. Add verification, monitoring and maintenance

Hardening is a recurring operating process. Create a short verification routine and run it after changes, updates and deployments.

  • Confirm that only approved ports are listening with ss -tulpen.
  • Review host and cloud firewall rules for unintended public exposure.
  • Test SSH access from an approved administrator account and confirm that unauthorized methods fail.
  • Check that updates completed successfully and identify systems needing a reboot.
  • Review recent authentication, sudo and service logs.
  • Confirm monitoring and alert delivery by generating a safe test event.
  • Verify that backups completed and periodically perform a restoration test.
  • Recheck user, SSH-key and privileged-group membership during access reviews.

For larger environments, manage the baseline as code or through configuration management. Record exceptions with an owner, reason, compensating control and review date. This prevents temporary access rules and emergency changes from becoming permanent exposure.

10. A production-safe order of operations

  1. Confirm console or recovery access and create a tested administrator account.
  2. Back up configurations and document current services, ports and firewall rules.
  3. Apply operating-system updates and plan required restarts.
  4. Install and test SSH keys in a separate session.
  5. Restrict SSH users, disable unnecessary authentication methods and validate with sshd -t.
  6. Review cloud firewall rules before enabling or tightening the host firewall.
  7. Apply least privilege to users, sudo and service accounts.
  8. Remove unnecessary services and protect sensitive files.
  9. Configure persistent logs, retention and centralized forwarding.
  10. Test the application, administration path, alerts and recovery procedures.

The goal is not to make a server impossible to use. The goal is to make access intentional, changes observable and failures recoverable. Combine this Linux baseline with your wider small-business cybersecurity program, endpoint controls, ransomware-resistant backups and incident-response plan. Those controls address the situations in which a server is misconfigured, compromised or unavailable despite preventive hardening.