Passwords, passkeys, recovery codes, API tokens, SSH keys, and other credentials are easy to accumulate and difficult to manage safely. Keeping them in browser notes, plain-text files, or scattered across devices creates unnecessary risk. A private password vault provides one controlled place for these secrets, while still making them available when you actually need them.
My preferred approach is to combine a Bitwarden-compatible client with a self-hosted Vaultwarden backend. The result is a practical balance between convenience, portability, and control: random passwords can be generated automatically, passkeys can be used where supported, and the same vault can be accessed from mobile, desktop, and automation tools.
What this setup should provide
- Random passwords, passkeys, and autofill: generate unique credentials for every service and let the client fill them only on the intended domain.
- A private Vaultwarden service: keep the encrypted vault synchronised through infrastructure that you control.
- Access from mobile, desktop, and agents: use official Bitwarden-compatible clients for people and carefully scoped CLI or API integrations for automation.
- A recovery plan: make sure the vault can still be recovered if a device, disk, or account is lost.
The heart of security: the Vaultwarden backend
Vaultwarden is a lightweight, unofficial Bitwarden-compatible server implementation. It is well suited to a personal server, home lab, or small private environment because it uses fewer resources than the official server stack while supporting the core password-management workflow.
The server should be treated as sensitive infrastructure. Although the vault data is encrypted before it is stored, the backend still contains account records, encrypted vault blobs, attachments, login metadata, and operational logs. A compromise can also expose the availability and integrity of the service, so encryption at rest is not a substitute for network security, updates, backups, or strong account protection.
Deployment options
There are two practical deployment paths:
- Docker Compose: the simplest option for a single VPS, home server, or NAS. It is easy to understand, update, back up, and restore.
- Kubernetes: useful when the service belongs to an existing cluster and you already have persistent storage, ingress, secrets management, monitoring, and backup procedures in place.
For most personal deployments, Docker Compose is the better starting point. Kubernetes does not automatically make a password vault safer; it adds operational complexity that must itself be managed correctly.
Deploy Vaultwarden with Docker Compose
The following example assumes an Ubuntu or Debian-based server, a DNS record such as vault.example.com pointing to the server, and Docker Engine with the Docker Compose plugin already installed. Replace the example domain and email address with your own values.
1. Prepare the host
sudo apt update
sudo apt install -y ca-certificates curl
sudo mkdir -p /opt/vaultwarden/vw-data
sudo chown -R "$USER":"$USER" /opt/vaultwarden
cd /opt/vaultwardenOpen only the ports that are needed for SSH, HTTP, and HTTPS. If a firewall is enabled, allow ports 80 and 443 for certificate issuance and web access, while keeping the Vaultwarden application port bound to localhost.
2. Create the Compose file
Create /opt/vaultwarden/compose.yaml:
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
DOMAIN: "https://vault.example.com"
SIGNUPS_ALLOWED: "true"
ADMIN_TOKEN: ""
volumes:
- ./vw-data:/data
ports:
- "127.0.0.1:8080:80"The 127.0.0.1:8080:80 mapping is intentional: only the local reverse proxy can reach Vaultwarden. The vw-data directory contains the persistent database, attachments, and configuration data, so it must be included in backups.
Start the service and inspect its logs:
docker compose pull
docker compose up -d
docker compose logs -f vaultwardenKeep registration enabled only long enough to create the intended account. After that, change SIGNUPS_ALLOWED to "false" and recreate the container. Do not leave public registration open on an internet-facing instance.
3. Generate a protected admin token
The admin interface is available at /admin. Before enabling it, generate an Argon2 hash using the Vaultwarden container:
docker exec -it vaultwarden /vaultwarden hashEnter a separate, strong admin password when prompted. Copy the generated hash into ADMIN_TOKEN. When the hash is placed directly in a Compose file, escape each dollar sign as $$, because Compose interprets a single dollar sign as variable expansion. Alternatively, keep the value in a protected .env file and reference it as ADMIN_TOKEN: ${ADMIN_TOKEN}. Never commit either the raw password or the hash to a public repository.
After setting the token and disabling open registration, apply the hardened configuration:
docker compose up -d
docker compose psGenerate an SSL certificate with Let's Encrypt and Nginx
Vaultwarden should normally run behind a reverse proxy. Nginx terminates TLS, serves the Let's Encrypt certificate, redirects HTTP to HTTPS, and forwards requests to the local Vaultwarden container. This is preferable to exposing Vaultwarden's internal port or configuring TLS directly inside the application container.
1. Install Nginx and Certbot
sudo apt update
sudo apt install -y nginx certbot python3-certbot-nginx
sudo ufw allow 'Nginx Full'Make sure the DNS A or AAAA record for vault.example.com resolves to this server before requesting the certificate. Port 80 must be reachable from the internet when using the HTTP-01 challenge.
2. Add the Nginx reverse-proxy configuration
Create /etc/nginx/sites-available/vaultwarden:
server {
listen 80;
listen [::]:80;
server_name vault.example.com;
client_max_body_size 128M;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
location /notifications/hub {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Enable the site and verify the configuration:
sudo ln -s /etc/nginx/sites-available/vaultwarden /etc/nginx/sites-enabled/vaultwarden
sudo nginx -t
sudo systemctl reload nginx3. Request and install the certificate
Use Certbot's Nginx plugin to request a certificate and update the Nginx configuration automatically:
sudo certbot --nginx -d vault.example.comFollow the prompts, provide a valid email address, accept the terms, and choose the HTTP-to-HTTPS redirect when asked. Certbot will create the certificate under /etc/letsencrypt/live/vault.example.com/, configure Nginx to use fullchain.pem and privkey.pem, and reload Nginx.
Test renewal without waiting for the certificate to expire:
sudo certbot renew --dry-runDo not copy the private key into the Vaultwarden data directory or commit it to source control. The Nginx process needs access to the certificate files; Vaultwarden itself does not need to manage these files in this reverse-proxy design.
4. Switch Vaultwarden to its final HTTPS URL
After HTTPS is working, confirm that the Compose file contains the exact public URL:
DOMAIN: "https://vault.example.com"Then restart Vaultwarden:
docker compose up -dOpen https://vault.example.com in a browser and confirm that the certificate is valid, the web vault loads, registration is disabled if appropriate, and the /notifications/hub connection does not produce repeated proxy errors.
HTTPS is required—but the service does not need to be public
HTTPS is required for secure browser access and for WebAuthn-based passkeys. However, HTTPS does not mean that the vault must be exposed to the entire public internet. A safer design is to keep the service on a private network and reach it through a VPN or an identity-aware access layer such as WireGuard, Tailscale, or another trusted private tunnel.
If remote public access is genuinely necessary, place the service behind a maintained reverse proxy with a valid certificate, strict firewall rules, rate limiting, secure headers, and monitoring. Do not expose the container directly, and do not rely on an obscure URL as a security control.
Authentication and recovery
The master password protects access to the vault, so it should be long, unique, and memorable without being reused anywhere else. A password manager is only as strong as the recovery process around it.
- Enable two-factor authentication for the vault account.
- Store recovery codes offline in a protected location.
- Keep a second, independent recovery method for the server and domain.
- Test restoration instead of assuming that an untested backup works.
- Do not store the only copy of recovery information inside the vault itself.
Passkeys can reduce dependence on passwords for supported services, but they do not remove the need for account recovery. Availability depends on the client, browser, server configuration, and the target service's WebAuthn implementation. Keep a recovery method for every important account.
Backups are part of the vault
A self-hosted password manager is not complete until it has a backup strategy. Back up the Vaultwarden database, attachments, configuration, and any keys or secrets required to restore the deployment. Encrypt backups before they leave the server, keep at least one copy offline or in a separate location, and periodically perform a clean restore into an isolated environment.
Backups should follow the same principle as passwords: least privilege, limited access, and no unnecessary copies. Avoid putting database dumps into a synchronised folder or a public object-storage bucket.
Clients and everyday workflow
Use a trusted client on each device and keep the clients updated. The normal workflow should be simple:
- Create a unique random password for every new account.
- Save the login only after confirming the domain and username.
- Prefer passkeys when the target service supports them and the recovery path is clear.
- Store recovery codes and important API tokens as protected notes or suitable secret entries.
- Review reused, weak, and old credentials periodically.
- Remove access from lost or retired devices.
Autofill is convenient, but it should not be completely automatic everywhere. Confirm the origin before filling credentials, especially after following links from email, chat, or search results. Phishing pages often imitate the appearance of a legitimate login page while using a different domain.
Using the vault with agents and automation
Automation introduces a different threat model. An agent or script should not receive the master password or unrestricted access to the entire vault. Prefer short-lived, narrowly scoped credentials, read-only access where possible, and a separate collection for automation secrets.
- Expose only the exact secret needed for a task.
- Keep tokens out of prompts, logs, shell history, screenshots, and error reports.
- Use environment injection or a dedicated secret interface rather than copying secrets into source code.
- Rotate credentials after testing, debugging, or suspected exposure.
- Audit which agent, machine, or integration can read each secret.
The goal is not to make an agent behave like a human with full vault access. The goal is to give automation the smallest useful capability and make that capability easy to revoke.
Operational checklist
- Run the latest supported Vaultwarden release and update it deliberately.
- Restrict administrative access to a private network or trusted devices.
- Use HTTPS for every client connection.
- Disable public registration after the intended accounts have been created.
- Use strong firewall rules and monitor authentication failures.
- Protect the server's host, container runtime, and backup destination.
- Document the recovery procedure without documenting secret values.
- Review vault access, active sessions, and emergency recovery options regularly.
Closing thoughts
A password vault is not simply a place to put passwords. It is a small security system that connects identity, authentication, recovery, backups, devices, and automation. Vaultwarden can be a good foundation for a private setup, but the most important decisions happen around it: keep the service reachable only where necessary, use strong authentication, maintain tested backups, and give people and agents only the access they need.
Convenience is valuable, but controlled convenience is the real goal. A vault should make secure behaviour easier—not make every secret available everywhere.