A brand-new VPS is reachable from the whole Internet as soon as it boots. Within the hour, bots are already trying passwords on port 22: it is not an attack aimed at you, it is a constant sweep of every IP address. A server left with root password login will give in sooner or later.
Here are the 7 settings to apply before installing anything, in order. The commands are written for Ubuntu 22.04 / 24.04 and Debian 12. Start by updating the system, logged in as root with the credentials your provider sent you:
apt update && apt upgrade -y1. Create a non-root user with sudo
Working as root every day means a typo or a script you did not read carefully has full power. Create your own user and give it sudo (on a minimal Debian image, install sudo first with apt install sudo):
adduser marie
usermod -aG sudo marie2. Log in with an SSH key
An SSH key cannot be guessed, unlike a password. Generate it on your computer (not on the server), then copy the public part to your new user:
ssh-keygen -t ed25519 -C "marie@laptop"
ssh-copy-id -i ~/.ssh/id_ed25519.pub marie@SERVER_IP
# Check that the key works before going further
ssh -i ~/.ssh/id_ed25519 marie@SERVER_IPssh-copy-id does not exist: paste the content of id_ed25519.pub into the user's ~/.ssh/authorized_keys on the server.3. Disable root login and passwords
Once the key is tested, stop SSH from accepting root and passwords. On recent Ubuntu and Debian, the cleanest way is a file in /etc/ssh/sshd_config.d/. The 00- prefix matters: SSH keeps the first value it reads, and many cloud images ship a 50-cloud-init.conf that turns passwords back on.
sudo tee /etc/ssh/sshd_config.d/00-hardening.conf > /dev/null <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
EOF
sudo sshd -t && sudo systemctl restart ssh
sudo sshd -T | grep -Ei 'permitrootlogin|passwordauthentication'sshd -t checks the syntax before the restart, sshd -T prints the configuration actually applied: both lines must end with no.From your second terminal, ssh root@SERVER_IP must now answer Permission denied (publickey). Moving SSH off port 22 reduces log noise but adds no real security: the key and fail2ban do the work.
4. Turn on a firewall with ufw
The idea: deny everything incoming, then open only what you need. Allow SSH before enabling the firewall, or you lock yourself out.
sudo apt install ufw
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 verbose5. Ban attackers with fail2ban
fail2ban reads the SSH logs and temporarily bans addresses that fail too often. Debian 12 no longer has a /var/log/auth.log file by default, so we read the systemd journal instead, which works on Ubuntu as well.
sudo apt install fail2ban python3-systemd
sudo tee /etc/fail2ban/jail.local > /dev/null <<'EOF'
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
[sshd]
enabled = true
backend = systemd
EOF
sudo systemctl enable fail2ban
sudo systemctl restart fail2ban
sudo fail2ban-client status sshdignoreip in the [DEFAULT] section so you never ban yourself. Details in Fail2ban explained simply.6. Install security updates automatically
Most hacked servers fall to a flaw that was patched long ago. unattended-upgrades installs security fixes every day, without touching major upgrades.
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
# Dry run: shows what would be installed
sudo unattended-upgrade --dry-run --debug/var/run/reboot-required appears when one is needed, and the Unattended-Upgrade::Automatic-Reboot option in /etc/apt/apt.conf.d/50unattended-upgrades can handle it at night.7. Plan backups (and test the restore)
Security also means being able to recover from a mistake, a deletion or a failing disk. Two levels work together:
- Provider snapshots: a full image of the disk, one click away in their dashboard, often a paid option. Ideal before a big upgrade.
- An off-server backup of your data: your files and a dump of your databases, sent somewhere else. If you lose access to the provider account, you lose the snapshots too.
sudo apt install restic
restic -r sftp:backup@other-server:/backups/vps init
restic -r sftp:backup@other-server:/backups/vps backup /etc /home /srv
# The test that matters: restore
restic -r sftp:backup@other-server:/backups/vps restore latest --target /tmp/restorepg_dump, mysqldump) rather than its files while they are being written. A backup you never restored is only a hope.Checklist
Before deploying your first application, make sure everything is ticked:
- A personal user with
sudo, no more working asroot. - SSH key login, tested from a second terminal.
PermitRootLogin noandPasswordAuthentication noconfirmed bysshd -T.- ufw active, only SSH, HTTP and HTTPS open.
- fail2ban active on
sshd, your IP inignoreip. - Security fixes installed every day.
- Off-server backups, and one restore already done.