Initial Ubuntu Server Setup: Secure a Fresh VPS in 20 Minutes (2026)

Khimananda Oli 7 min read Database
Initial Ubuntu Server Setup: Secure a Fresh VPS in 20 Minutes (2026)

By Khimananda Oli | Last reviewed: August 2026

A brand-new VPS is exposed the moment it boots. Within minutes, automated bots are hammering port 22 with root/password guesses, and a default Ubuntu image does nothing to stop them. This initial Ubuntu server setup is the first-hour hardening that closes those doors before anything of value goes on the box — a non-root sudo user, SSH key authentication, a locked-down firewall, and unattended security updates. Do it once, in the right order, and every deploy after that starts from a safe baseline. If you would rather hand this off, my DevOps and cloud services cover server hardening end to end.

Fresh Ubuntu 24.04 VPS — hardening layersAutomatic security updates (unattended-upgrades)fail2ban — ban repeat offendersUFW firewall — allow only SSH + 80/443SSH key auth — no passwords, no rootNon-root user with sudo
The initial Ubuntu server setup builds defence in layers — each one assumes the layer below it is already in place.

What should you do first on a fresh Ubuntu VPS?

Log in as the account your provider gave you (usually root) and update the package index before anything else. A fresh image is often weeks old, so patching first closes any already-known holes:

ssh [email protected]

apt update && apt -y full-upgrade
apt -y autoremove

Set the timezone and confirm clock sync while you are here — accurate time matters for TLS certificates, log correlation, and fail2ban windows. Ubuntu 24.04 keeps time via systemd-timesyncd, so no extra NTP daemon is needed:

timedatectl set-timezone Asia/Kathmandu
timedatectl set-ntp true
timedatectl status

The order for the rest of the setup is deliberate. Create your user and prove key login works before you disable password and root access, or you can lock yourself out of the machine entirely.

How do you create a non-root sudo user on Ubuntu?

Running everything as root means one careless command or one compromised process owns the whole box. Create a normal user, add it to the sudo group, and do your day-to-day work there instead:

adduser deploy
usermod -aG sudo deploy

adduser prompts for a password and creates the home directory. The -aG sudo line grants administrative rights through sudo, so the account can escalate when needed but is not privileged by default. Verify it before moving on:

su - deploy
sudo whoami        # should print: root
exit

Why is SSH key authentication better than a password login?

A password is a short secret a bot can guess or brute-force. An SSH key pair is a long cryptographic secret that never travels over the wire — the server only ever sees your public key, and only a holder of the matching private key can log in. That single change eliminates the entire category of password-guessing attacks that fill server logs.

Password loginattacker botSSH serverport 22guess, guess, guess…secret travels every attemptweak: brute-forceableSSH key authenticationyour laptopprivate keySSH serverpublic keychallenge signed locallyprivate key never sentstrong: not guessable
SSH key authentication keeps the private key on your machine — the server only stores the public key, so there is nothing to brute-force.

Generate a key pair on your local machine (skip this if you already have one), then copy the public half up to the new user:

ssh-keygen -t ed25519 -C "you@laptop"

ssh-copy-id [email protected]

If ssh-copy-id is unavailable, append the public key manually to ~/.ssh/authorized_keys for the deploy user and fix the permissions:

mkdir -p /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys
chown -R deploy:deploy /home/deploy/.ssh

Now open a new terminal and confirm ssh [email protected] logs you in without asking for a password. Do not skip this test — the next step removes the fallback.

How do you disable root login and password authentication in SSH?

With key login proven, harden the SSH daemon. On Ubuntu 24.04 the clean way is a drop-in file under /etc/ssh/sshd_config.d/ rather than editing the main config, so upgrades never clobber your changes:

sudo tee /etc/ssh/sshd_config.d/99-hardening.conf > /dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
EOF

Validate the syntax and reload the service. Ubuntu 24.04 uses socket activation, so restart ssh.socket to be safe:

sudo sshd -t
sudo systemctl restart ssh.socket ssh.service

Keep your existing session open and test a fresh login in another window. Two behaviours confirm success: root can no longer log in over SSH, and any password attempt is refused before it reaches a prompt.

How do you set up a UFW firewall for a web server?

UFW (Uncomplicated Firewall) ships with Ubuntu and wraps iptables in readable rules. The safe pattern is deny-by-default inbound, then allow only the ports you actually serve. Allow SSH before you enable the firewall, or the enable command will cut your connection:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

Here is what each rule buys you on a typical web server:

  • default deny incoming — everything is blocked unless a rule opens it, so a service you forgot about is never silently reachable.
  • allow OpenSSH — opens port 22 (or your custom SSH port) so you keep access.
  • allow 80/tcp and 443/tcp — HTTP and HTTPS for your site; HTTP is usually kept only to redirect to HTTPS.
  • default allow outgoing — the server can still reach package mirrors, APIs, and databases it needs.
UFWdeny incomingby defaultSSH · 22HTTP · 80HTTPS · 4433306, 6379, …web serverNginx / app
A UFW firewall for a web server allows only SSH, HTTP, and HTTPS inbound; database and cache ports like 3306 and 6379 stay closed to the internet.

Notice that a database (MySQL 3306) or cache (Redis 6379) port is never opened to the world — those should bind to localhost or a private network only. If you changed SSH to a non-standard port, run sudo ufw allow 2222/tcp (with your port) before enabling, then remove the OpenSSH rule.

How do you block brute-force attacks and keep Ubuntu patched automatically?

Two background services do the ongoing work so you do not have to babysit the box. fail2ban watches auth logs and temporarily bans IPs that fail repeatedly, and unattended-upgrades applies security patches on a schedule:

sudo apt install -y fail2ban unattended-upgrades
sudo systemctl enable --now fail2ban

fail2ban ships with a working default jail for SSH, so it protects you the moment it starts. Confirm it is watching and enable automatic security updates through the interactive prompt:

sudo fail2ban-client status sshd
sudo dpkg-reconfigure -plow unattended-upgrades

Choose Yes when asked to download and install stabilised updates automatically. With that, your server patches known vulnerabilities on its own and quietly turns away the bots probing SSH — the two chores most people forget after the first week. For a working example of hardened servers running real workloads, see my DevOps case studies.

Conclusion

Twenty focused minutes is all it takes to turn a wide-open VPS into a defensible one: a non-root sudo user, SSH key authentication with root and password login disabled, a deny-by-default UFW firewall, fail2ban, and automatic security updates. Run this initial Ubuntu server setup before your first deploy and every project after it inherits a safe baseline. Ready to deploy on top of it? Read my step-by-step guide to building a CI/CD pipeline with GitLab CI for Laravel, or contact me to have your servers hardened and audited for you.

Frequently Asked Questions

Log in and run apt update then apt full-upgrade to patch the image, then set the timezone. After that, create a non-root sudo user and add your SSH key before disabling root and password login, so you never risk locking yourself out.

Root has unrestricted power, so a single mistyped command or one compromised process can destroy or expose the entire server. A normal user with sudo escalates only when you explicitly ask it to, which contains accidents and limits the blast radius of an attack.

Run adduser deploy to create the account and set a password, then usermod -aG sudo deploy to grant administrative rights. Test it with sudo whoami, which should print root, before you rely on the account for anything else.

Yes. A private key is a long cryptographic secret that never leaves your machine, while a password is short and travels on every login attempt. Keys cannot be brute-forced the way passwords can, which removes the most common attack against SSH entirely.

Add PermitRootLogin no to a file such as /etc/ssh/sshd_config.d/99-hardening.conf, validate with sudo sshd -t, then restart the SSH service. Confirm key login for your normal user works in a separate session first so you keep access.

Set PasswordAuthentication no and KbdInteractiveAuthentication no in a drop-in file under /etc/ssh/sshd_config.d/, then reload SSH. Always verify that key-based login works before doing this, or you will be locked out of the server.

Only if your SSH key is not yet working. Always copy your public key to the new user and confirm a passwordless login in a fresh terminal before you set PasswordAuthentication no. Keep the original session open as a safety net during the change.

Allow SSH (OpenSSH), plus 80/tcp and 443/tcp for HTTP and HTTPS. Set default deny incoming so everything else is blocked. Never open database or cache ports like 3306 or 6379 to the internet; bind those to localhost instead.

With default deny incoming, enabling UFW immediately drops every unlisted connection, including your current SSH session. Running ufw allow OpenSSH first guarantees port 22 stays open, so the enable command does not cut you off from the server.

fail2ban scans authentication logs and temporarily bans IP addresses that fail to log in repeatedly. It stops brute-force and credential-stuffing attempts on SSH and other services. On a public VPS it is well worth the few minutes it takes to install.

Install the unattended-upgrades package and run sudo dpkg-reconfigure -plow unattended-upgrades, choosing Yes. Ubuntu then downloads and applies security patches automatically on a schedule, closing known vulnerabilities without you logging in to run apt.

Use timedatectl set-timezone Asia/Kathmandu (or your zone) and timedatectl set-ntp true. Ubuntu 24.04 keeps the clock synced with systemd-timesyncd, so no separate NTP daemon is needed. Accurate time matters for TLS, logs, and ban windows.

It is optional. Moving SSH to a non-standard port cuts noise from automated scanners but is not real security on its own. If you change it, add a matching UFW allow rule before enabling the firewall and keep key authentication in place.

Use Ubuntu 24.04 LTS. Long-term support releases get five years of standard security updates, giving you a stable base with predictable patching. The setup steps here apply cleanly to 24.04 and its point releases.

About 20 minutes for someone comfortable with the terminal. Creating the user, adding your SSH key, hardening the daemon, configuring UFW, and installing fail2ban and unattended-upgrades are all quick, one-time commands you run once per server.