
Table of Contents
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.
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.
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/tcpand443/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.
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.