🛠️ Tutorials · ⏱ 10 min read

Install and Secure an Ubuntu 24.04 VPS in 2026: The Complete A to Z Guide

Master your server with this 2026 guide to installing and hardening an Ubuntu 24.04 VPS. Covers SSH keys, root disablement, UFW, fail2ban, auto-updates, and essential security best practices with ready-to-copy commands.

S By Selfhostr Team · independent tests
Install and Secure an Ubuntu 24.04 VPS in 2026: The Complete A to Z Guide
ⓘ This article may contain affiliate links (no extra cost to you, it supports our tests). See the disclosure.
🐧
Ubuntu 24.04 LTS
OS Version
⏱️
30-45 min
Est. Time
💶
€4/mo
Min Cost

👍 What we like

  • Uses robust Ed25519 SSH key authentication instead of passwords
  • Disables direct root login to prevent brute-force attacks
  • Configures UFW firewall and fail2ban for anti-bruteforce protection
  • Includes automatic security updates for continuous hardening

👎 What to watch

  • Requires 30-45 minutes for initial setup and configuration
  • Complexity may be challenging for absolute beginners
  • Risk of lockout if SSH keys are not verified before disabling password auth
📑 Contents

You’ve just ordered your first VPS, the welcome email gives you an IP address and a root password, and then… you’re staring at an empty terminal. This is exactly where 90% of your server’s security is determined. A freshly installed Ubuntu VPS is exposed to the Internet within minutes: bots scan port 22 continuously and attempt thousands of connections per day. Leaving password authentication enabled with an accessible root account is leaving the door wide open.

In this guide, we will start with a pristine Ubuntu 24.04 LTS VPS and transform it into a hardened server, ready to host any service in production. Everything is explained, every command is exact and tested: creating a non-root user, SSH key authentication, disabling password and root login, UFW firewall, anti-bruteforce protection with fail2ban, and automatic security updates. Expect to spend 30 to 45 minutes the first time.

Prerequisites

Before starting, ensure you have:

  • A freshly provisioned Ubuntu 24.04 LTS VPS (a reliable provider like Hetzner starting at €4/month, or OVHcloud works perfectly). If you’re still hesitating, our comparison of the best VPS for self-hosting will help you choose.

  • The public IP address of your VPS and the initial root password (provided via email).

  • A terminal on your local machine: Terminal on macOS/Linux, or PowerShell / Windows Terminal on Windows (OpenSSH has been integrated since Windows 10).

  • 30 minutes of your time and a bit of rigor.

Throughout this tutorial, replace 203.0.113.10 with your server’s actual IP and selfhostr with your chosen username.

Step 1: First connection and system update

Connect for the first time as root using the password you received:


ssh root@203.0.113.10

Accept the server fingerprint (yes) then enter the password. You are now in the shell. Before doing anything else, update the system to fetch the latest security patches:


apt update && apt upgrade -y

If the kernel is updated, a reboot is required. Check with:


[ -f /var/run/reboot-required ] && echo "Reboot required" || echo "No reboot needed"

If a reboot is required, run reboot and reconnect after a minute.

Take this opportunity to set the server’s timezone and hostname:


timedatectl set-timezone Europe/Paris

hostnamectl set-hostname srv-selfhostr

Step 2: Create a non-root user with sudo

Working as root daily is bad practice: a single mistake can destroy the system, and a compromised service running as root gives the attacker full access. So, we create a dedicated user:


adduser selfhostr

Enter a strong password (this will serve as a safety net for sudo, not for SSH). The other fields (full name, etc.) can be left empty. Then, add this user to the sudo group:


usermod -aG sudo selfhostr

Verify that the user has the correct permissions:


groups selfhostr

The output must contain sudo. Do not close the root session just yet: we will first configure SSH keys and verify that we can connect with the new user.

Step 3: Generate and install an SSH key pair

Key-based authentication is infinitely more robust than a password. A modern Ed25519 key is impossible to brute-force within a reasonable timeframe.

On your local machine

Open a new local terminal (do not close the one connected to the VPS) and generate the key pair:


ssh-keygen -t ed25519 -C "selfhostr@$(hostname)" -f ~/.ssh/id_selfhostr

Accept the proposed location and, ideally, protect the key with a passphrase. You will get two files: id_selfhostr (private, never share it) and id_selfhostr.pub (public, to be placed on the server).

Copy the public key to the VPS

The simplest method, if available:


ssh-copy-id -i ~/.ssh/id_selfhostr.pub selfhostr@203.0.113.10

Enter the selfhostr user’s password. If ssh-copy-id is not available (notably on Windows), do it manually. On the server side (in the already open root session):


mkdir -p /home/selfhostr/.ssh

chmod 700 /home/selfhostr/.ssh

nano /home/selfhostr/.ssh/authorized_keys

Paste the content of your id_selfhostr.pub file, save (Ctrl+O, Enter, Ctrl+X), then set permissions:


chmod 600 /home/selfhostr/.ssh/authorized_keys

chown -R selfhostr:selfhostr /home/selfhostr/.ssh

Test key-based connection

Before disabling anything, open a new local terminal and test:


ssh -i ~/.ssh/id_selfhostr selfhostr@203.0.113.10

You should land in the shell without being asked for an SSH password (only the key’s passphrase, if set). If it works, the rest can be done safely. If it fails, do not touch the SSH config until key-based login is operational.

To make life easier, create an alias in ~/.ssh/config on your local machine:


Host selfhostr

    HostName 203.0.113.10

    User selfhostr

    IdentityFile ~/.ssh/id_selfhostr

    Port 22

You can then connect with a simple ssh selfhostr.

Step 4: Harden the SSH server configuration

This is the most important step. We will disable root login and password authentication. Logged in as selfhostr, edit the config via a dedicated file (Ubuntu 24.04 loads files from /etc/ssh/sshd_config.d/, which is cleaner than modifying the main file):


sudo nano /etc/ssh/sshd_config.d/99-hardening.conf

Paste the following content:


# Disables direct root login

PermitRootLogin no



# Disables password authentication (keys only)

PasswordAuthentication no

KbdInteractiveAuthentication no

ChallengeResponseAuthentication no



# Enables public key authentication

PubkeyAuthentication yes



# Limits attempts and sessions

MaxAuthTries 3

MaxSessions 5

LoginGraceTime 30



# Restricts access to the authorized user only

AllowUsers selfhostr

Save. Validate the syntax before restarting the service, otherwise you risk locking yourself out:


sudo sshd -t

If the command returns nothing, the config is valid. Reload SSH:


sudo systemctl restart ssh

Classic trap: Do not close your current session under any circumstances. Open a new terminal and test ssh selfhostr. If key-based login still works, you’re good. If you are locked out, you still have the old session open to fix it. Most providers also offer a VNC/KVM console as a fallback in case of total lockout.

Let’s verify that root is indeed denied (this command should fail quickly):


ssh root@203.0.113.10

You should get Permission denied (publickey). Perfect.

Step 5: Configure the UFW firewall

By default, all ports are potentially exposed. UFW (Uncomplicated Firewall) allows you to let through only what you need. The golden rule: block everything incoming, allow everything outgoing, then open only the necessary ports.


sudo ufw default deny incoming

sudo ufw default allow outgoing

Allow SSH before enabling the firewall (otherwise you cut off your own connection):


sudo ufw allow OpenSSH

If you plan to host a site or a reverse proxy, also open web traffic:


sudo ufw allow 80/tcp

sudo ufw allow 443/tcp

Enable the firewall and confirm with y:


sudo ufw enable

Check the status of the rules:


sudo ufw status verbose

You will get a list of open ports. Everything else is blocked incoming.

Security tip: If you want to further limit SSH bruteforce at the network level, sudo ufw limit OpenSSH temporarily blocks an IP that opens more than 6 connections in 30 seconds.

Step 6: Install fail2ban against bruteforce

Even with SSH keys, bots will continue to hammer your port 22 and pollute your logs. fail2ban monitors logs and automatically bans IPs that multiply failures.


sudo apt install -y fail2ban

Never modify jail.conf directly (it gets overwritten during updates). Create a jail.local file:


sudo nano /etc/fail2ban/jail.local

With this content:


[DEFAULT]

# Ban for 1 hour after 4 failures within a 10-minute window

bantime = 1h

findtime = 10m

maxretry = 4

# Never ban yourself (add your static IP if you have one)

ignoreip = 127.0.0.1/8 ::1



[sshd]

enabled = true

port = ssh

On Ubuntu 24.04, the default log backend is systemd, which is handled automatically. Enable and start the service:


sudo systemctl enable --now fail2ban

Verify that the SSH jail is active:


sudo fail2ban-client status sshd

You will see the number of currently banned IPs and the list. To unban an IP if needed:


sudo fail2ban-client set sshd unbanip 198.51.100.5

Step 7: Enable automatic security updates

An unpatched server is an easy target. The unattended-upgrades package automatically applies security patches.


sudo apt install -y unattended-upgrades

sudo dpkg-reconfigure -plow unattended-upgrades

Select Yes in the window that appears. To go further, check the configuration file:


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

Ensure that the security updates line is uncommented:


Unattended-Upgrade::Allowed-Origins {

    "${distro_id}:${distro_codename}-security";

    "${distro_id}ESMApps:${distro_codename}-apps-security";

    "${distro_id}ESM:${distro_codename}-infra-security";

};

Optionally, enable automatic reboot at night if a kernel patch requires it (only do this if a short planned downtime is not an issue):


Unattended-Upgrade::Automatic-Reboot "true";

Unattended-Upgrade::Automatic-Reboot-Time "04:00";

Run a dry test to verify everything works:


sudo unattended-upgrades --dry-run --debug

Step 8: Final hardening verification

Run a complete check. Here are the verifications that confirm your server is properly secured:


# SSH root login must be denied

sudo sshd -T | grep -E "permitrootlogin|passwordauthentication"

# Expected: permitrootlogin no / passwordauthentication no



# The firewall must be active

sudo ufw status | head -1

# Expected: Status: active



# fail2ban must be running

sudo systemctl is-active fail2ban

# Expected: active



# Auto-updates must be scheduled

systemctl is-enabled unattended-upgrades

# Expected: enabled

If all outputs match, your VPS is hardened according to 2026 best practices.

Best practices and advanced hardening

To go beyond the basic foundation:

  • Change the SSH port (from 22 to a high port like 49222) drastically reduces bot noise. This is security through obscurity, so it’s a complement, never a substitute for keys. Remember to update the UFW rule and the Port directive in the SSH config.

  • Disable IPv6 if you don’t use it, or remember to duplicate your UFW and fail2ban rules for IPv6.

  • SSH 2FA via Google Authenticator (libpam-google-authenticator) adds a TOTP layer for sensitive environments.

  • Regular snapshots with your provider: this is your safety net in case of a mistake. Combine them with off-site backups (see our restic tutorial below).

  • Monitor connections with sudo lastb (failures) and last (successes), and regularly audit /var/log/auth.log.

  • Principle of least privilege: every service you install next should run under its own user, never as root.

FAQ

Is it really necessary to disable password authentication?

Yes, absolutely. It is the measure with the most impact. As long as PasswordAuthentication yes is active, any bot can try to guess your password indefinitely. With Ed25519 keys, this attack becomes practically impossible. Simply keep a backup copy of your private key in a password manager or an encrypted vault.

I lost my SSH key, how do I reconnect?

Use the KVM/VNC rescue console provided by your host (Hetzner, OVH, etc. all offer one). Log in as root via this console, temporarily re-enable PasswordAuthentication yes or add a new public key to authorized_keys, then reload SSH. This is exactly why you should never lock yourself out without a Plan B.

Do UFW and fail2ban overlap?

No, they are complementary. UFW is a static firewall: it decides which ports are open or closed. fail2ban is dynamic: it analyzes application logs and temporarily bans IPs that misbehave on the ports you chose to open. Together, they cover both the attack surface and behavior.

Does this guide also apply to Debian 12?

95% yes. The apt, UFW, and fail2ban commands are identical. The main difference concerns SSH service management (the service name is ssh on both recent versions) and the fail2ban log backend. Adjust paths if necessary, the rest applies as is.

How much RAM do I need for a basic secure VPS?

Hardening itself consumes almost nothing: fail2ban, UFW, and unattended-upgrades fit within a few dozen MBs. A VPS with 1 or 2 GB of RAM is more than enough for the base. Size it based on the services you will host next. For an overview of affordable offers, check our selection of cheap VPS in 2026.

Your VPS is now a clean and secure foundation. The logical next step: set up a reverse proxy to expose your services cleanly over HTTPS, then implement automatic encrypted backups. To stay updated on vulnerabilities, new self-hosted services, and VPS deals, join our Telegram watch bot.

Tags: UbuntuVPSLinuxSecurityServer AdministrationDevOps

Related

🛠️ Tutorials

Self-Hosting Your Website in 2026: Complete Guide (VPS, Docker, HTTPS)

2026 technical guide to self-hosting on a VPS: choosing plans, Docker setup, Let's Encrypt HTTPS, security, and real costs. Compare self-hosting vs. cloud.

Read
🛠️ Tutorials

Build Your Own WireGuard VPN on a VPS in 2026: The Complete Guide

2026 tutorial on self-hosting a WireGuard VPN on a Linux VPS. Covers installation, key generation, server and client configuration (mobile, PC), routing, NAT, kill switch, and DNS. Includes exact commands and ready-to-use configs.

Read
🛠️ Tutorials

Hosting n8n on a VPS in 2026: Complete Self-Hosted Guide (Docker, HTTPS, Backups)

2026 technical guide to self-hosting n8n on a VPS using Docker Compose, HTTPS, and security best practices. Compare cloud vs on-premise costs to automate workflows without subscriptions.

Read