1. Sign In and Update
Use the server's IP address from your dashboard and the root password you chose when ordering. If you added an SSH key to the order, it is already set up for root and no password is asked for:
ssh [email protected] apt update && apt full-upgrade -y [ -f /var/run/reboot-required ] && reboot
If it rebooted, wait a minute and sign in again.
2. Create Your Own User
Day to day, work as a normal user and use sudo when you need root. Debian's minimal image may not have sudo yet, so the first line installs it:
apt install -y sudo adduser alice usermod -aG sudo alice
3. Add Your SSH Key
On your own computer, make a key if you do not have one, then copy it to the server. On macOS and Linux:
ssh-keygen -t ed25519 -C "my laptop" ssh-copy-id [email protected]
Windows has no ssh-copy-id; in PowerShell:
ssh-keygen -t ed25519 -C "my laptop" type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh [email protected] "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
If you added a key when ordering, it is already in root's account, so copy it across on the server instead:
rsync --archive --chown=alice:alice ~/.ssh /home/alice
Now open a new terminal and check that the key works and sudo asks for alice's password:
ssh [email protected] sudo -v
4. Turn Off Password Logins
Keep your current session open until you have tested the change from a second one. Put the settings in their own file:
sudo tee /etc/ssh/sshd_config.d/00-hardening.conf >/dev/null <<'EOF' PasswordAuthentication no KbdInteractiveAuthentication no PermitRootLogin no EOF sudo sshd -t && sudo systemctl restart ssh
The 00- in the name matters. SSH uses the first value it reads for each setting, and some images ship a file such as 50-cloud-init.conf that turns passwords back on. Confirm what SSH is really using:
sudo sshd -T | grep -Ei '^(passwordauthentication|permitrootlogin)'
Both should say no. From another terminal, a password-only attempt should now be refused with Permission denied (publickey):
ssh -o PubkeyAuthentication=no [email protected]
5. Allow Only the Ports You Use
You have two places to do this, and you can use either or both. The Firewall on your server's page in the dashboard is applied outside the server, before traffic reaches it, and has presets for SSH, web, Remote Desktop and WireGuard. It also shows your current IP address, so you can allow SSH from your address only.
Inside the server, UFW does the same job:
sudo apt install -y ufw sudo ufw allow OpenSSH sudo ufw allow 80,443/tcp # only if this will be a web server sudo ufw enable sudo ufw status verbose
If you will run Docker, read the firewall section of How to run Docker and Docker Compose on a VPS first: ports that Docker publishes skip UFW's rules.
6. Turn On Automatic Security Updates
sudo apt install -y unattended-upgrades sudo dpkg-reconfigure -plow unattended-upgrades # answer Yes systemctl list-timers apt-daily-upgrade.timer
Security updates now install every day. Kernel updates only take effect after a reboot. To let the server reboot itself at a quiet hour when one is needed, set these two lines in /etc/apt/apt.conf.d/50unattended-upgrades:
Unattended-Upgrade::Automatic-Reboot "true"; Unattended-Upgrade::Automatic-Reboot-Time "04:00";
7. Optional: fail2ban
fail2ban blocks addresses that keep failing to sign in. Reading the systemd journal works on both Ubuntu and Debian, including Debian 12, which has no /var/log/auth.log by default:
sudo apt install -y fail2ban python3-systemd sudo tee /etc/fail2ban/jail.d/sshd.local >/dev/null <<'EOF' [sshd] enabled = true backend = systemd EOF sudo systemctl restart fail2ban sudo fail2ban-client status sshd
What to Do Next
Set up backups before the server holds anything you would miss: How to back up a Linux server with Borg takes about as long as this guide. Then host a website or run Docker. If SSH stops letting you in, How to fix common SSH errors goes through each message.