Hardening Ubuntu Server After Install

13 min read 2,437 words
Securing Your Ubuntu Server After a Fresh Install featured image

Why the First 30 Minutes on a New Server Matter

A freshly installed Ubuntu server on a VPS or cloud instance is functional out of the box, but it is not secure by default. The default settings are well-documented, meaning attackers know exactly what to look for. Open SSH ports running on the standard port, root login enabled, and no firewall rules in place are all common attack vectors that automated bots scan for constantly.

Hardening a new server does not require advanced knowledge, but it does require knowing which steps matter most and in what order to apply them. Skipping steps or applying them in the wrong sequence can leave gaps. This guide walks through the essential hardening tasks that apply to any Ubuntu server exposed to the internet, whether it is a VPS, cloud instance, or physical server.

Creating a Non-Root User for Daily Administration

Logging in as root gives you unrestricted access to everything on the system, including the ability to accidentally delete critical files or change settings that break the server. Best practice is to create a regular user with sudo privileges and use that account for day-to-day administration.

adduser deploy
usermod -aG sudo deploy

The deploy user can now run administrative commands by prefixing them with sudo. Before relying on sudo for critical tasks, test that it works correctly:

su - deploy
sudo ls /root

If ls displays the contents of /root without errors, sudo is configured properly for that user. You should also set up key-based authentication for this account to avoid using passwords for SSH connections.

Choose a username that does not immediately reveal the purpose of the account. Names like admin, server, or ubuntu are common targets because attackers know administrators often use predictable usernames. A less obvious username adds a small but meaningful layer of obscurity.

Setting Up SSH Key-Based Authentication

Key-based authentication is more secure than password authentication because it cannot be brute-forced in the same way. The cryptographic strength of modern SSH keys makes them significantly harder to crack than even strong passwords. Create the required directory structure and set appropriate permissions:

mkdir ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Copy your public key to the server using ssh-copy-id or by manually appending the key content to ~/.ssh/authorized_keys. The ssh-copy-id method is simpler:

ssh-copy-id -p 2222 deploy@your_server_ip

Once key-based authentication is confirmed to work, you can disable password authentication entirely in the SSH daemon configuration. Test the key login first by opening a new terminal session and connecting with the key. Only disable passwords after confirming the key works.

Hardening the SSH Daemon Configuration

The SSH configuration file at /etc/ssh/sshd_config controls how users can connect to the server. Open it with a text editor:

sudo nano /etc/ssh/sshd_config

Apply these settings to strengthen the default configuration:

Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
X11Forwarding no
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2

Changing the SSH port from 22 to something less common like 2222 does not provide true security, but it significantly reduces automated bot traffic since most bots scan only port 22 by default. Think of it as noise reduction rather than a security measure on its own.

The MaxAuthTries 3 setting disconnects after three failed authentication attempts, which helps protect against brute force attempts. The ClientAliveInterval and ClientAliveCountMax settings work together to close idle connections after 10 minutes, preventing resource exhaustion from forgotten sessions left open.

After saving the configuration, always test it before restarting the service:

sudo sshd -t

If no errors are reported, reload the SSH configuration:

sudo systemctl reload sshd

Keep your existing SSH session open and test the new configuration in a separate terminal before logging out. If the new settings break SSH access somehow, your existing session lets you fix the problem without losing connectivity to the server.

For a deeper walkthrough of SSH hardening techniques, including additional configuration options and key setup, see the guide on securing SSH on Ubuntu.

Configuring the Firewall with UFW

Ubuntu includes UFW (Uncomplicated Firewall), which provides a simplified interface to manage iptables rules. Before enabling the firewall, make sure you allow SSH on the new port to avoid locking yourself out:

sudo ufw allow 2222/tcp
sudo ufw allow 'Apache Full'
sudo ufw enable

If you are running other services such as mail servers, databases on non-standard ports, or custom applications, allow their respective ports before enabling the firewall. Run sudo ufw status numbered to see all rules in order with their line numbers. This numbering is useful when you need to delete specific rules later.

UFW's default policy already sets default-deny for incoming connections, which is the recommended setting for servers. This means any port not explicitly allowed will be blocked automatically. If you need to allow HTTP traffic on port 80, for example, run sudo ufw allow 80/tcp.

Review your rules before and after enabling the firewall. A common mistake is forgetting to allow a service you need, which can cause applications to appear broken until you realise the firewall is blocking them.

Installing and Configuring Fail2Ban

Fail2Ban monitors log files and automatically bans IP addresses that repeatedly fail authentication. It is particularly effective against brute force attacks on SSH and web services. Install it first:

sudo apt install fail2ban -y

The default configuration works, but you should copy the configuration file to a local override file so your settings are not overwritten when the package receives updates:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

Update the SSH jail to use your custom port and adjust the ban settings to suit your environment:

[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600

The bantime value sets the ban duration in seconds, so 3600 equals one hour. For more detailed Fail2Ban configuration including HTTP protection and custom filter settings, the guide on setting up Fail2Ban on Ubuntu covers additional options.

Start and enable the service:

sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Check the current status:

sudo fail2ban-client status

You should see output showing the SSH jail with a count of currently banned IPs. If you see 0 banned IPs initially, that is normal on a freshly hardened server. The count will increase as automated scanners attempt to connect.

Enabling Automatic Security Updates

Security patches are released regularly, and applying them manually is easy to forget, especially if you manage multiple servers. Ubuntu can install security updates automatically without requiring your attention each time.

sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure unattended-upgrades

Choose Yes when prompted to enable automatic updates. The configuration is stored in /etc/apt/apt.conf.d/50unattended-upgrades. Verify the setup is working:

sudo unattended-upgrades --dry-run

For servers where you want to receive notifications when updates are applied, configure email alerts in the unattended-upgrades configuration file. This is particularly useful for production environments where knowing what changed matters for auditing purposes. Add an email address to the configuration file under the Unattended-Upgrade::Mail setting.

Disabling Unnecessary Services

A default Ubuntu server installation includes services you may not need. Each running service represents a potential attack surface. Check what is currently running:

systemctl list-units --type=service --state=running

Review the list and disable services you do not use. Common services to check on a web server include:

  • CUPS: The print server. Unless you are printing directly from the server, it should not be running.
  • Bluetooth: Not needed on a headless server.
  • Avahi: Service discovery daemon. Useful on local networks but unnecessary on public servers.
  • atd: The at scheduling daemon. Disable if you do not use it.

Stop and disable a service with:

sudo systemctl stop cups
sudo systemctl disable cups

After disabling a service, verify it is no longer listening on any ports by running sudo ss -tulpn again. Services sometimes have dependencies, so test that your server continues to function normally after disabling them.

Configuring Swap Space

Swap is disk space used as virtual memory when physical RAM is full. Without swap configured, a server under memory pressure can trigger the Linux Out of Memory Killer, which arbitrarily terminates processes to free up memory. This can kill critical services without warning. Check if swap is already configured:

sudo swapon --show

If no swap is shown, create a swap file:

sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

Make the swap file permanent by adding it to /etc/fstab:

echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Set the swappiness value to control how aggressively the kernel uses swap. A value of 10 means the kernel swaps only when RAM usage reaches approximately 90%:

echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf

The appropriate swappiness value depends on your workload. Database servers often benefit from lower swappiness to keep data in RAM, while servers running multiple applications may prefer a higher value to avoid running out of memory unexpectedly.

Hardening System Kernel Parameters

The Linux kernel controls network behaviour and memory management at a low level. Edit /etc/sysctl.conf to add network hardening settings:

sudo nano /etc/sysctl.conf

Add these settings to improve the server's resistance to common network-based attacks:

# IP spoofing protection
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1

# Do not accept IP source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

# Ignore ICMP redirects
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0

# Ignore send redirects
net.ipv4.conf.all.send_redirects = 0

# Log suspicious packets
net.ipv4.conf.all.log_martians = 1

Apply the changes without rebooting:

sudo sysctl -p

These settings prevent IP spoofing, disable source routing, and log suspicious packets. They represent standard hardening practices for any publicly accessible server. For a more comprehensive look at Ubuntu server hardening, the guide on Ubuntu 22.04 security hardening covers additional steps worth considering.

Verifying the Hardened Configuration

After completing the hardening steps, verify the server is in a defensible state before considering it ready for production use:

sudo ufw status
sudo systemctl status fail2ban
sudo ss -tulpn | grep LISTEN

The ufw status command shows all active firewall rules. The fail2ban status confirms the service is running and monitoring for suspicious activity. The ss command lists all listening ports and the services associated with them.

Review the output carefully. Confirm only the ports you expect to be open are actually listening. Any unexpected listening service should be investigated. Either disable it if it is unnecessary, or secure it properly if it is required for your setup.

A useful checklist approach to hardening verification is available in the Ubuntu server hardening checklist, which covers the key configuration points to verify after initial setup.

Next Steps After Hardening

Hardening the server is only part of maintaining a secure environment. Once the initial setup is complete, ongoing maintenance becomes the priority. This includes monitoring logs regularly, testing backups, and reviewing access controls when team members join or leave.

If you are running a web server alongside these hardening steps, Apache security configuration also deserves attention. The guide on securing Apache HTTPd settings covers additional steps for protecting web services specifically.

Backups should be tested regularly. A backup that has never been verified may fail when you need it most. Schedule time to test restore procedures on a regular basis.

Consider setting up log monitoring or a centralised logging solution if you manage multiple servers. Reviewing logs manually on a single server is manageable, but becomes time-consuming as your infrastructure grows.

Frequently Asked Questions

How long does server hardening take on a new Ubuntu installation?
For someone familiar with Linux administration, the steps in this guide typically take 20 to 40 minutes. If you are new to server administration, budget closer to an hour to work through each step carefully and test the configuration.
Can I skip changing the SSH port?
Yes, changing the SSH port is optional. It reduces automated bot traffic but does not provide real security on its own. If you choose not to change it, ensure Fail2Ban and key-based authentication are properly configured instead.
Should I apply all hardening steps in this order?
The order matters primarily for SSH and the firewall. You must allow SSH on your chosen port before enabling the firewall, otherwise you risk locking yourself out of the server. The other steps can be applied in any order after that.
What if I lock myself out after changing SSH settings?
If you are using a VPS or cloud instance, most providers offer a console access method through their control panel that bypasses SSH entirely. This lets you correct the configuration and regain access. Always keep an active SSH session open when testing new configurations until you have confirmed everything works.
Do I need to repeat these steps after every server reboot?
No. Most settings applied through sysctl.conf, /etc/fstab, and systemd services persist across reboots. The exception is any temporary change made directly through the sysctl command without editing the configuration file, which would be lost on reboot.
How often should I review and update server hardening settings?
Review your server configuration whenever Ubuntu releases major updates, when you add new services, or when you notice unusual activity in your logs. Security best practices evolve over time, so periodic reviews help ensure your setup reflects current recommendations.
Is Fail2Ban enough to stop all brute force attacks?
Fail2Ban is effective against automated brute force attempts because it dynamically bans IPs that fail authentication repeatedly. However, it works best as one layer of a broader security approach. Combining Fail2Ban with key-based authentication, a properly configured firewall, and regular log monitoring provides more robust protection than relying on any single tool.
What is the most common mistake during server hardening?
The most common mistake is enabling the firewall before confirming SSH access works on the new configuration. This locks administrators out of their own servers. Always test SSH connectivity with your new settings before running sudo ufw enable.
Do I need to harden a server that is only accessible internally?
Even servers on private networks benefit from hardening. Internal servers can be compromised through vulnerable services, misconfigured access controls, or compromised credentials. Applying baseline hardening ensures consistency and reduces risk if the server's network exposure changes.