How to Add Passkeys to Your Self-Hosted Apps and Homelab

··11 min read
How to Add Passkeys to Your Self-Hosted Apps and Homelab

If you run a homelab, you almost certainly have a password problem you haven't admitted to yet. Maybe it's the shared admin password on your Proxmox box, your Nextcloud instance, your Home Assistant dashboard, and your Vaultwarden install. Maybe it's the same passphrase you've reused since 2019 because typing a 24-character string into a TV browser is its own special torture. Either way, the attack surface is bigger than you think, and the credential is the weakest link.

Here's a stat worth sitting with: according to Verizon's Data Breach Investigations Report, stolen or weak credentials are involved in the majority of breaches year after year, and phishing remains one of the top initial access methods. Passwords, even strong ones, can be phished, leaked, and replayed. Passkeys can't be. A passkey is bound to the origin it was created for, so a fake login page at nextcloud-login.evil.example simply cannot trick your authenticator into handing over a credential for your real domain.

This guide walks through exactly how to add passkeys to your self-hosted apps and homelab — what they are, what actually supports them today, how to set them up on Nextcloud, Vaultwarden, and a reverse proxy with Authelia, and where the sharp edges hide. Everything here comes from running these tools, breaking them, and fixing them.

Key Takeaways
  • Passkeys are phishing-resistant by design because the credential is cryptographically bound to your exact domain — copycat login pages can't harvest them.
  • To use passkeys on a homelab you need HTTPS with a valid certificate and a real domain name (or a properly trusted internal CA). http://192.168.1.x will not work.
  • Centralizing passkey login behind an identity provider or reverse proxy (Authelia, Authentik, Keycloak) is far cleaner than bolting WebAuthn onto every app individually.
  • Always keep at least two registered authenticators plus a recovery method. A lost passkey with no backup means a locked door.
  • Hardware keys (YubiKey, etc.) give you portable, syncless passkeys; platform passkeys (iCloud, Google Password Manager, Windows Hello) give you convenience and sync.

What Are Passkeys, and Why Self-Hosters Should Care

A passkey is a FIDO2/WebAuthn credential: a public-private key pair where the private key never leaves your device (or your synced keychain), and the server only ever stores the public key. When you log in, your device signs a challenge, the server verifies the signature against the stored public key, and you're in. There is no shared secret to steal.

For self-hosters, three properties matter most:

  • Phishing resistance. The credential is scoped to a Relying Party ID (your domain). It won't fire on a lookalike domain. This kills credential phishing dead.
  • No server-side secret to leak. If someone dumps your database, they get public keys. Useless without the matching private key.
  • No reusable password. Nothing to brute-force, nothing to spray across your other services.

The catch for homelabs is the prerequisite list. WebAuthn requires a secure context, which in practice means HTTPS with a valid certificate and a real hostname. This is the single most common reason homelab passkey setups fail, so we'll deal with it head-on before touching any app.

Passkeys vs. Passwords vs. TOTP: What You're Actually Trading

People conflate "2FA" with "passkeys," but they solve different problems. Here's how the common options stack up for a typical homelab login:

Method Phishing-resistant Server stores a secret? Needs HTTPS Login friction Recovery pain
Password only No Yes (hash) No (but you should) Low Low
Password + TOTP No (codes are phishable) Yes (shared seed) No Medium Medium
Password + hardware key (U2F) Yes Yes (password hash) Yes Medium Medium
Passkey (platform, synced) Yes No (public key only) Yes Very low Medium
Passkey (hardware, device-bound) Yes No (public key only) Yes Low Higher

Notice that TOTP, the classic homelab 2FA, is still phishable: a fake login page can ask for the 6-digit code and replay it within the 30-second window. Passkeys close that gap entirely.

The Prerequisite Nobody Mentions: HTTPS and a Real Domain

You cannot register a passkey on http://nextcloud.local or a bare LAN IP. WebAuthn only runs in a secure context. There are three sane ways to get there in a homelab.

  1. Public domain + Let's Encrypt (recommended). Point a real subdomain like cloud.yourdomain.com at your reverse proxy. Use a DNS-01 challenge so you never have to expose port 80, and your internal services can stay internal while still getting trusted certificates.
  2. Split-horizon DNS. Resolve cloud.yourdomain.com to your internal IP on the LAN, and use the same Let's Encrypt certificate. Browsers see a valid cert and a real hostname — exactly what WebAuthn wants.
  3. Internal CA. Run your own certificate authority (e.g. with step-ca) and install the root cert on every client device. This works but is brittle: forget to trust the CA on a new phone and passkeys silently break.

Option 1 or 2 is what I run. A reverse proxy like Caddy, Traefik, or Nginx Proxy Manager handles TLS termination and gives every app a clean HTTPS hostname. Once that's in place, the actual passkey setup is almost anticlimactic.

If you're hardening a homelab seriously, layering matters. The same mindset that drives disabling xmlrpc.php to stop brute-force attacks applies here: shrink the attack surface before you add convenience features on top.

How to Add Passkeys to Nextcloud (Step by Step)

Nextcloud has supported WebAuthn passwordless login for years through the built-in WebAuthn app. Here's the full walkthrough.

  1. Confirm HTTPS. Open Nextcloud at its real HTTPS domain. Check the address bar for a valid lock icon. If you see a certificate warning, stop and fix the proxy first.
  2. Set trusted_domains correctly. In config/config.php, make sure your domain (e.g. cloud.yourdomain.com) is listed, and that overwriteprotocol is set to https if you terminate TLS at a proxy.
  3. Enable the WebAuthn app. Go to Apps → Security and confirm "WebAuthn" is enabled (it usually is by default).
  4. Register a device. Click your profile → Settings → Security. Scroll to Passwordless Authentication / Devices, click Add WebAuthn device, name it (e.g. "iPhone 15" or "YubiKey 5C"), and follow the OS prompt to create the passkey.
  5. Test in a private window. Log out, open a private browsing window, and use "Login with a device" instead of typing your password. Confirm the passkey flow completes.
  6. Register a second device. Do not skip this. Add a hardware key as a backup so a lost phone doesn't lock you out.

A Real Before/After Worked Example

Say your homelab has 9 self-hosted services: Nextcloud, Vaultwarden, Home Assistant, Jellyfin, Gitea, Grafana, Portainer, Paperless-ngx, and a router admin page. Before passkeys, you had 4 unique passwords reused across those 9 services and TOTP on only 3 of them. That's 6 services protected by phishable credentials.

After consolidating logins behind a single identity provider with passkeys (covered next), you go from 9 separate password prompts to 1 phishing-resistant login. The number of phishable secrets drops from 4 to 0. Login time per service drops from roughly 15 seconds of typing and code entry to about 2 seconds of a fingerprint touch. Multiply that across a dozen daily logins and the convenience pays for the setup time within a week.

How to Add Passkeys to Vaultwarden

Vaultwarden, the lightweight Bitwarden-compatible server, is a special case because it is your password manager. You want it locked down hard.

  1. Serve over HTTPS. Same rule as always. Route vault.yourdomain.com through your reverse proxy with a valid cert.
  2. Enable WebSocket and proper headers at the proxy so the web vault behaves correctly.
  3. Log in to the web vault and go to Settings → Security → Two-step Login.
  4. Add a FIDO2 WebAuthn key as a second factor. Vaultwarden supports passkeys both as a 2FA method and, in newer clients, for passkey login itself.
  5. Store recovery codes offline. Vaultwarden generates a recovery code when you enable two-step login. Print it or write it down and put it somewhere physical. If you lose access to your authenticator and your recovery code, your vault is gone.

One honest tradeoff: because Vaultwarden holds the keys to your kingdom, I keep a hardware-key passkey registered there specifically, not just a synced platform passkey. If your cloud account is ever compromised, a device-bound hardware key is a much harder target.

The Smarter Pattern: Centralize Passkeys Behind a Reverse Proxy

Adding passkeys app-by-app gets tedious fast, and

Cover image: Software value feedback loop by jakuza, licensed under BY-SA 2.0 via Openverse.

Recent Posts

View all →

Most Popular Software

View all →

Browse by Platform

View all →