Setting Up a Fresh Ubuntu VPS the Right Way
Md Asaduzzaman · · 4 min read
You just bought a VPS from DigitalOcean, Hetzner, Vultr or Contabo and got an IP address and a root password. Before you deploy anything, spend half an hour making the server safe. Bots start scanning a new IP for weak SSH logins within minutes.
This guide uses Ubuntu 24.04 LTS, but the steps are almost the same on 22.04 and on Debian.
Throughout this post, replace
203.0.113.10with your server's IP andasadwith your own username.
1. Log in and update everything
ssh [email protected]
apt update && apt upgrade -y
apt install -y curl git ufw fail2ban unattended-upgrades
If the upgrade installed a new kernel, reboot with reboot and log in again.
2. Set the hostname and timezone
hostnamectl set-hostname my-server
timedatectl set-timezone Asia/Dhaka
A correct timezone makes logs and cron jobs much easier to read.
3. Create a normal user with sudo
Working as root all day means one typo can break the whole machine. Create your own user and give it sudo rights:
adduser asad
usermod -aG sudo asad
4. Log in with an SSH key instead of a password
On your own computer (not the server), create a key if you don't have one yet, then copy it to the server:
ssh-keygen -t ed25519 -C "[email protected]"
ssh-copy-id [email protected]
On Windows without ssh-copy-id, print the key with type $env:USERPROFILE/.ssh/id_ed25519.pub in PowerShell and paste it into /home/asad/.ssh/authorized_keys on the server.
Now open a new terminal and check that this works without a password:
ssh [email protected]
Keep your root session open until you are sure, so you can't lock yourself out.
5. Harden SSH
Edit the SSH config:
sudo nano /etc/ssh/sshd_config
Find these lines (remove the # in front if there is one) and set:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
On Ubuntu, also check /etc/ssh/sshd_config.d/: some providers put a file there that turns password login back on. Then test the config and restart:
sudo sshd -t
sudo systemctl restart ssh
From now on, only your key can log in, and root can't log in over SSH at all.
6. Turn on the firewall
UFW ("uncomplicated firewall") blocks everything except the ports you open. Allow SSH first, or you will cut your own connection:
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status
Ports 80 and 443 are for the website we will deploy later. Your database, Node.js app and Redis should not be open to the internet; they only need to listen on 127.0.0.1.
7. Block brute-force attempts with Fail2ban
Fail2ban watches the SSH log and bans IPs that fail to log in too many times. The default jail for SSH is enough for most servers:
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
8. Automatic security updates
sudo dpkg-reconfigure --priority=low unattended-upgrades
Choose Yes. Ubuntu will now install security patches by itself every day.
9. Add swap on small servers
A 1 GB VPS can run out of memory while running npm install or docker build. A swap file prevents the build from being killed:
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
free -h
10. Point your domain at the server
In your domain provider's DNS settings, add two A records:
| Type | Name | Value |
|---|---|---|
| A | @ | 203.0.113.10 |
| A | www | 203.0.113.10 |
DNS can take a few minutes to a few hours to update. Check it with ping example.com.
Checklist
- System updated
- Normal user with sudo
- SSH key login, no passwords, no root login
- Firewall allows only 22, 80 and 443
- Fail2ban and automatic security updates
- Swap on small servers
- Domain pointing at the server
The server is now ready for real work. In the next post we install Node.js and deploy a React app behind Nginx with free HTTPS.