The Critical First 20 Minutes: Securing Your New VPS

Every self-hosted project, from personal blogs to production applications, begins with a new Virtual Private Server (VPS). The crucial difference between a secure, private environment and a compromised system lies in the initial setup—specifically, the first twenty minutes before any application is installed. A fresh server with a public IP address is immediately subjected to probes and attacks. Default configurations on most operating system images prioritize convenience over security, leaving your server vulnerable to everything from unauthorized access to becoming a node in a botnet.

This guide outlines the essential security baseline established on every new server. It’s the foundational security layer that ensures a robust starting point for any deployment, whether it's Docker, n8n, or any other self-hosted service. The commands provided have been verified against current Ubuntu LTS documentation, and critical steps requiring direct server interaction are clearly marked.

Creating a Non-Root User with Sudo Privileges

The most fundamental security principle is to avoid performing daily tasks as the root user. Root has unrestricted access to the entire system, and any mistake or exploit while operating as root can have catastrophic consequences. Instead, you should create a dedicated user account with elevated privileges granted through the `sudo` command.

First, log in to your VPS as the root user. Then, create a new user. Replace `your_username` with your desired username:

adduser your_username

This command creates the user and prompts you to set a password and provide some optional information about the user. It’s essential to choose a strong, unique password for this new account.

Next, you need to grant this new user `sudo` privileges. This allows the user to execute commands as root when prefixed with `sudo`. Add the new user to the `sudo` group:

usermod -aG sudo your_username

After adding the user to the `sudo` group, it is highly recommended to test the new user’s `sudo` capabilities. Log out of your root session and log back in using your newly created user account. Once logged in, try running a command that requires root privileges, such as updating the package list:

sudo apt update

If prompted for a password, enter the password for `your_username`. If the command executes successfully without errors, your `sudo` user is configured correctly.

Disabling Root Login via SSH

With a functional `sudo` user in place, the next critical step is to disable direct root login via SSH. This prevents attackers from targeting the well-known root account directly. You will manage administrative tasks using your `sudo` user.

You need to edit the SSH daemon configuration file. Open it with a text editor, such as `nano`:

sudo nano /etc/ssh/sshd_config

Locate the line that reads `PermitRootLogin yes` or `PermitRootLogin prohibit-password`. Change this line to:

PermitRootLogin no

If the `PermitRootLogin` directive is commented out (starts with a `#`), uncomment it by removing the `#` and set its value to `no`.

After saving the changes to the configuration file, you must restart the SSH service for the changes to take effect. The command to do this is:

sudo systemctl restart sshd

Crucially, before logging out, open a *new* terminal window and attempt to log in as your `sudo` user. Verify that you can successfully connect and execute `sudo` commands. Only after confirming that your non-root user can access the server and perform administrative tasks should you log out of the root session. This prevents you from locking yourself out of your server.

Configuring SSH Key-Based Authentication

Password-based SSH authentication is inherently less secure than using SSH keys. Keys are much harder to brute-force and eliminate the risk of compromised passwords. Setting up SSH key authentication involves generating a public/private key pair on your local machine and then placing the public key on the server.

On your local machine, generate an SSH key pair if you don’t already have one:

ssh-keygen -t rsa -b 4096

This command will prompt you to choose a location to save the key and to set a passphrase. A strong passphrase adds an extra layer of security. The command generates two files: `id_rsa` (your private key, keep this secret) and `id_rsa.pub` (your public key, which you will place on the server).

Next, copy your public key to the VPS. The easiest way is using the `ssh-copy-id` command:

ssh-copy-id your_username@your_vps_ip

Replace `your_username` and `your_vps_ip` accordingly. You will be prompted for your user’s password on the VPS. This command appends your public key to the `~/.ssh/authorized_keys` file on the server.

After copying the key, log in to your VPS using your `sudo` user and test SSH key authentication. You should be prompted for your SSH key passphrase (if you set one) instead of your user password. Once you confirm that key-based authentication works, you can further enhance security by disabling password authentication entirely. Edit the SSH configuration file again:

sudo nano /etc/ssh/sshd_config

Find or add the following lines:

PasswordAuthentication no
PubkeyAuthentication yes

Restart the SSH service after making these changes:

sudo systemctl restart sshd

As with disabling root login, test this change thoroughly by opening a new terminal session before logging out of your current one. Ensure you can still log in with your SSH key.

Configuring the Firewall (UFW)

A firewall is essential for controlling network traffic to and from your server, allowing only necessary ports to be open. Uncomplicated Firewall (UFW) is a user-friendly interface for managing `iptables` on Ubuntu.

First, ensure UFW is installed. It is usually pre-installed on Ubuntu:

sudo apt install ufw

Before enabling the firewall, you must explicitly allow SSH traffic. This is critical to avoid locking yourself out. Since SSH typically runs on port 22, you should allow it:

sudo ufw allow ssh

If you have changed the default SSH port, replace `ssh` with the specific port number (e.g., `sudo ufw allow 2222/tcp`).

Now, enable the firewall:

sudo ufw enable

You will be prompted to confirm. Once enabled, UFW will start on boot.

You can check the status of UFW and the rules that are active:

sudo ufw status

By default, UFW denies all incoming connections except those you explicitly allow. For a web server, you would typically allow HTTP (port 80) and HTTPS (port 443):

sudo ufw allow http
sudo ufw allow https

This setup provides a secure baseline, allowing only essential services like SSH, HTTP, and HTTPS to communicate with your server. Any other ports will be blocked by default.

Keeping Your System Updated

Software vulnerabilities are constantly discovered, and regular updates are the primary defense against them. A proactive approach to system updates is non-negotiable for maintaining a secure server.

You can update your package lists and upgrade installed packages with these commands:

sudo apt update
sudo apt upgrade -y

The `-y` flag automatically confirms any prompts during the upgrade process. While convenient, it’s generally recommended to review package upgrades before applying them in production environments.

For automated security updates, you can install the `unattended-upgrades` package:

sudo apt install unattended-upgrades

This package can be configured to automatically install security updates. To enable it, you typically edit the configuration file `/etc/apt/apt.conf.d/50unattended-upgrades` and ensure the relevant security repositories are uncommented. You also need to configure `/etc/apt/apt.conf.d/20auto-upgrades` to enable automatic updates and reboots if necessary. A common configuration for `20auto-upgrades` is:

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

This tells the system to update the package list daily and perform unattended upgrades daily.

Conclusion: A Proactive Security Stance

These initial steps—creating a non-root user, disabling root SSH login, implementing SSH key authentication, configuring a firewall, and establishing a regular update schedule—form the bedrock of a secure VPS. This twenty-minute investment transforms a generic server image into a hardened environment, significantly reducing its attack surface. It’s the essential preparation that allows you to deploy applications with confidence, knowing that your infrastructure is protected against common threats. This secure baseline is not an optional extra; it’s a prerequisite for any serious self-hosting endeavor.