Self-hosted 2FA: Proxmox, Home Assistant, Nextcloud, and your VPN
Turning on 2FA across a homelab: Proxmox VE, Home Assistant, Nextcloud, Synology DSM, and your VPN, plus recovery plans that survive an admin lockout.

Your homelab probably has a hostname forwarded through your router, a TLS certificate from Let's Encrypt, and a login page one password away from full control of the house. The hypervisor that runs everything, the automation that controls the front door, the NAS with the family's entire history — each of them ships a second factor, and in most racks all of them sit switched off. The codes involved are ordinary TOTP, the same six-digit standard your bank uses. What changes is where the toggle hides and what happens the day you are the one locked out.
Here is the tour: Proxmox VE, Home Assistant, Nextcloud, Synology DSM, and the VPN question that ties self-hosting in knots.
Proxmox VE
The Proxmox VE administration guide devotes a chapter to two-factor authentication, and the implementation is more thorough than most commercial panels. Per user, TOTP enrollment lives behind the TFA button — reachable from the Two Factor view under Datacenter → Permissions, the user list, or the top-right username menu. The dialog randomizes a Base32 secret, takes an issuer name, shows a QR code, and asks for your password to confirm. WebAuthn is a first-class alternative, so a hardware key or a laptop's TPM can be the second factor, and single-use recovery keys ship alongside both.
Admins can also enforce a second factor per authentication realm via the TFA dropdown, choosing TOTP or YubiKey OTP — at which point users without a factor configured simply cannot log in. The failure handling is specified: eight failed TOTP attempts disable the user's TOTP factors, and recovery comes from a recovery key or an admin running pveum user tfa unlock. WebAuthn and recovery keys get a higher allowance of 100 tries, then a one-hour block. That is a lockout policy you can actually reason about.
Home Assistant
Home Assistant's multi-factor authentication docs describe a TOTP module that is already there: if your configuration.yaml defines no auth_mfa_modules section, a module named "Authenticator app" is loaded automatically. Nothing to install — you enable it per account under User profile → Security, in the Multi-factor authentication modules section. Click Enable, get a secret and QR code, pair your authenticator app, enter a code to confirm, and every future login wants the six digits after the password. The docs warn about the obvious footgun: TOTP is only as good as the host clock, so keep the machine on NTP.
There is also a notify module that sends an HMAC-based one-time password through any notify target — a creative fallback when someone refuses an authenticator app. WebAuthn is the honest caveat: it is not in the official docs as a core MFA module. Passkey sign-in exists through a third-party WebAuthn MFA integration — community-maintained, a reasonable trade for a house, a bigger one for a company.
Nextcloud
Nextcloud keeps 2FA in apps. The administrator enables the Two-Factor TOTP provider, after which each account turns it on in personal settings: the user manual walks through the Second-factor Auth section, where you see the secret and QR code, pair the app, and verify one code before the factor goes live. A WebAuthn app adds hardware keys as another second factor, and the manual's fine print matters: don't reuse a token you use for passwordless WebAuthn login as your 2FA device, or you are back to one factor wearing two hats.
Two Nextcloud-specific details matter. Backup codes are generated from the same settings screen — one-time codes that function as a spare second factor, which the manual tells you to store separately from the phone. And once 2FA is on, plain-password clients stop working: desktop apps and phone clients need device-specific app passwords instead. That is by design, and it is the first thing to tell anyone who shares your instance.
Synology DSM
Synology's DSM calls it 2-Factor Authentication and puts it in Personal → Security. Three second factors are supported: a push-style Approve sign-in through Synology's own Secure SignIn app, a verification code via any TOTP app — the docs name Google Authenticator explicitly — and a hardware security key. The OTP wizard shows a QR code with a manual secret fallback, demands a working code before finishing, then insists on a verified backup email address that can receive codes when the paired device is gone. Trusted devices can be remembered per browser and revoked in a list when that stops being wise.
The DSM 6.2-era label was "2-step verification," and older Synology guidance still uses it — same feature, older skin. The package ecosystem mostly follows the account-level factor, and Synology publishes a separate article listing which packages support it fully, worth a read before you rely on it for everything.
The VPN question
This is where self-hosted 2FA gets philosophical, because the two popular tunnels have opposite answers.
OpenVPN Access Server has TOTP built in: an admin flips Require MFA in the Admin Web UI under Authentication — globally, per group, or per user — and each user enrolls at the Client Web UI on next sign-in, scanning a QR code or typing the plaintext key and confirming one code. The server accepts the immediately preceding and following codes to absorb drift, and its install images run NTP by default. One limit: built-in TOTP does not combine with SAML authentication, where the IdP is expected to carry the MFA.
WireGuard has nothing to type. The protocol authenticates peers by public key exchange and contains no password prompt, so there is nowhere in the handshake for a six-digit code. The self-hoster's workarounds are all "put the factor in front of the tunnel": issue peer profiles only through an admin surface that itself has 2FA, or terminate authentication with a RADIUS server such as privacyIDEA that validates TOTP before a session is allowed — the verification logic involved is the same material covered in implementing TOTP. If you are the only user, the honest assessment is that protecting the portal and keeping the tunnel config off the internet does most of the same work.
The admin lockout problem
The worst 2FA failure is not "attacker got in" — it is "the only person with console rights cannot." Every platform above recovers differently, and none of them does it for you.
The pattern that survives contact with reality is threefold. Generate recovery keys or backup codes at enrollment, every time, and store them where the phone is not — a printed sheet, or an offline vault as covered in the KeePass guide. Keep a second admin account on each platform with its own factor, because one locked-out owner is a support ticket and two is a rounding error. And keep one out-of-band path that bypasses the web login entirely — the hypervisor's console, SSH with keys, the physical machine. Home Assistant's own locked-out guide is explicit about this: owner recovery happens in a terminal over console access, never in the web UI you are locked out of. If your codes come from a phone that dies, an offline TOTP copy on a laptop or in the installed PWA turns a bad evening into a small delay.
When you run enough services, get a hub
Past a half-dozen services, per-app 2FA stops scaling: six enrollments, six recovery schemes, six chances to misconfigure. privacyIDEA is the purpose-built answer — an open-source authentication server on Linux that fronts VPNs, SSH, web portals, and local logins with a second factor through RADIUS, SAML, or its own APIs. The lighter-weight version is Keycloak, the open-source identity provider with TOTP enrollment built into every account: point your apps at it over OIDC or SAML, enforce one-time passwords per realm, and your second factors live in one place. The trade is real — a Keycloak outage is now everyone's outage — so size it honestly.
The settings, in one table
| Platform | Methods | Where the setting lives | Recovery mechanism |
|---|---|---|---|
| Proxmox VE | TOTP, WebAuthn, YubiKey OTP | TFA button — Datacenter → Permissions → Two Factor, or username menu | Recovery keys, admin pveum user tfa unlock |
| Home Assistant | TOTP, notify HOTP | User profile → Security → MFA modules | Console owner reset (locked-out guide) |
| Nextcloud | TOTP, WebAuthn | Personal settings → Second-factor Auth | One-time backup codes |
| Synology DSM | OTP, Approve sign-in, security key | Personal → Security → 2-Factor Authentication | Backup email codes, trusted devices |
| OpenVPN AS | TOTP | Admin Web UI → Authentication → Require MFA | Admin regenerates enrollment |
| WireGuard | None native | Guard the portal or add RADIUS/privacyIDEA | Portal-side policy |
Frequently asked questions
Is TOTP enough for internet-exposed services?
As a baseline, yes — it defeats credential stuffing, leaked passwords, and casual scanning outright, and it is what every platform in this post offers first. For panels that face the public internet, prefer WebAuthn where available, since a phishing page cannot relay a hardware key the way it can relay a six-digit code. And keep the network layer honest: a VPN or reverse proxy in front of the admin UI means the second factor guards a door that is not on the open internet to begin with.
What if I lock myself out of my own server?
Use the platform's designed escape hatch first: recovery keys on Proxmox, backup codes on Nextcloud, the verified backup email on Synology DSM. If those are gone, you need an out-of-band path — the hypervisor console, SSH, or physical access — plus, on Proxmox specifically, an admin who can clear the failed-attempt lockout on your account. This is why recovery material gets created at enrollment, not during the emergency. An admin lockout with no console access and no second admin is the one failure mode in self-hosting with no clean exit.
Can I add TOTP to WireGuard?
Not inside the protocol — WireGuard authenticates with key pairs and has no step where a code could be checked. The working patterns put the factor elsewhere: enroll peers only through a 2FA-protected portal, gate the tunnel with a RADIUS server like privacyIDEA, or run OpenVPN Access Server where TOTP is built in. Many homelabs instead keep WireGuard config distribution strictly manual and behind an authenticated surface, accepting that the tunnel itself trusts keys alone. That is a defensible design as long as the portal is the guarded part.
Do I need a different authenticator app for each service?
No. One authenticator app holds entries for all of them — Proxmox, Home Assistant, Nextcloud, DSM, and your VPN each become one more line in the same list, distinguished by issuer. The real question is backup: with every second factor in one app, that app's survival is your survival, so keep an exported or written copy of the secrets somewhere encrypted, and the recovery codes the platforms generate somewhere else. One app, many entries, two independent backups.
Should I self-host a 2FA hub like Keycloak?
If you run more than a handful of services, or other people log in to them, a hub starts earning its keep: one enrollment per person, one recovery process, one place to enforce policy across everything over OIDC or SAML. For a single-admin homelab, per-app 2FA is simpler and fails more gracefully — Keycloak down means everyone down. A middle path is privacyIDEA as a policy server for the VPN and SSH without becoming the identity source for every web app. Match the hub to the number of humans, not the number of containers.
One last habit before you start flipping toggles: test each enrollment immediately. Paste the secret or QR code your server just generated into the guest generator and confirm both sides show the same six digits — everything is computed in the page with zero network requests — before you commit your only admin account to it.