← Self-Hosting · Security & Privacy · Replaces: LastPass, 1Password, Bitwarden cloud
What You'll Build
Vaultwarden is a small, fast server that works with the official Bitwarden apps and browser extensions. You get Bitwarden's polished apps, including autofill, passkeys, and TOTP codes, with the vault stored on your own server.
Port: 8082 · RAM: tiny (~50 MB) · Time: 30 minutes · Difficulty: Medium
This is your most important app. Lose this server without a backup and you lose every password. Don't move your passwords in until backups are running and you've tested a restore. Keep the Bitwarden apps' offline copies enabled too.
What You Need
- Your home server from Foundations 1 (Docker installed,
~/stacksfolder). - Nginx Proxy Manager with your
*.home.example.comcertificate — required for this app. - Nothing else — but HTTPS is mandatory: the web vault refuses to work over plain http.
Step 1: Start Vaultwarden
mkdir -p ~/stacks/vaultwarden && cd ~/stacks/vaultwarden
nano compose.yaml
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
ports:
- "8082:80"
environment:
DOMAIN: "https://vault.home.example.com" # must match your proxy address, with https
SIGNUPS_ALLOWED: "true" # ← set to "false" after Step 3!
volumes:
- ./data:/data # the encrypted vault database
docker compose up -d
Step 2: Add the HTTPS Proxy Host
Nginx Proxy Manager: vault.home.example.com → http, 192.168.1.50, port 8082, Websockets on (needed for live sync), wildcard certificate, Force SSL.
Step 3: Create Your Account, Then Lock Sign-Ups
- Open
https://vault.home.example.com→ Create account. - Choose a long master password (4–5 random words works well). It can never be recovered — write it down and store it somewhere physically safe.
- Create accounts for family members now too.
- Turn sign-ups off: in
compose.yamlsetSIGNUPS_ALLOWED: "false", thendocker compose up -d. - In the web vault: Settings → Security → Two-step login → set up an authenticator app. Save the recovery code.
Step 4: Secure the Admin Page (Optional)
The /admin page lets you invite users and change settings. It's disabled until you set a token. Use a hashed one:
# Generate an argon2 hash of a password you choose (it asks you to type it twice)
docker exec -it vaultwarden /vaultwarden hash
Copy the $argon2id$... output into compose.yaml under environment:. Double every $ sign ($$) — Compose treats a single $ as a variable:
ADMIN_TOKEN: "$$argon2id$$v=19$$m=65540,t=3,p=4$$...rest-of-hash..."
docker compose up -d
# Now visit https://vault.home.example.com/admin and log in with the password you hashed
Step 5: Connect the Bitwarden Apps and Import
- Install Bitwarden on your phone, the browser extension, and optionally the desktop app.
- On the login screen, change the region/server to Self-hosted and enter
https://vault.home.example.com. - Import: export from your old manager (Chrome, Firefox, LastPass, 1Password all support CSV/JSON export), then web vault → Tools → Import data. Delete the export file afterwards — it's unencrypted.
- On your phone, set Bitwarden as the system autofill service.
With Tailscale on, the apps sync from anywhere. Without it, they still work offline from their cached copy and sync when you're home.
Add It to Your Proxy, Dashboard, and Backups
- Nginx Proxy Manager: new proxy host
vault.home.example.com→ schemehttp,192.168.1.50, port8082, Websockets on, your wildcard certificate, Force SSL. - Homepage: add a tile in
services.yaml(how). - Uptime Kuma: add an HTTP monitor for the new address (how).
- Backups:
~/stacks/vaultwardenis already covered by the restic script. Test restoring it. The key files aredb.sqlite3,rsa_key*, and theattachmentsfolder.
Troubleshooting
- Web vault shows a blank page or a crypto error — you're using http. Always use the https proxy address.
- Apps don't update live between devices — Websockets aren't enabled on the proxy host.
- Admin token "invalid" — the
$signs weren't doubled incompose.yaml. - Can't log in on the phone — the app is still set to bitwarden.com. Switch to Self-hosted.