Skip to main content

Command Palette

Search for a command to run...

My Journey to Self-Hosting: Part 2 - Securing the Server

Updated
6 min read
My Journey to Self-Hosting: Part 2 - Securing the Server
N
I'm a Full-Stack Web Developer and enthusiastic nature photographer from Switzerland.

In the last article, I se tup Infomaniak's VPS Lite server and logged in via SSH. The server is up and running, but a brand-new sever is like an open front door, anyone can try to enter. In this second part, I'll walk you through, step by step, how I secure the system.

Updates

The first thing I do after logging in is make sure all packages are up to date:

sudo apt update
sudo apt upgrade

apt update updates the list of available packages and apt upgrade installs the latest versions.

It is important to pay attention to the messages in the terminal, as shown in this example:

Diagnostics:
  The currently running kernel version is not the expected kernel version
6.8.0-124-generic.

Restarting the system to load the new kernel will not be handled automatically,
so you should consider rebooting.

If such a kernel update is pending (an update to the core of the operating system), the server must be restarted:

sudo reboot

Automatic Security Updates

To avoid having to install important updates manually all the time, I'll set up automatic security updates:

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

dpkg-reconfigure reopens the unattended-upgrades configuration. Using --priority=low displays all configuration prompts, including the simple ones, so I can explicitly confirm each step. When prompted, I select Yes, after which security updates are automatically installed in the background.

Disable Password Login

By default, SSH login with a password is enabled. This means bots can constantly try to log in using different passwords. To see how many failed attempts there have been so far, you can check the server's log files. On Ubuntu, there are two ways to do this:

# Option 1
sudo grep "Failed password" /var/log/auth.log | wc -l

# Option 2
sudo journalctl -u ssh --no-pager | grep "Failed password" | wc -l

Since I have already set up an SSH key, I am completely disabling password-based login to prevent such attempts in the future:

sudo nano /etc/ssh/sshd_config

this command opens the sshd_config configuration file in the selected text editor (nano) so that I can edit it. Many lines in the file are commented out with #, which means they are ignored and the default value is used. To change a setting, you must remove the # and adjust the value.

So I search the file for the line PasswordAuthentication, remove the #, and set it to no. It then looks like this:

PasswordAuthentication no

Then just save and confirm (Ctrl+XYEnter on a Mac).

Since the changes to the configuration file don't take effect until the service is restarted, I'll do that right away:

sudo systemctl restart ssh

Firewall (UFW)

The next step is to set up a firewall. UFW (Uncomplicated Firewall) is a tool in Ubuntu that controls network traffic, meaning which connections are allowed and which are blocked.

Without a firewall, all of the server's ports are open and accessible. With UFW, you can explicitly specify that only SSH is allowed, everything else is blocked:

sudo ufw allow ssh
sudo ufw enable

Important: Be sure to run sudo ufw allow ssh first, otherwise you'll lock yourself out 😉

With this command you can check whether UFW is running correctly:

sudo ufw status

Fail2ban

Even when passwords are disabled, bots continue to hammer away at my server's digital door. The "Fail2ban" program monitors log files for failed login attempts and blocks the attackers' IP addresses.

Use this command to install it:

sudo apt install fail2ban

With this command you can check whether Fail2ban has been enabled (use q to exit the view):

sudo systemctl status fail2ban

If it is not yet enabled, enable it as follows:

sudo systemctl start fail2ban
sudo systemctl enable fail2ban

By default Fail2ban protects SSH access on port 22 immediately after installation using the default settings. However, for optimal protection, I should make additional adjustments:

  • Create a custom configuration file

  • Adjust the most important settings

  • Check SSH protection or enable it explicitly

The main configuration file /etc/fail2ban/jail.conf is overwritten during updates, so you should never modify it. Instead, create your own file named jail.local. This file will then take precedence and remain intact during updates.

First I'll copy the original configuration file so I don't have to start my own file from scratch:

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

Now I'll open the file and change the most iportant values:

sudo nano /etc/fail2ban/jail.local

ignoreip

ignoreip = 127.0.0.1/8 ::1 MY_IP

ignoreip is commented out by default. I remove the # and add my IP address at the end, which prevents me from ever accidentally locking myself out. If you don't know your IP address, you can easily find it by entering the command curl ifconfig.me in a separate terminal.

bantime

bantime = 1d

Since modern attack bots are patient, they wait briefly and then continue indefinitely. A one day block immediately stops the attack and also reduces the number of firewall operations, since each block and unblock rewrites the firewall rules.

findtime

findtime = 10m

The time window during which failed attempts are counted. 10 minutes is a good average, short enough to detect actual attacks and long enough not to prenalize accidental typos.

maxretry

maxretry = 3

A legimitate user might make a typo once or twice, if there are more than three, that suggest an attacker.

sshd

I need to make the final change in the sshd section of the file. I add the line enable = true right above the line port = ssh. The finished block then looks like this:

enable  = true
port    = ssh
logpath = %(sshd_log)s
backend = %(sshd_backend)s

Then save and confirm (Ctrl+XYEnter on a Mac) and restart Fail2ban:

sudo systemctl restart fail2ban

With this last command, I can check whether Fail2ban is running correctly and monitoring SSH:

sudo fail2ban-client status sshd

Disable Root Login

The root user exists on every Linux system and has unrestricted privileges across the entire system. Attackers are therefore already familiar with this username and often attempt to log in directly as root.

Although Infomaniak blocks direct logins as the root user by default for security reasons, I still explicitly disable this option in the server's SSH configuration file:

sudo nano /etc/ssh/sshd_config

From:

#PermitRootLogin prohibit-password

To:

PermitRootLogin no

Now restart SSH so that the change takes effect:

sudo systemctl restart ssh

What's next?

The server is now basically secure, though not yet perfect. There are additional steps, such as changing the SSH port, but I'll cover those at a later time.

In the next part, I'll install Docker, which will allow me to run applications in isolated containers.

My Journey to Self-Hosting

Part 2 of 2

This blog series chronicles my journey to self-hosting. I’ll show you how I set up, secure, and configure an affordable Swiss VPS Lite so that I can run as many apps and websites as I want on it simultaneously.

Start from the beginning

My Journey to Self-Hosting: Part 1 - VPS and SSH Key

This article is also available in German (Deutsch). If you develop several small web apps and hobby projects, you’ll quickly run into a financial problem: if you pay for separate hosting or a PaaS (Pl

More from this blog

N

Nathalie's Notebook

2 posts

Welcome to my learning notebook! This is where I document my personal insights, step-by-step guides, and clear explanations. My goal is to share knowledge structurally and break down complex topics into simple terms.