What to Do Right After Buying a VPS: Initial Setup and Security
A new VPS gets attacked within minutes of going online: bots constantly scan the internet and try to guess SSH passwords. That's why basic protection should be in place before you install a website, a bot or a VPN.
This guide has nine steps and takes 20–30 minutes. Commands are for Ubuntu 22.04/24.04 and Debian 12. Once done, your server is closed to password guessing, installs security updates on its own and won't crash from running out of memory.
Step 1. Update the System
Your host's OS image may be months old and contain vulnerabilities that have since been fixed. Connect using the details from your host's welcome email and update the packages:
ssh root@SERVER_IPapt update && apt upgrade -y
If the kernel was updated, reboot the server: reboot.
While you're at it, set the time zone and a clear hostname. Correct time matters for logs, cron and SSL certificates:
timedatectl set-timezone Europe/Londonhostnamectl set-hostname web-01
Run timedatectl list-timezones to find your time zone.
Step 2. Create a User with sudo Rights
Working as root all the time is risky: one wrong command can break the system, and root is the first target for password guessing. Create a regular user and let it run admin commands through sudo:
adduser adminusermod -aG sudo admin
Pick your own name instead of admin: it's harder to guess. Set a strong password; you'll need it for sudo.
Step 3. Set Up SSH Key Login
Unlike a password, an SSH key can't be brute-forced. A key has two files: the private one stays on your computer, the public one goes to the server.
On your own computer (Linux, macOS or PowerShell on Windows 10/11), create a key:
ssh-keygen -t ed25519 -C "my-laptop"
Press Enter to save it in the default location. Set a passphrase: if your laptop is stolen, the key can't be used.
Copy the public key to the server. On Linux and macOS:
ssh-copy-id admin@SERVER_IP
Windows has no ssh-copy-id, so use PowerShell:
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh admin@SERVER_IP "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Test the login in a new terminal window: ssh admin@SERVER_IP. The server should let you in without the user's password (or ask only for the key passphrase).
Step 4. Disable Root and Password Login
Once key login works, turn off passwords. This stops SSH password guessing completely.
Don't close your current session until you've tested the new settings in another window. Otherwise, one mistake can lock you out.
Create a settings file:
sudo nano /etc/ssh/sshd_config.d/01-hardening.conf
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yesMaxAuthTries 3
The 01-... name matters: SSH uses the first value it finds, and many hosts put a 50-cloud-init.conf with PasswordAuthentication yes in the same folder. The file with the lower number is read first and wins.
Check the config and restart SSH:
sudo sshd -tsudo systemctl restart ssh
In a new window, confirm that ssh admin@SERVER_IP works and ssh root@SERVER_IP doesn't.
Changing the SSH port from 22 cuts down log noise but doesn't replace keys. If you change it, add Port 2222 to the same file and open the port in the firewall (Step 5) before restarting. On Ubuntu 24.04, then run sudo systemctl daemon-reload && sudo systemctl restart ssh.socket.
Step 5. Turn On the Firewall
A firewall closes every port except the ones you open yourself. That way, a service or database you started by accident won't be reachable from the internet.
Standard Ubuntu images usually include UFW, but minimal images and Debian need it installed. Allow SSH first, or you'll lose access once it's enabled:
sudo apt install -y ufwsudo ufw allow OpenSSH
# if you changed the SSH port: sudo ufw allow 2222/tcpsudo ufw default deny incomingsudo ufw default allow outgoingsudo ufw enable
For a website, open the web ports: sudo ufw allow 80,443/tcp. Review the rules with sudo ufw status verbose.
If you'll run Docker, note that it publishes ports bypassing UFW. Bind container ports to 127.0.0.1 and expose them through Nginx.
Step 6. Install fail2ban
fail2ban reads the logs and blocks IPs with too many failed login attempts. Even with key-only login, it takes bot load off the server and keeps the logs clean.
sudo apt install -y fail2ban python3-systemdsudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 YOUR_IP
[sshd]
enabled = truebackend = systemd
Add your IP to ignoreip if it's static, so you don't ban yourself by accident. If you changed the SSH port, add port = 2222 to the [sshd] block.
sudo systemctl enable --now fail2bansudo fail2ban-client status sshd
Step 7. Enable Automatic Security Updates
New vulnerabilities are found all the time, and manual updates are easy to forget. unattended-upgrades installs only security fixes every day, without changing major software versions.
sudo apt install -y unattended-upgradessudo dpkg-reconfigure -plow unattended-upgrades
Choose Yes in the dialog. To check that it works, do a test run: sudo unattended-upgrade --dry-run --debug.
Some updates, such as kernel updates, need a reboot. If the file /var/run/reboot-required exists, reboot the server at a convenient time.
Step 8. Add Swap
On a VPS with 1–2 GB of RAM, running out of memory is a common cause of sudden crashes: the system kills the database or website process. Swap is a file on disk that acts as a safety net during load spikes.
Check whether swap exists with free -h. If the Swap row shows zeros, create a 2 GB file:
sudo fallocate -l 2G /swapfilesudo chmod 600 /swapfilesudo mkswap /swapfilesudo swapon /swapfileecho '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
To make the system use swap only when memory actually runs low:
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swap.confsudo sysctl --system
Swap is slower than RAM. If your server relies on it constantly, it's time to move to a plan with more memory.
Step 9. Set Up Backups and Monitoring
A backup is the only thing that saves you from deleted files, a hack or a disk failure. Monitoring tells you about a problem before your customers do.
Backups:
- Turn on snapshots in your hosting panel if available. A snapshot restores the whole server in a few minutes.
- Keep at least one copy of important data (databases, site files, configs) off the server: in S3-compatible storage or on another VPS.
resticorborgwork well for this. - Once a month, check that you can actually restore from the backup.
Monitoring:
- Connect an external uptime monitoring service. It checks your site every minute and alerts you via Telegram or email if it stops responding.
- For a quick look at resources on the server itself:
htop(CPU and memory),df -h(disk space),free -h(memory). - Keep an eye on disk space: at 100%, databases crash and logs stop being written.
Checklist
What's Next
Your server is ready. What comes next depends on your goal: for example, run a Telegram bot 24/7 or protect your site from DDoS attacks.
FAQ
What if I locked myself out of SSH? Log in through the web console (VNC) in your hosting panel. It works directly, bypassing SSH and the firewall. Fix the settings and restart SSH.
Should I change the SSH port? It's optional. Keys and disabled passwords provide the real protection. A different port only reduces the number of bots in the logs.
What if I lose my SSH key? Log in through your host's web console with your user's password and add a new public key to ~/.ssh/authorized_keys. It's best to add keys from two devices in advance.
Do I need antivirus on a Linux server? For a typical VPS, updates, keys, a firewall and a minimum of open ports matter more. Antivirus makes sense if the server accepts files from users, such as mail or file sharing.
How often should I update the server manually? Security updates install themselves after Step 7. Once a month, run sudo apt update && sudo apt upgrade and reboot if needed.