Harden a Debian VPS for production with a security checklist

A fresh Debian VPS is a blank slate, and that is exactly what makes it dangerous. The default install comes with password-based SSH, root login enabled, and no firewall rules. On a public IPv4 address, that combination gets probed within minutes. The first thing to do on any new production box is work through a harden Debian VPS Vietnam security checklist before you deploy anything on it. This guide walks you through the essential steps: SSH key authentication, a stateful nftables firewall, fail2ban, automatic security updates, and the verification commands that prove each layer actually works. It applies to Debian 12 and Debian 13.
Prerequisites
- A Debian 12 or Debian 13 VPS with root or sudo access. If you are starting fresh, a Linux VPS with a dedicated IPv4 and full root access gives you the control this checklist assumes.
- SSH access to the server from your local machine.
- An SSH key pair generated on your local machine (
ssh-keygen -t ed25519). - Basic familiarity with the command line. You do not need to be a security expert, but you should know what sudo does.
Why a production Debian server needs hardening before anything else
Most break-ins on small VPS instances are not sophisticated attacks. They are automated scans that try default credentials, weak passwords, and known exploits. A server that still allows password authentication over SSH is exposed to a brute-force campaign the moment it gets an IP address. The same goes for an open port 22 without rate limiting.
Hardening is not about making the server impenetrable. It is about reducing the attack surface to something you can actually defend. Every service you do not run, every port you do not open, and every authentication method you disable is one less thing to monitor. A harden Debian VPS Vietnam security checklist gives you a repeatable baseline, so you do not forget the step that matters. This is the same discipline you would apply to any production workload, whether it is a web server, an n8n instance, or a database host.
Step 1 - Update the system and enable automatic security updates
Before changing any configuration, bring the base system up to date. An outdated kernel or a vulnerable OpenSSL package undermines everything else on this checklist.
sudo apt update && sudo apt full-upgrade -y
Then install the package that handles unattended security updates:
sudo apt install unattended-upgrades apt-listchanges -y
Enable it and verify the configuration:
sudo dpkg-reconfigure --priority=low unattended-upgrades
sudo systemctl status unattended-upgrades
Verify: the service should report active (running). The default configuration on Debian 12 and 13 applies security updates automatically, which is what you want on a production box. You can check which packages are held back with sudo unattended-upgrades --dry-run.
This covers the most common way servers get compromised: a known vulnerability that was patched upstream but never applied. Automatic updates close that gap without you logging in every week.
Step 2 - Set up SSH key authentication and disable password login
Password authentication over SSH is the weakest link on a fresh server. The fix is to use an ED25519 key pair, which is faster and more secure than RSA for this use case. Generate the key on your local machine, not on the server:
ssh-keygen -t ed25519 -a 100
Copy the public key to the server:
ssh-copy-id user@your-server-ip
Test that key login works from a second terminal before you disable passwords. If you lock yourself out, you will need the VPS control panel to reinstall the OS, so always keep an active session open while testing:
ssh -i ~/.ssh/id_ed25519 user@your-server-ip
Then edit the SSH daemon configuration:
sudo nano /etc/ssh/sshd_config
Set or confirm these values:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
UsePAM no
MaxAuthTries 3
Restart SSH to apply the changes:
sudo systemctl restart sshd
Verify: from a new session, try to log in with a password. It should be rejected. Your key-based session should still work. If it does not, fix the key configuration before you close the working session. This is the single highest-impact step on the entire harden Debian VPS Vietnam security checklist.
| Setting | Value | Why it matters |
|---|---|---|
| PermitRootLogin | no | Stops direct root login over SSH |
| PasswordAuthentication | no | Blocks brute-force password attacks |
| MaxAuthTries | 3 | Limits login attempts per connection |
| PubkeyAuthentication | yes | Enables the key-based method you just set up |
Step 3 - Configure a stateful nftables firewall
Debian 12 and 13 ship with nftables as the default firewall framework. It replaces iptables, and the syntax is cleaner. You only need a few rules for a basic production server: allow established connections, allow SSH, allow HTTP and HTTPS if you run a web service, and drop everything else.
sudo nano /etc/nftables.conf
Replace the file with a minimal stateful configuration:
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
iif lo accept
tcp dport 22 accept
tcp dport 80 accept
tcp dport 443 accept
icmp type echo-request accept
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy accept;
}
}
Apply the rules and enable the service:
sudo nft -f /etc/nftables.conf
sudo systemctl enable --now nftables
Verify: check the active ruleset with sudo nft list ruleset. You should see the input chain with a drop policy and the accept rules you defined. From another machine, confirm port 22 still accepts connections and a random port like 8080 times out: nc -vz your-server-ip 8080 should fail.
If you run services on other ports, add them before the drop policy. If you change the SSH port, update the firewall rule to match. A firewall that blocks your own SSH access is worse than no firewall, so test from a second session the same way you tested SSH keys.
Step 4 - Deploy fail2ban to stop brute-force attempts
A firewall blocks connections to closed ports, but it does nothing to stop repeated login attempts against the SSH port. fail2ban watches the authentication logs and bans IP addresses that hit a failure threshold. On a SMTP VPS or any publicly reachable server, this is the difference between a log file full of junk and a log file you can actually read.
sudo apt install fail2ban -y
Create a local jail configuration that overrides the defaults:
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
backend = systemd
[sshd]
enabled = true
Start and enable the service:
sudo systemctl enable --now fail2ban
Verify: check the status of the SSH jail:
sudo fail2ban-client status sshd
You should see Currently banned: 0 or a count of already-banned IPs. The counter going up over the first days on a public IP is normal. You can test the jail by making five failed login attempts from another machine, then checking the status again. The IP should appear in the banned list.
Step 5 - Review listening ports and remove unused services
Every open port is a potential entry point. After the firewall is up, check what is actually listening on the network:
sudo ss -tlnp
The output shows the services bound to a TCP port. On a minimal Debian install, you should only see SSH on port 22. Anything else is a service you either need or should remove. Common culprits on a default install include exim4 and avahi-daemon, neither of which a production server needs:
sudo systemctl disable --now avahi-daemon
sudo apt purge exim4-base -y
Verify: run sudo ss -tlnp again. The port list should be shorter. The fewer services running, the fewer packages need security updates, and the smaller the attack surface. This is not a one-time task, re-run it every time you install something new.
Troubleshooting common hardening failures
Hardening steps fail in predictable ways. Here are the three failures you are most likely to hit.
You are locked out of SSH after disabling password authentication. This usually means the public key is not in ~/.ssh/authorized_keys on the server, or the file has the wrong permissions. In another terminal, check with ls -la ~/.ssh/authorized_keys; the permissions must be 600 and the .ssh directory 700. If you are already locked out, use the VPS control panel's console access to fix the file, then test again before touching sshd_config.
nftables blocks SSH after a reboot. The service is enabled, so the rules load at boot, but you edited the file while the old ruleset was still active. After changing /etc/nftables.conf, always apply with sudo nft -f /etc/nftables.conf and verify with sudo nft list ruleset. Do not reboot until the new rules are confirmed working.
fail2ban bans your own IP. If you mistype your password several times, you will ban yourself. The ban lasts one hour by default with the configuration above. To unban immediately: sudo fail2ban-client set sshd unbanip your-ip-address. To avoid this on a server you manage from a fixed IP, add ignoreip = your-ip-address to the [DEFAULT] section of jail.local.
Why this checklist is different from a generic guide
Most guides stop at SSH keys and a firewall. That is a good start, but it misses the parts that actually get servers in trouble: automatic updates and log monitoring. A server that never applies security patches is vulnerable no matter how strong your SSH key is. A server without fail2ban is a magnet for brute-force noise that buries real alerts.
The order matters too. You update the system first, because patching before you change configuration avoids the situation where an outdated package breaks a new config. You set up SSH keys before the firewall, because the key must be in place before you lock the door. You add fail2ban after the firewall, because it protects the one port you deliberately left open. Work through the checklist in order and every step builds on the one before it. If you are planning a China-facing deployment, the same baseline applies, then you layer a VPN on top; see our guide on setting up a VPS VPN for China users for that next step.
FAQ
Is Debian 12 or Debian 13 better for a production VPS?
Both are solid. Debian 12 is the long-term supported release with the most mature package set. Debian 13 is the current stable and is fine for production in 2026. If you need the newest kernel and toolchain, use Debian 13. Otherwise, Debian 12 gives you the longest supported lifecycle. The hardening steps in this guide are identical on both.
Do I need to change the default SSH port?
Changing the port from 22 to something like 2222 reduces automated scan noise, but it is not real security. A determined attacker will find the port with a full scan. The protection comes from key-only authentication and fail2ban, not from hiding. If you do change it, remember to update the nftables rule and your SSH client config.
How often should I re-run the harden Debian VPS Vietnam security checklist?
Run it once on a fresh install, then re-check the listening ports and SSH config after every major change, like installing a new service or opening a new port. Automatic updates handle the day-to-day patching. A full audit once per quarter is reasonable for a small production server.
What is the difference between nftables and iptables on Debian?
nftables is the modern replacement for iptables. It is the default on Debian 12 and 13, has a cleaner syntax, and performs better with complex rule sets. iptables still works through a compatibility layer, but new configurations should use nftables. This guide uses nftables throughout.
Does hardening affect performance?
Negligibly. A stateful firewall and fail2ban add microseconds of latency per connection. The SSH key exchange is faster than password authentication. The real performance win is that you are not wasting CPU cycles on brute-force attempts and background malware scans.
Related articles
- Hardening SSH on a new VPS: keys, ports, fail2ban and CrowdSec
- Set up an nftables firewall on a VPS to replace iptables
- Security audit and hardening with Lynis on a VPS
- How to configure the UFW firewall on an Ubuntu VPS
That is the full baseline. Work through the steps once and a production Debian box stops being a liability and starts being a server you can actually operate. The whole checklist takes about thirty minutes on a fresh install. If you want a shortcut, a Linux VPS from a provider that gives you full root access and a clean IPv4 makes the process straightforward, and the same steps apply whether you rent the cheapest plan or a larger one. For most workloads, a 2GB RAM VPS with Debian 12 and this checklist is a defensible production setup. Deploy, verify, and move on to the actual work.
Debian VPS 安全加固要点
生产环境的 Debian VPS 必须按顺序完成安全加固:先更新系统并启用自动安全更新,然后配置 ED25519 SSH 密钥登录并禁用密码认证,再用 nftables 设置状态防火墙,最后部署 fail2ban 阻止暴力破解。每次修改后都要用独立会话验证,避免把自己锁在服务器外。这套检查清单在 Debian 12 和 13 上完全适用,是上线前必须完成的基础工作。


