Skip to content
Server Setup #VPS #Linux #Ubuntu

New Ubuntu 26.04 VPS? The First-Hour Setup Checklist (and What Changed Since 24.04)

Everything to do in the first hour on a fresh Ubuntu 26.04 LTS server, in order: a sudo user, SSH keys, the firewall, automatic security updates, swap and time sync, plus the 26.04 changes (sudo-rs, OpenSSH 10, apt-key removal) that trip up old setup scripts.

A fresh VPS is at its most exposed in the first hour. It has a public IP, root login, and often password authentication switched on, and bots start trying passwords within minutes of it booting. This checklist is the order I work through on every new server, updated for Ubuntu 26.04 LTS, which changed enough under the hood that a setup script written for 24.04 can fail in confusing ways.

Each step links to a longer guide if you want the details. If you only have ten minutes, do steps 1 to 4 now and the rest later today.

Before you start: what is different on 26.04

If you are reusing notes or a script from an older Ubuntu, these are the changes most likely to bite:

  • sudo is now sudo-rs. Most rules work as before, but wildcards inside command arguments are rejected. See why your sudoers rule stopped working.
  • OpenSSH 10.2. DSA keys are gone, post-quantum key exchange is preferred, and PerSourcePenalties is on by default, which temporarily blocks addresses that keep failing to log in. That includes your own CI runner if its key is wrong.
  • apt-key is removed. Any install guide that says curl … | apt-key add - will fail. Third-party repositories need a key file in /etc/apt/keyrings/ and a Signed-By: line.
  • chrony replaces systemd-timesyncd on fresh installs, and some everyday commands (ls, sort, date) are now the Rust rewrites from uutils. Scripts that parse their exact output can behave differently.
  • PHP 8.5, MySQL 8.4 and Nginx 1.28 are the versions in the archive. /tmp is now a tmpfs, so it lives in RAM and is wiped on reboot.

1. Log in and update everything

Log in as root (or the default user your provider created) and bring the system up to date before installing anything:

apt update && apt full-upgrade -y
reboot

Rebooting now picks up a new kernel while nothing important is running yet.

2. Create your own user with sudo

adduser deploy
usermod -aG sudo deploy

Pick any name you like. You will use this account from now on, and turn off root login in the next step. Check that sudo works before you go further:

su - deploy
sudo whoami   # should print: root

On 26.04 the password prompt now reads [sudo: authenticate] Password:. That is sudo-rs, and it is expected.

3. Switch to SSH keys and turn off passwords

From your own computer, copy your public key to the new user:

ssh-copy-id deploy@YOUR_SERVER_IP

Open a second terminal and confirm you can log in as deploy with the key. Only then disable password logins and root login. Put your settings in a drop-in file so a package update never overwrites them:

sudo tee /etc/ssh/sshd_config.d/00-hardening.conf >/dev/null <<'EOF'
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
EOF
sudo sshd -t && sudo systemctl reload ssh

The file name starts with 00- on purpose. OpenSSH uses the first value it reads for each setting, and many cloud images ship a 50-cloud-init.conf that turns passwords back on. Our guide to disabling SSH password login so it actually sticks explains this trap in full.

Thinking of moving SSH to another port? On Ubuntu 24.04 and later, SSH is started by a systemd socket, so changing Port in the config is not enough on its own. You also need sudo systemctl daemon-reload && sudo systemctl restart ssh.socket. Personally I would skip the port change and put SSH behind Tailscale instead of port 22.

4. Turn on the firewall without locking yourself out

sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

Allow SSH before enabling the firewall. Getting the order wrong is the most common way people lock themselves out of a new server; here is how to recover if it happens.

If you will run Docker, read this next: Docker ignores UFW rules for published ports. A database container started with -p 3306:3306 is open to the internet even with UFW enabled.

5. Make sure security updates install themselves

Ubuntu Server ships with unattended-upgrades, which installs security updates daily. Don't assume your provider's image left it on. Check:

systemctl status unattended-upgrades
cat /etc/apt/apt.conf.d/20auto-upgrades

You want both lines set to "1":

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

If the file is missing, sudo dpkg-reconfigure -plow unattended-upgrades creates it.

Kernel and library updates only take full effect after a reboot. If you would rather the server reboot itself at a quiet hour than remember to do it, add an override file:

sudo tee /etc/apt/apt.conf.d/52reboot >/dev/null <<'EOF'
Unattended-Upgrade::Automatic-Reboot "true";
Unattended-Upgrade::Automatic-Reboot-Time "04:00";
EOF

Only do this if your apps come back by themselves after a reboot: services enabled in systemd, containers with a restart policy, and queue workers under Supervisor or systemd.

6. Set the time zone and check the clock

sudo timedatectl set-timezone UTC
timedatectl

I keep servers on UTC and convert in the application; it makes logs from several servers line up. Check that System clock synchronized: yes appears. On a fresh 26.04 install that is chrony's job; chronyc tracking shows the details.

The time zone matters for scheduled jobs. If you write cron schedules, our Cron Expression Generator shows when an expression will next run, so you can check it against the server's clock.

7. Add swap on small servers

On a 1 or 2 GB VPS, a swap file is the difference between a slow moment and MySQL being killed by the out-of-memory killer during a traffic spike or a composer install:

sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

Our swap guide covers sizing and swappiness, and how to find what is actually eating the memory.

8. See what is listening before you install anything else

sudo ss -tulpn

On a clean server you should see SSH, plus perhaps chrony and systemd-resolved on localhost. Anything else listening on 0.0.0.0 or [::] deserves an explanation. Run this again after every new service you install. It takes two seconds and catches the database that was meant to listen only on 127.0.0.1.

9. Decide on backups before there is data to lose

Turn on your provider's backups if you want a quick restore point, but plan a copy that lives somewhere else too. The five-layer backup strategy walks through it, and automatic MySQL backups to Cloudflare R2 is a good first layer for any PHP app.

What about fail2ban?

fail2ban is still a fine tool, but once passwords are off and root login is disabled, the bots hammering SSH cannot get in, and blocking them mostly keeps your logs tidy. OpenSSH 10's built-in PerSourcePenalties now does a basic version of the same thing. I install fail2ban on servers that run something with its own login form exposed to the internet, such as a mail server or an admin panel, and skip it on a plain web server reached over SSH keys.

The checklist in one place

  1. apt update && apt full-upgrade, then reboot
  2. Create a sudo user; check sudo whoami
  3. SSH keys in; passwords and root login off in sshd_config.d/00-hardening.conf
  4. UFW: allow OpenSSH, 80 and 443, then enable
  5. Confirm unattended-upgrades is on; optionally auto-reboot at 04:00
  6. Time zone set, clock synchronised
  7. Swap file on 1–2 GB servers
  8. ss -tulpn after every install
  9. Backups planned, with one copy off the server

I checked the Ubuntu 26.04 changes in this guide against Canonical's 26.04 release notes and published upgrade reports as of October 2026. The commands are standard on Ubuntu Server 26.04; if your provider's image differs, the checks in each step will show it.

Comments 0

Be the first to comment.

Leave a comment