> ## Content Index
> Fetch the complete content index at: https://corti.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Hardening Internet-Facing Linux Servers: A Practical Security Guide
- URL: https://corti.com/hardening-internet-facing-linux-servers-a-practical-security-guide/
- Published: 2025-12-09T15:36:48.000Z
- Updated: 2025-12-09T15:36:48.000Z
- Author: Sascha Corti

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**

```bash
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**

```bash
sudo ufw allow 9022/tcp

```

More details on the UFW firewall later.

### **Step 3: Restart SSH (mandatory)**

```bash
sudo systemctl restart sshd

```

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

```bash
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.

```bash
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.

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

```

Manual fallback:

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

```

Permissions:

```bash
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).

```bash
ssh -p 9022 user@yourserver.com

```

To specify a non-default key, use:

```bash
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.

```bash
nano ~/.ssh/config

```

Example:

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

```

The login command now becomes:

```bash
ssh myserver

```

---

## **5\. Disable Root SSH Login and Password Authentication**

```bash
sudo nano /etc/ssh/sshd_config

```

Set:

```
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes

```

Restart SSH:

```bash
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**

```bash
sudo ufw default deny incoming
sudo ufw default allow outgoing

```

### **Allow workload-specific ports**

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

```

### **Enable UFW**

```bash
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**

```bash
sudo apt update
sudo apt install fail2ban

```

### **Configure jail overrides**

```bash
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**

```bash
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:

```bash
sudo apt install unattended-upgrades

```

### **Step 2: Enable unattended upgrades**

```bash
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:

```bash
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**

```bash
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.