๐งญ Overview
This is a walkthrough of my secure, private, self-hosted password manager setup using:
- Vaultwarden (Bitwarden-compatible Rust rewrite)
- Docker
- Traefik as a reverse proxy
- Cloudflare Tunnel for remote HTTPS access
- Tailscale for internal LAN access
๐ ๏ธ My Setup
Component | Role |
---|---|
Vaultwarden | Password manager backend |
Traefik | Reverse proxy & TLS termination |
Cloudflare Tunnel | Exposes Vaultwarden securely without port-forwarding |
Docker Compose | Orchestration layer |
Tailscale | VPN mesh for local/private access |
๐งฑ Folder Structure
~/docker/vaultwarden/
โโโ docker-compose.yml
โโโ traefik_dynamic.yml
โโโ .env
โโโ data/
โ๏ธ docker-compose.yml
version: "3.8"
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
environment:
- WEBSOCKET_ENABLED=true
env_file:
- .env
volumes:
- ./data:/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.vaultwarden.rule=Host(`vaultwarden.neilpatterson.dev`)"
- "traefik.http.routers.vaultwarden.entrypoints=websecure"
- "traefik.http.routers.vaultwarden.tls.certresolver=cloudflare"
- "traefik.http.services.vaultwarden.loadbalancer.server.port=80"
networks:
- web
networks:
web:
external: true
๐ .env
File
# Vaultwarden admin panel (optional)
ADMIN_TOKEN=supersecureadminkey
# Encryption key (auto-generated on first run or provide your own)
DATABASE_URL=data/db.sqlite3
Restrict file permissions:
chmod 600 .env
๐ DNS & Cloudflare Setup
- Add a DNS record in Cloudflare:
- Type:
CNAME
- Name:
vaultwarden
- Target:
your-cloudflare-tunnel-id.cfargotunnel.com
- Proxy: โ enabled
- Set up Cloudflare Tunnel:
cloudflared tunnel create vaultwarden-tunnel
cloudflared tunnel route dns vaultwarden-tunnel vaultwarden.neilpatterson.dev
- Define config in
/etc/cloudflared/config.yml
:
tunnel: vaultwarden-tunnel
credentials-file: /etc/cloudflared/vaultwarden-tunnel.json
ingress:
- hostname: vaultwarden.neilpatterson.dev
service: http://localhost:80
- service: http_status:404
- Start the tunnel:
sudo systemctl start cloudflared
๐ Access Over Tailscale
- You can also access Vaultwarden via local Tailscale IP:
http://100.x.y.z:PORT
- Useful for maintenance or as a backup path if Cloudflare Tunnel goes down.
โ Security Notes
- Vaultwarden encrypts all data client-side.
- Traefik terminates TLS using Let's Encrypt (or Cloudflare DNS challenge).
- Cloudflare Tunnel eliminates port-forwarding and public IP exposure.
- Admin panel protected via
ADMIN_TOKEN
env var.
๐งช Restore & Backup
Backups
I backup the /data
folder with Restic:
restic backup ~/docker/vaultwarden/data
Restore
- Just copy
db.sqlite3
and config JSON to a fresh container
๐ก Final Thoughts
This setup has been stable, private, and cost-effective. I get:
- Browser extensions & mobile app support
- No recurring fees
- Full control of my data
- Local + remote access