On this page 10 sections
Automated scanners start probing a new server within minutes of it going online. This checklist covers the essentials for your first hour. You need root access over SSH with your key installed; see Create and use SSH keys. We don’t administer your operating system, so these steps are yours to take.
Keep one SSH session open while you change SSH or firewall settings, and test each change from a second session. If you lock yourself out anyway, the console still works.
Install updates automatically
# Debian, Ubuntu
sudo apt update && sudo apt full-upgrade
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
# AlmaLinux, Rocky Linux
sudo dnf upgrade
sudo dnf install dnf-automatic
sudo systemctl enable --now dnf-automatic-install.timer
On Debian and Ubuntu, unattended-upgrades installs security updates by default. New kernels only take effect after a reboot, so schedule one regularly.
Work as a sudo user
sudo adduser alice && sudo usermod -aG sudo alice # Debian, Ubuntu
sudo useradd -m -G wheel alice && sudo passwd alice # AlmaLinux, Rocky Linux
sudo install -d -m 700 -o alice -g alice /home/alice/.ssh
sudo install -m 600 -o alice -g alice /root/.ssh/authorized_keys /home/alice/.ssh/
Give the user a strong password: sudo asks for it, and you need it to log in on the console. Check that ssh alice@203.0.113.10 and sudo -v work before you continue.
Allow SSH keys only
Create /etc/ssh/sshd_config.d/00-hardening.conf:
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
For each setting, sshd uses the first value it reads, so a file named 00-… wins over later ones such as 50-cloud-init.conf. Test the configuration, reload, and check the values in effect:
sudo sshd -t && sudo systemctl reload ssh # Debian, Ubuntu
sudo sshd -t && sudo systemctl reload sshd # AlmaLinux, Rocky Linux
sudo sshd -T | grep -Ei 'passwordauth|kbdinteractive|permitrootlogin'
Once your sudo user works, you can set PermitRootLogin no. On FreeBSD, make the same changes in /etc/ssh/sshd_config and run service sshd reload.
Enable a firewall
First, see what is listening with sudo ss -tulpn: anything bound to 0.0.0.0 or [::] is reachable from the internet unless a firewall blocks it. On Debian, this ruleset in /etc/nftables.conf accepts SSH, loopback, ICMP and replies to your own connections, and drops everything else:
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
ct state invalid drop
iif "lo" accept
meta l4proto { icmp, ipv6-icmp } accept
tcp dport 22 accept
}
chain forward {
type filter hook forward priority filter; policy drop;
}
}
sudo nft -c -f /etc/nftables.conf # check syntax
sudo nft -f /etc/nftables.conf # load now
sudo systemctl enable nftables # load at boot
Add a rule such as tcp dport { 80, 443 } accept for each service you publish. Keep ICMP open: IPv6 doesn’t work without ICMPv6.
flush rulesetdeletes every existing rule, including those created by Docker, libvirt or the Proxmox VE firewall. On such hosts, use their own firewall integration instead.
On Ubuntu, ufw is simpler: sudo ufw allow OpenSSH, then sudo ufw enable. On AlmaLinux and Rocky Linux, firewalld is normally active and already allows SSH. Review it with sudo firewall-cmd --list-all, add services with sudo firewall-cmd --permanent --add-service=https, remove unused ones such as cockpit with --remove-service, then run sudo firewall-cmd --reload.
Slow down brute-force attempts
With passwords disabled, guessing can’t succeed, but it fills your logs. fail2ban bans addresses that fail repeatedly. Install it with sudo apt install fail2ban python3-systemd, then create /etc/fail2ban/jail.local:
[sshd]
enabled = true
backend = systemd
maxretry = 5
bantime = 1h
Restart it with sudo systemctl restart fail2ban and check it with sudo fail2ban-client status sshd. On AlmaLinux and Rocky Linux, fail2ban comes from EPEL: run sudo dnf install epel-release, then sudo dnf install fail2ban. sshguard is a lighter alternative.
Keep the clock in sync
Logs, TLS certificates and two-factor codes depend on accurate time. timedatectl should report System clock synchronized: yes. If it doesn’t, install the chrony package and enable its service.
Back up your data
We don’t back up your data, and RAID isn’t a backup: it doesn’t protect against deletion, ransomware or a compromised system. Follow the 3-2-1 rule: three copies of your data, on two different types of storage, with one copy off-site, for example on a server in another location. Tools such as restic and BorgBackup encrypt and deduplicate. Test a restore regularly.
Protect your client area account
Anyone who can log in to your client area can reinstall your server, open its console or boot it into rescue mode. Enable two-factor authentication (TOTP) under Account → Security, and use a password you don’t use anywhere else.
Monitor the server
Set up an external uptime check (ping or HTTP) that runs outside our network, alerts for disk space and load, and the RAID and SMART alerts described in Monitor and repair software RAID. Network incidents are published on our status page.
If your server is compromised
- Stop the damage. If the server attacks others, power it off or boot it into rescue mode, which runs a clean system from the network.
- Don’t trust the installed system. From rescue mode, copy off only the data you need, not programs or scripts, plus logs if you want to investigate.
- Reinstall the operating system. Cleaning up in place is never reliable.
- Rotate every secret that was on the server or used to reach it: SSH keys, passwords, API tokens and database credentials.
- Restore data from a backup made before the intrusion, fix the weakness the attacker used, and repeat this checklist before going live.
When we receive an abuse report about your server, we notify you and give you 24 hours to fix the problem; active attacks are stopped immediately with a null route or suspension. The details are in the Acceptable Use Policy.



