Skip to main content

Vaultwarden

Quick Overview

Purpose: Self-hosted password manager compatible with Bitwarden
Category: Security & Collaboration
Access URL: https://vaultinas.billpantzartzis.info
Status: 🟢 Active

📋 Description

Vaultwarden is a lightweight, self-hosted password manager that implements the Bitwarden API. Written in Rust, it offers a resource-efficient alternative to the official Bitwarden server while maintaining full compatibility with Bitwarden clients. Perfect for individuals and small teams who want complete control over their password data.

Key Features

  • Full Bitwarden Compatibility: Works with all official Bitwarden apps and browser extensions
  • Low Resource Usage: Runs efficiently on minimal hardware (< 100MB RAM)
  • WebSocket Support: Real-time sync across all devices
  • 2FA Support: TOTP, U2F, YubiKey, and Duo authentication
  • Organizations: Share passwords securely with teams
  • File Attachments: Store secure notes and files
  • Admin Panel: Built-in administration interface
  • Send Feature: Securely share text and files with anyone

🏗️ Architecture

🚀 Deployment

docker-compose.yml
version: '3.8'

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"

# Admin panel
ADMIN_TOKEN: "${ADMIN_TOKEN}" # Generate with: openssl rand -base64 48

# WebSocket
WEBSOCKET_ENABLED: "true"

# SMTP Configuration
SMTP_HOST: "smtp.gmail.com"
SMTP_PORT: 587
SMTP_SECURITY: "starttls"
SMTP_FROM: "vault@example.com"
SMTP_USERNAME: "${SMTP_USERNAME}"
SMTP_PASSWORD: "${SMTP_PASSWORD}"

# Database
DATABASE_URL: "data/db.sqlite3"

# Logging
LOG_LEVEL: "info"
EXTENDED_LOGGING: "true"
LOG_FILE: "/data/vaultwarden.log"

# Security headers
ROCKET_LIMITS: "{json=10485760}"
ROCKET_WORKERS: 10

volumes:
- ./vw-data:/data
- ./backups:/backups

ports:
- "3012:3012" # WebSocket port
- "8080:80" # HTTP port (use reverse proxy for HTTPS)

# Health check
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80/alive"]
interval: 30s
timeout: 3s
retries: 3
start_period: 30s

# Optional: PostgreSQL for better performance
# postgres:
# image: postgres:15-alpine
# container_name: vaultwarden-db
# restart: unless-stopped
# environment:
# POSTGRES_DB: vaultwarden
# POSTGRES_USER: vaultwarden
# POSTGRES_PASSWORD: "${DB_PASSWORD}"
# volumes:
# - ./postgres-data:/var/lib/postgresql/data

# Backup service
backup:
image: bruceforce/vaultwarden-backup:latest
container_name: vaultwarden-backup
restart: unless-stopped
depends_on:
- vaultwarden
environment:
BACKUP_INTERVAL: 12h
BACKUP_KEEP_DAYS: 30
TIMESTAMP: "true"
volumes:
- ./vw-data:/data:ro
- ./backups:/backups
- /etc/localtime:/etc/localtime:ro

⚙️ Configuration

Environment Variables

Security Notice

Never commit sensitive environment variables to version control. Use .env files or secrets management.

📋 Complete Environment Variables List
VariableDescriptionDefaultRequired
Core Settings
DOMAINFull URL for the service-
ROCKET_PORTInternal port80
ROCKET_WORKERSNumber of worker threads10
Security
ADMIN_TOKENAdmin panel access token-
SIGNUPS_ALLOWEDAllow new user registrationtrue
INVITATIONS_ALLOWEDAllow user invitationstrue
SIGNUPS_VERIFYRequire email verificationfalse
SIGNUPS_DOMAINS_WHITELISTAllowed email domains-
SHOW_PASSWORD_HINTDisplay password hintstrue
Database
DATABASE_URLDatabase connection stringSQLite
DATABASE_MAX_CONNSMax database connections10
Email
SMTP_HOSTSMTP server address-
SMTP_PORTSMTP server port587
SMTP_SECURITYstarttls, force_tls, or offstarttls
SMTP_FROMFrom email address-
SMTP_USERNAMESMTP username-
SMTP_PASSWORDSMTP password-
Advanced
WEBSOCKET_ENABLEDEnable WebSocket notificationsfalse
WEBSOCKET_PORTWebSocket port3012
LOG_LEVELtrace, debug, info, warn, errorinfo
EXTENDED_LOGGINGEnable extended loggingtrue
LOG_FILELog file path-
ICON_SERVICEIcon download serviceinternal
ICON_CACHE_TTLIcon cache time (seconds)2592000
DISABLE_ICON_DOWNLOADDisable favicon downloadsfalse

Reverse Proxy Configuration

/etc/nginx/sites-available/vaultwarden
server {
listen 443 ssl http2;
server_name vault.example.com;

# SSL Configuration
ssl_certificate /etc/letsencrypt/live/vault.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vault.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;

# Security Headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;

# Vaultwarden proxy
location / {
proxy_pass http://localhost: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;

# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}

# WebSocket specific location
location /notifications/hub {
proxy_pass http://localhost:3012;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}

# Admin panel (optional: restrict by IP)
location /admin {
# allow 192.168.1.0/24;
# deny all;
proxy_pass http://localhost: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;
}
}

📖 Usage

Initial Setup

First Time Setup

Follow these steps to configure Vaultwarden after deployment

  1. Access the Web Vault

    • Navigate to https://vault.example.com
    • Click "Create Account"
    • Enter your email and master password
  2. Configure Admin Panel

    # Access admin panel at:
    https://vault.example.com/admin

    # Enter the admin token from your environment variables
  3. Recommended Admin Settings

    • Disable open registration: SIGNUPS_ALLOWED=false
    • Enable email verification: SIGNUPS_VERIFY=true
    • Configure SMTP for email notifications
    • Set backup retention policies
  4. Install Clients

Client Configuration

🔧 Configure Bitwarden Clients
  1. Open the Bitwarden app/extension
  2. Click the gear icon (Settings)
  3. Select "Self-hosted environment"
  4. Enter your server URL:
    • Server URL: https://vault.example.com
    • Leave other fields empty
  5. Save and log in with your credentials

Common Tasks

📝 Backup and Restore

Automated Backups

backup.sh
#!/bin/bash
# Vaultwarden backup script

BACKUP_DIR="/backups"
DATA_DIR="/data"
DATE=$(date +%Y%m%d_%H%M%S)

# Stop Vaultwarden for consistency
docker stop vaultwarden

# Create backup
tar -czf "$BACKUP_DIR/vaultwarden_$DATE.tar.gz" \
-C "$DATA_DIR" .

# Start Vaultwarden
docker start vaultwarden

# Remove old backups (keep 30 days)
find "$BACKUP_DIR" -name "vaultwarden_*.tar.gz" \
-mtime +30 -delete

echo "Backup completed: vaultwarden_$DATE.tar.gz"

Restore from Backup

# Stop Vaultwarden
docker stop vaultwarden

# Backup current data (just in case)
mv /data /data.old

# Extract backup
tar -xzf /backups/vaultwarden_20240101_120000.tar.gz \
-C /data

# Start Vaultwarden
docker start vaultwarden
🔄 Update Vaultwarden
# Pull latest image
docker pull vaultwarden/server:latest

# Stop current container
docker stop vaultwarden

# Remove old container (data is preserved in volumes)
docker rm vaultwarden

# Start with new image
docker-compose up -d

# Verify update
docker logs vaultwarden | grep "Version"
👥 User Management

Invite New Users

  1. Access Admin Panel: https://vault.example.com/admin
  2. Navigate to "Users" section
  3. Click "Invite User"
  4. Enter email address
  5. User receives invitation email

Disable/Enable Users

-- Via SQLite (backup first!)
sqlite3 /data/db.sqlite3

-- Disable user
UPDATE users SET enabled = 0 WHERE email = 'user@example.com';

-- Enable user
UPDATE users SET enabled = 1 WHERE email = 'user@example.com';

-- List all users
SELECT email, enabled, created_at FROM users;

🔧 Troubleshooting

Common Issues

Connection Issues

Most problems are related to reverse proxy or WebSocket configuration

❌ Cannot Access Web Vault

Symptoms: Browser shows connection error or timeout

Solutions:

  1. Check container status:

    docker ps | grep vaultwarden
    docker logs vaultwarden
  2. Verify port mapping:

    netstat -tulpn | grep 8080
  3. Test direct access:

    curl http://localhost:8080/alive
  4. Check reverse proxy:

    • Verify SSL certificates
    • Check proxy configuration
    • Review proxy logs
🔄 Sync Not Working

Symptoms: Changes don't sync between devices

Solutions:

  1. Enable WebSocket:

    WEBSOCKET_ENABLED: "true"
  2. Configure reverse proxy for WebSocket:

    • Ensure /notifications/hub is proxied to port 3012
    • Add WebSocket headers
  3. Check client logs:

    • Browser: F12 → Console
    • Mobile: App settings → Sync status
  4. Force sync:

    • Pull down to refresh (mobile)
    • Click sync button (desktop)
🔐 Forgot Admin Token

Recovery Steps:

  1. Generate new token:

    openssl rand -base64 48
  2. Update container:

    docker stop vaultwarden
    docker rm vaultwarden
    docker run -d \
    --name vaultwarden \
    -e ADMIN_TOKEN="new-token-here" \
    [other options...]
  3. Alternative: Disable admin panel:

    # Remove ADMIN_TOKEN environment variable
    # Admin panel will be disabled

🔐 Security Best Practices

Hardening Checklist

Security Requirements

Implement these measures for production deployments

  • Use HTTPS only - Never expose over HTTP
  • Strong admin token - Minimum 48 characters
  • Disable signups - Use invitations only
  • Enable 2FA - Require for all users
  • Regular backups - Automated and tested
  • Update regularly - Subscribe to security advisories
  • Firewall rules - Restrict admin panel access
  • Fail2ban - Protect against brute force
  • Audit logs - Monitor access patterns

Fail2ban Configuration

🛡️ Fail2ban Setup
/etc/fail2ban/filter.d/vaultwarden.conf
[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <HOST>\. Username:.*$
ignoreregex =
/etc/fail2ban/jail.d/vaultwarden.conf
[vaultwarden]
enabled = true
port = 80,443,8080
filter = vaultwarden
logpath = /opt/vaultwarden/data/vaultwarden.log
maxretry = 5
bantime = 3600
findtime = 600

📊 Monitoring

Health Checks

docker-compose.yml (Healthcheck)
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80/alive"]
interval: 30s
timeout: 3s
retries: 3

Metrics & Logging

MetricLocationPurpose
Access logs/data/vaultwarden.logUser activity
Error logsDocker logsTroubleshooting
Database size/data/db.sqlite3Storage monitoring
Backup status/backups/Verify backups

Monitoring with Prometheus

prometheus.yml
scrape_configs:
- job_name: 'vaultwarden'
static_configs:
- targets: ['vaultwarden:80']
metrics_path: '/alive'

🔗 Resources


Maintenance Information

Last Updated: December 2024
Version: vaultwarden/server:latest (1.30.x)
Maintainer: Infrastructure Team
Backup Schedule: Daily at 2 AM