2 min readlinuxdebian

Debian 12 minimal server checklist

Every new VPS gets the same treatment before anything else is installed. None of this is clever; the point is to do it every time, in the same order, so nothing is forgotten.

1. Update and enable unattended upgrades

apt update && apt full-upgrade -y
apt install -y unattended-upgrades apt-listchanges
dpkg-reconfigure -plow unattended-upgrades

The default policy installs security updates only, which is what I want on a server. Check /var/log/unattended-upgrades/ after a day to confirm it ran.

2. A user, a key, and no passwords over SSH

adduser deploy
usermod -aG sudo deploy
install -d -m 700 -o deploy -g deploy /home/deploy/.ssh
# paste your public key into /home/deploy/.ssh/authorized_keys

Then put the SSH policy in a drop-in file instead of editing the main config, so package upgrades never conflict with it:

# /etc/ssh/sshd_config.d/10-hardening.conf
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
sshd -t && systemctl reload ssh
Keep your current session open and test a new login in a second terminal before closing anything.

3. Firewall

Debian 12 uses nftables. A small ruleset that allows SSH, HTTP and HTTPS and drops the rest:

#!/usr/sbin/nft -f
flush ruleset
table inet filter {
  chain input {
    type filter hook input priority 0; policy drop;
    iif lo accept
    ct state established,related accept
    ct state invalid drop
    meta l4proto { icmp, ipv6-icmp } accept
    tcp dport { 22, 80, 443 } accept
  }
}
nft -c -f /etc/nftables.conf && systemctl enable --now nftables

Docker writes its own rules and published container ports bypass this chain — keep that in mind if you run containers.

4. Time, logs and swap

  • Time: timedatectl should show "System clock synchronized: yes". systemd-timesyncd is enough for most servers.
  • Journal size: set SystemMaxUse=500M in /etc/systemd/journald.conf on small disks.
  • Swap: small instances often ship without it. A 1 GB swap file avoids the OOM killer during apt runs.
fallocate -l 1G /swapfile && chmod 600 /swapfile
mkswap /swapfile && swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab

5. Look at what is listening

ss -tulpn

Anything listening on 0.0.0.0 or [::] that you did not expect should be stopped or bound to 127.0.0.1. Images from hosting providers sometimes ship with extras enabled — test servers, agents, panels. Disable what you do not use with systemctl disable --now.

6. Write it down

Keep a short text file in /root or your notes with what was changed and why. Six months later it is the only documentation that exists.