Hardening Internet-Facing Linux Servers: A Practical Security Guide

Hardening Internet-Facing Linux Servers: A Practical Security Guide
Photo by Peter Conrad / Unsplash

Exposing a Linux server to the public Internet always introduces risk. Attackers constantly scan for open ports, weak SSH credentials, and unpatched services. With a few targeted configuration steps, you can significantly strengthen your security posture without increasing operational complexity.

This guide walks you through a practical baseline for securing Linux servers that are reachable from the Internet:

  • Move SSH from port 22 to port 9022
  • Use RSA SSH keys for authentication
  • Create an .ssh/config file for easier and more secure access
  • Disable root SSH login and disable password authentication
  • Configure UFW to expose only the ports you explicitly require
  • Install and configure fail2ban
  • Enable automatic security updates

All steps apply to Ubuntu 20.04 → 24.04 and most modern Debian-based distributions.


1. Move SSH from Port 22 to Port 9022 or any other Port you like

While not a primary security measure, shifting SSH away from the default port dramatically reduces bot-driven login attempts. It’s a simple and effective hardening step.

Step 1: Edit the SSH daemon config

sudo nano /etc/ssh/sshd_config

Find:

#Port 22

Uncomment it to:

Port 9022

Save and exit.

Step 2: Allow the new SSH port in UFW

sudo ufw allow 9022/tcp

More details on the UFW firewall later.

Step 3: Restart SSH (mandatory)

sudo systemctl restart sshd

Step 4: Test the new port before closing your existing session

ssh -p 9022 user@yourserver.com

Only continue once this works.


2. Create and Use an RSA Key Pair for SSH

Key-based authentication is significantly more secure than passwords and prevents brute-force attacks.

Step 1: Generate an RSA key pair on your client

To start, we need to create an RSA key.

ssh-keygen -t rsa -b 4096 -C "yourname@example.com"

This creates:

  • ~/.ssh/id_rsa → private key
  • ~/.ssh/id_rsa.pub → public key

Step 2: Copy your public key to the server

To enable this key on the server, you need to copy the public key to the ˜/.ssh/authorized_keys file of the user that needs to be able to log in to the server using the key and SSH.

ssh-copy-id -p 9022 user@yourserver.com

Manual fallback:

cat ~/.ssh/id_rsa.pub | ssh -p 9022 user@yourserver.com 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'

Permissions:

ssh -p 9022 user@yourserver.com "chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"

3. SSH Into the Server Using Your RSA Key

If you are using the default key name (id_rsa).

ssh -p 9022 user@yourserver.com

To specify a non-default key, use:

ssh -i ~/.ssh/custom_key -p 9022 user@yourserver.com

4. Create an .ssh/config File for Easier Logins

This makes using SSH to log in much easier as we don't have to specify the key, port, user and full host name when we want to connect to a remote host.

nano ~/.ssh/config

Example:

Host myserver
    HostName yourserver.com
    Port 9022
    User username
    IdentityFile ~/.ssh/id_rsa

The login command now becomes:

ssh myserver

5. Disable Root SSH Login and Password Authentication

sudo nano /etc/ssh/sshd_config

Set:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

Restart SSH:

sudo systemctl restart sshd

6. Configure UFW and Allow Only Required Ports

UFW is the built-in firewall for many Unix system. It's effective and easy to configure.

Default deny posture

sudo ufw default deny incoming
sudo ufw default allow outgoing

Allow workload-specific ports

sudo ufw allow 9022/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Enable UFW

sudo ufw enable
sudo ufw status verbose

7. Install, Enable, and Configure Fail2ban

Fail2ban stops users from repeatedly trying to log in by blacklisting them for a set amount of time before they can try to log in again. Fail2ban uses UFW rules to accomplish this.

Install

sudo apt update
sudo apt install fail2ban

Configure jail overrides

sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8

[sshd]
enabled = true
port = 9022
filter = sshd
logpath = /var/log/auth.log
maxretry = 4

Restart and verify

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

8. Enable Automatic Security Updates

Keeping your system updated is critical, especially for Internet-facing machines. Ubuntu includes unattended-upgrades, a service that automatically applies security patches.

Step 1: Install the required package

Most Ubuntu systems already have it, but ensure it’s installed:

sudo apt install unattended-upgrades

Step 2: Enable unattended upgrades

sudo dpkg-reconfigure --priority=low unattended-upgrades

This creates or updates /etc/apt/apt.conf.d/20auto-upgrades with:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

Step 3: Optional — Review or customize the update policy

Main config file:

sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

Key options:

  • Allow only security updates (recommended)
  • Automatically remove unused packages
  • Enable reboot if required (use with caution on production systems)

Step 4: Test it manually

sudo unattended-upgrade --dry-run --debug

This shows what would be applied without making changes.


Conclusion

Hardening Internet-facing Ubuntu servers doesn’t require complex tooling. By moving SSH to a nonstandard port, enforcing RSA key authentication, disabling root and password logins, configuring a strict firewall, installing fail2ban, and enabling automatic security updates, you eliminate the vast majority of attack vectors used by automated bots and low-effort attackers.

This setup provides a strong and reliable security baseline for any production or personal workload — and can be easily automated using Ansible, cloud-init, or shell scripts.