Every other security decision in your homelab is scoped to one service. If Vaultwarden gets popped, you lose your passwords. If Jellyfin gets popped, someone can watch your movies. If your Proxmox host gets popped, the attacker owns every VM and LXC running on it, plus whatever network access those guests have. The hypervisor is the one layer where “harden it properly” isn’t optional homelab polish, it’s the thing that determines whether a bad day stays contained to one service or takes out the whole stack.
This isn’t about the Proxmox firewall or RBAC permissions, both of which already have their own dedicated treatment on this site. This is about the host itself: the SSH daemon, the web UI login, and the root account that both of those ultimately answer to. Three different doors, and most homelab builds leave at least one of them wide open by default.
Why root-over-SSH-with-a-password is the first thing to kill
Proxmox ships with root SSH access enabled and, depending on how you installed it, password authentication turned on. That combination means the entire host is one guessed or leaked password away from full compromise, and root means full compromise with no privilege escalation step required at all.
Fix it in two moves. First, get key-based auth working before you touch anything else, so you don’t lock yourself out:
# from your workstation, not the Proxmox host
ssh-copy-id root@your-proxmox-host
Confirm you can log in with the key alone, then disable password auth in /etc/ssh/sshd_config:
PasswordAuthentication no
PermitRootLogin prohibit-password
prohibit-password (not no) keeps root login available over SSH, but only with a key, never a password. That’s the right default for a single-operator homelab, you still want emergency key-based root access from the one machine you trust, you just never want a guessable secret to be the thing standing between the internet and root.
Restart sshd and test from a second terminal before closing your first session, the oldest lesson in remote administration and still the one that bites people who skip it:
systemctl restart sshd
If you’re running a cluster, repeat this on every node. SSH key trust between cluster nodes themselves is separate and Proxmox manages that internally, this is specifically about external access into each node.
fail2ban: catching what key-only auth doesn’t stop
Disabling password auth closes the door to brute-forcing SSH, but it doesn’t do anything about the web UI login on port 8006, which still accepts a username and password by design, and which the internet-wide scanning bots will absolutely find if that port is reachable from outside your network. fail2ban is the standard answer: watch the auth logs, and ban an IP after too many failed attempts in too short a window.
Install it and enable the Proxmox-specific jail, which ships with recent Debian/Proxmox fail2ban packages:
apt install fail2ban
Create /etc/fail2ban/jail.d/proxmox.conf:
[proxmox]
enabled = true
port = https,http,8006
filter = proxmox
logpath = /var/log/daemon.log
maxretry = 3
bantime = 3600
findtime = 600
This bans an IP for an hour after three failed web UI login attempts inside ten minutes. Check fail2ban-client status proxmox after a deliberate bad-password test to confirm the jail is actually catching attempts, a misconfigured logpath or filter will silently do nothing while looking like it’s working, and you won’t find out until you need it.
Pair this with the same jail config for sshd if you haven’t already (most Debian-based fail2ban installs enable sshd by default), even with key-only auth there’s no harm in also banning IPs that spam connection attempts, it keeps log noise down if nothing else.
Two-factor on the web UI, and why TOTP alone isn’t the end of it
TOTP two-factor for the Proxmox web UI gets a brief mention in the permissions article on this site, worth going deeper on here because of one detail that trips people up: losing your TOTP device locks you out of the web UI with no built-in recovery flow from that same UI. Proxmox doesn’t have an email-based reset or a support line to call.
The actual safety net is the recovery keys Proxmox generates when you enable TOTP, a one-time list of codes shown exactly once at setup time. Save them somewhere that isn’t the Proxmox host itself, a password manager vault or printed and stored physically both work. If you skip past that screen without saving them, your only recovery path if you lose the device is console access to the host (physical or IPMI/iDRAC/iLO, covered in its own article on this site) to re-run the TOTP enrollment as root from the command line.
Proxmox 8 also supports WebAuthn (hardware security keys, or a platform authenticator like a laptop’s fingerprint reader) as a second factor, configured the same place as TOTP under Datacenter > Permissions > Two Factor. It’s a better fit than TOTP if you already own a hardware key for other services, no code to type, no app to have your phone unlocked for, and a hardware key is harder to phish than a 6-digit code someone could social-engineer out of you.
Whichever method you pick, turn it on for every account with real reach, not just root. A compromised low-privilege PAM account is still a foothold.
Stop exposing port 8006 to the internet at all
Everything above reduces risk on an exposed management interface. The better move is to not expose it in the first place. There’s close to zero legitimate reason to port-forward 8006 (or 22) from your router to your Proxmox host, and doing so puts your hypervisor’s login prompt directly in front of every scanning bot on the internet, fail2ban and 2FA included.
If you need remote access to manage Proxmox from outside your network, put it behind a VPN overlay instead, WireGuard, Tailscale, or ZeroTier all work for this and each has its own comparison article on this site. Connect to the VPN first, then hit https://10.x.x.x:8006 over that tunnel exactly as if you were on the home network. The management plane never touches the public internet at all, which is a categorically different risk posture than “exposed but hardened.”
Stop using root for day-to-day admin
This one’s less about a single vulnerability and more about blast radius. If you log into the web UI as root for everything, every mistake, every leaked session, every malicious script you accidentally paste into a shell, happens with full privileges by default. The permissions/RBAC article on this site covers building a scoped PAM or PVE-realm user with a role like PVEAdmin instead of root; the short version here is: create that user once, use it for routine VM/LXC management, and reserve actual root login for the handful of tasks that genuinely require it (host package updates, storage configuration, fixing a broken cluster). It costs one extra login prompt and buys you a real ceiling on what a mistake or a compromised session can do.
Keep the host itself patched
None of the above matters much if the underlying Debian base and PVE packages are sitting unpatched for known CVEs. Proxmox’s own upgrade cadence (no-subscription repo, apt pinning, major version jumps) has its own dedicated article here; the hardening-specific point is narrower: security patches for openssh-server, the kernel, and fail2ban itself are worth applying promptly even between major PVE version jumps, they’re small, low-risk updates compared to a full version upgrade, and they close real attack surface. apt update && apt list --upgradable on a regular cadence, even just monthly, catches most of it.
The combination is the point
No single one of these is exotic. Key-only SSH, fail2ban, 2FA, a VPN instead of a port-forward, and a non-root daily account are all well-known practices individually. What actually matters is running all five together, because each one covers a gap the others leave open: key-only SSH stops password brute-forcing but does nothing for the web UI; fail2ban slows down attackers but doesn’t stop a correctly-guessed credential; 2FA stops a leaked password but not a session hijack; a VPN removes the exposed surface entirely but only if you actually use it instead of leaving a port forward around “just in case.” Layered together, compromising the one host that can take down your whole homelab stops being a single mistake away and starts requiring several independent failures at once.