Docker Compose Configuration for Password Managers
Ready-to-adapt Docker Compose files for running Vaultwarden and Bitwarden in containers, with networks, volumes, reverse proxy integration, and backup containers alongside.
Vaultwarden Basic Configuration
Minimal Setup
version: '3'
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
- ROCKET_PORT=8080
volumes:
- ./vw-data:/data
ports:
- "8080:8080" Production Configuration
version: '3'
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
# Domain configuration
- DOMAIN=https://vault.example.com
# Security settings
- SIGNUPS_ALLOWED=false
- INVITATIONS_ALLOWED=true
- SHOW_PASSWORD_HINT=false
# WebSocket for live sync
- WEBSOCKET_ENABLED=true
# SMTP configuration
- SMTP_HOST=smtp.example.com
- SMTP_FROM=vaultwarden@example.com
- SMTP_PORT=587
- SMTP_SECURITY=starttls
- SMTP_USERNAME=vaultwarden@example.com
- SMTP_PASSWORD=smtp_password
# Admin panel
- ADMIN_TOKEN=your_secure_admin_token
# Logging
- LOG_FILE=/data/vaultwarden.log
- LOG_LEVEL=info
volumes:
- ./vw-data:/data
ports:
- "8080:80"
- "3012:3012" # WebSocket port Vaultwarden with Traefik
Complete Stack with Traefik Reverse Proxy
version: '3'
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
- DOMAIN=https://vault.example.com
- WEBSOCKET_ENABLED=true
- SIGNUPS_ALLOWED=false
volumes:
- ./vw-data:/data
labels:
# Enable Traefik
- "traefik.enable=true"
# Main application
- "traefik.http.routers.vaultwarden.rule=Host(`vault.example.com`)"
- "traefik.http.routers.vaultwarden.entrypoints=websecure"
- "traefik.http.routers.vaultwarden.tls.certresolver=letsencrypt"
- "traefik.http.services.vaultwarden.loadbalancer.server.port=80"
# WebSocket
- "traefik.http.routers.vaultwarden-ws.rule=Host(`vault.example.com`) && Path(`/notifications/hub`)"
- "traefik.http.routers.vaultwarden-ws.entrypoints=websecure"
- "traefik.http.routers.vaultwarden-ws.tls.certresolver=letsencrypt"
- "traefik.http.services.vaultwarden-ws.loadbalancer.server.port=3012"
networks:
- traefik
networks:
traefik:
external: true Vaultwarden with External Database
With PostgreSQL
version: '3'
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
- DOMAIN=https://vault.example.com
- DATABASE_URL=postgresql://vaultwarden:password@postgres:5432/vaultwarden
- SIGNUPS_ALLOWED=false
volumes:
- ./vw-data:/data
depends_on:
- postgres
ports:
- "8080:80"
postgres:
image: postgres:15-alpine
container_name: vaultwarden-db
restart: unless-stopped
environment:
- POSTGRES_DB=vaultwarden
- POSTGRES_USER=vaultwarden
- POSTGRES_PASSWORD=password
volumes:
- ./postgres-data:/var/lib/postgresql/data With MySQL/MariaDB
version: '3'
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
- DOMAIN=https://vault.example.com
- DATABASE_URL=mysql://vaultwarden:password@mysql:3306/vaultwarden
- SIGNUPS_ALLOWED=false
volumes:
- ./vw-data:/data
depends_on:
- mysql
ports:
- "8080:80"
mysql:
image: mariadb:10
container_name: vaultwarden-db
restart: unless-stopped
environment:
- MYSQL_DATABASE=vaultwarden
- MYSQL_USER=vaultwarden
- MYSQL_PASSWORD=password
- MYSQL_ROOT_PASSWORD=rootpassword
volumes:
- ./mysql-data:/var/lib/mysql Environment Variable Management
Using .env File
Create .env file:
# Domain
DOMAIN=https://vault.example.com
# Security
SIGNUPS_ALLOWED=false
INVITATIONS_ALLOWED=true
ADMIN_TOKEN=your_secure_random_token
# SMTP
SMTP_HOST=smtp.example.com
SMTP_FROM=vaultwarden@example.com
SMTP_PORT=587
SMTP_SECURITY=starttls
SMTP_USERNAME=vaultwarden@example.com
SMTP_PASSWORD=smtp_password
# Database (if using external)
DATABASE_URL=postgresql://vaultwarden:password@postgres:5432/vaultwarden Reference in compose file:
version: '3'
services:
vaultwarden:
image: vaultwarden/server:latest
env_file: .env
volumes:
- ./vw-data:/data
ports:
- "8080:80" Container Resource Limits
Memory and CPU Limits
version: '3'
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
- DOMAIN=https://vault.example.com
volumes:
- ./vw-data:/data
ports:
- "8080:80"
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 256M Health Checks
Container Health Monitoring
version: '3'
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
- DOMAIN=https://vault.example.com
volumes:
- ./vw-data:/data
ports:
- "8080:80"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80/alive"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s Multi-Stack Deployment
Vaultwarden + Reverse Proxy + Database
docker-compose.yml:
version: '3'
services:
# Reverse Proxy
nginx:
image: nginx:alpine
container_name: nginx-proxy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- vaultwarden
# Vaultwarden Application
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
- DOMAIN=https://vault.example.com
- DATABASE_URL=postgresql://vaultwarden:password@postgres:5432/vaultwarden
- WEBSOCKET_ENABLED=true
- SIGNUPS_ALLOWED=false
volumes:
- ./vw-data:/data
depends_on:
- postgres
# Database
postgres:
image: postgres:15-alpine
container_name: postgres-db
restart: unless-stopped
environment:
- POSTGRES_DB=vaultwarden
- POSTGRES_USER=vaultwarden
- POSTGRES_PASSWORD=password
volumes:
- ./postgres-data:/var/lib/postgresql/data
networks:
default:
name: vaultwarden-network Management Commands
Starting Services
# Start all services
docker compose up -d
# Start specific service
docker compose up -d vaultwarden
# View logs
docker compose logs -f vaultwarden
# Check status
docker compose ps Updating Containers
# Pull latest images
docker compose pull
# Recreate containers with new images
docker compose up -d
# Or combine both
docker compose pull && docker compose up -d Backup with Compose
# Stop services
docker compose stop vaultwarden
# Backup volumes
tar -czf backup-$(date +%Y%m%d).tar.gz ./vw-data/
# Restart services
docker compose start vaultwarden Volume Management
Named Volumes vs Bind Mounts
Bind mounts (recommended for backups):
volumes:
- ./vw-data:/data # Easy to backup
- ./config.json:/data/config.json:ro # Read-only config Named volumes (Docker-managed):
services:
vaultwarden:
volumes:
- vaultwarden-data:/data
volumes:
vaultwarden-data:
driver: local Security Best Practices
Secrets Management
Using Docker secrets (Swarm mode):
version: '3.8'
services:
vaultwarden:
image: vaultwarden/server:latest
environment:
- DOMAIN=https://vault.example.com
- ADMIN_TOKEN_FILE=/run/secrets/admin_token
secrets:
- admin_token
volumes:
- ./vw-data:/data
secrets:
admin_token:
file: ./secrets/admin_token.txt Network Isolation
version: '3'
services:
vaultwarden:
image: vaultwarden/server:latest
networks:
- frontend
- backend
environment:
- DATABASE_URL=postgresql://vaultwarden:password@postgres:5432/vaultwarden
postgres:
image: postgres:15-alpine
networks:
- backend # Only accessible to vaultwarden
nginx:
image: nginx:alpine
networks:
- frontend # Only nginx is exposed
ports:
- "443:443"
networks:
frontend:
backend:
internal: true # No external access Troubleshooting
View Container Logs
# All logs
docker compose logs
# Specific service
docker compose logs vaultwarden
# Follow logs
docker compose logs -f vaultwarden
# Last 100 lines
docker compose logs --tail=100 vaultwarden Restart Services
# Restart specific service
docker compose restart vaultwarden
# Recreate container (rebuild)
docker compose up -d --force-recreate vaultwarden Debug Container
# Execute shell in container
docker compose exec vaultwarden sh
# Check environment variables
docker compose exec vaultwarden env
# Check processes
docker compose exec vaultwarden ps aux Related Documentation
- Vaultwarden Self-Hosted Deployment - Complete Vaultwarden guide
- Database Options for Self-Hosted Applications - Database configuration
- Reverse Proxy Configuration for Web Services - NGINX, Caddy, Traefik setup
- Password Manager Backup and Recovery Strategies - Backup procedures