Harden a VM

The platform enforces one rule on your machine — anti-spoof, which lets it send only from its own IP and MAC — and filters nothing else. There is no firewall API; you set the policy in the guest. **A rule that drops your own SSH locks you out until you boot rescue**: there is no console and no password.

Never apply a rule you cannot undo

Apply firewall and sshd changes with an automatic undo: schedule the revert *first*, confirm you still have access, then cancel the revert.

# 1. schedule the undo before you change anything
systemd-run --on-active=10min --unit=fw-revert nft flush ruleset

# 2. apply your ruleset
nft -f /etc/nftables.conf

# 3. from somewhere else, open a SECOND ssh session and confirm it works

# 4. only then, cancel the undo
systemctl stop fw-revert.timer

If step 3 fails, do nothing: the timer fires and the machine lets you back in. For ufw, step 1 is `systemd-run --on-active=10min --unit=fw-revert ufw disable`; the rest is the same. For sshd, the undo puts back a copy of the config:

cp -a /etc/ssh /root/ssh.bak
systemd-run --on-active=10min --unit=ssh-revert \
  sh -c 'rm -rf /etc/ssh && cp -a /root/ssh.bak /etc/ssh && systemctl restart ssh'
# change the config, restart ssh, then confirm a NEW session connects
systemctl stop ssh-revert.timer

Test with a new session while the old one is still open: the session you are holding survives a restart that broke the config.

Take a snapshot before any larger change; it is the only other way to undo one. It bills for as long as you keep it, and rolling back needs the VM stopped and leaves it stopped.

A policy that fits this platform

sshd

Key-only login is already the default, so the useful changes are small:

Run sshd -t before restarting: sshd will not start with a config it cannot parse, and then you cannot log in.

Already locked out: [Debug a VM that will not come up](debug-vm-boot.md#5-if-the-guest-locked-you-out).