Table of Contents
- Overview
- Prerequisites
- Quick Architecture
- Variables
- Step 1 — Install / Setup
- Step 2 — Base Configuration
- Step 3 — Enable & Health Checks
- Security / Hardening
- Performance & Optimization
- Backup & Restore
- Advanced Add-Ons
- Troubleshooting (Top issues)
- Key Takeaways & Next Steps
Overview
Deploy Vaultwarden Self Hosted HTTPS on Docker , WebSocket support, and an admin token. Per‑OS install commands are split; Add‑Ons are OS‑agnostic.
Prerequisites
Linux server with DNS to it; ports 80/443 open; sudo shell.
Quick Architecture

Variables
Before you copy: Customize values once; then run source /root/vars.sh to load them for all steps.
VW_DOMAIN,EMAIL,VW_DATA,NGINX_SITE,VW_IMAGE,VW_ADMIN_TOKEN
sudo install -d -m 700 /root
cat <<'EOF' | sudo tee /root/vars.sh
export VW_DOMAIN="vault.example.com"
export EMAIL="[email protected]"
export VW_DATA="/var/lib/vaultwarden"
export NGINX_SITE="/etc/nginx/sites-available/vaultwarden.conf"
export VW_IMAGE="vaultwarden/server:latest"
export VW_ADMIN_TOKEN="$(openssl rand -hex 24)"
EOF
source /root/vars.sh
Step 1 — Install / Setup
Debian / Ubuntu
sudo apt update
sudo apt -y install docker.io nginx certbot # Certbot install here (per‑OS)
RHEL / Rocky / Alma / CentOS Stream / Fedora
sudo dnf -y install docker nginx certbot # Certbot install here (per‑OS)
Arch / Manjaro
sudo pacman -Syu --noconfirm docker nginx certbot # Certbot install here (per‑OS)
openSUSE / SLE
sudo zypper refresh
sudo zypper install -y docker nginx certbot # Certbot install here (per‑OS)
Step 2 — Base Configuration
sudo mkdir -p "$VW_DATA"
sudo docker run -d --name vaultwarden --restart unless-stopped -p 127.0.0.1:8080:80 -v "$VW_DATA":/data -e SIGNUPS_ALLOWED=true -e ADMIN_TOKEN="$VW_ADMIN_TOKEN" -e WEBSOCKET_ENABLED=true "$VW_IMAGE"
Nginx TLS site (universal)
server {
listen 80;
server_name $VW_DOMAIN;
location /.well-known/acme-challenge/ { root /var/www/_letsencrypt; }
location / { return 301 https://$host$request_uri; }
}
server {
listen 443 ssl http2;
server_name $VW_DOMAIN;
ssl_certificate /etc/letsencrypt/live/$VW_DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/$VW_DOMAIN/privkey.pem;
client_max_body_size 100m;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
location /notifications/hub/negotiate { proxy_pass http://127.0.0.1:8080; }
location /notifications/hub { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://127.0.0.1:8080; }
location / { proxy_pass http://127.0.0.1:8080; }
}
Step 3 — Enable & Health Checks
sudo systemctl enable --now docker nginx
sudo docker ps --format "table {{.Names}} {{.Status}} {{.Ports}}" | grep -E '^vaultwarden\b' || echo "vaultwarden not running?"
sudo ss -tlnp | grep -E ':(80|443)\b' # Check
Security / Hardening
Harden with these practices; snippets are optional and separate:
- Keep the app bound to
127.0.0.1:8080; all traffic goes through HTTPS Nginx. - Rotate the admin token regularly.
- Restrict
/adminto trusted IPs or a VPN.
Rotate admin token
export VW_ADMIN_TOKEN="$(openssl rand -hex 24)"
sudo docker stop vaultwarden && sudo docker rm vaultwarden
sudo docker run -d --name vaultwarden --restart unless-stopped -p 127.0.0.1:8080:80 -v "$VW_DATA":/data -e SIGNUPS_ALLOWED=true -e ADMIN_TOKEN="$VW_ADMIN_TOKEN" -e WEBSOCKET_ENABLED=true "$VW_IMAGE"
Restrict /admin by IP
location /admin {
allow 203.0.113.0/24; # your office block
deny all;
proxy_pass http://127.0.0.1:8080;
}
Performance & Optimization
- Enable HTTP/2 (already enabled) and proxy keepalive.
- Place data on SSD; monitor I/O latency (SQLite is file‑based).
- Reduce
client_max_body_sizeif attachments are disabled.
Backup & Restore
Back up both the app data and Nginx config. Store off‑server.
Backup
sudo tar -C / -czf /root/vaultwarden-backup.tgz "$VW_DATA" "$NGINX_SITE"
ls -lh /root/vaultwarden-backup.tgz # Check
Restore
sudo systemctl stop nginx
sudo docker stop vaultwarden
sudo tar -C / -xzf /root/vaultwarden-backup.tgz
sudo docker start vaultwarden
sudo systemctl start nginx
curl -s https://$VW_DOMAIN/ | head -n 1 # Check
Advanced Add-Ons
OS‑agnostic only.
(Add‑On) Automated Certificates (Certbot)
Use webroot ACME to request/renew certificates. Install Certbot per‑OS in Step 1; here we only run it.
sudo install -d -m 755 /var/www/_letsencrypt
sudo certbot certonly --webroot -w /var/www/_letsencrypt -d "$VW_DOMAIN" --email "$EMAIL" --agree-tos --no-eff-email
sudo certbot renew --dry-run # Check
(Add‑On) SMTP Email
Enable email delivery for verification and invites.
sudo docker stop vaultwarden
sudo docker rm vaultwarden || true
sudo docker run -d --name vaultwarden --restart unless-stopped -p 127.0.0.1:8080:80 -v "$VW_DATA":/data -e SIGNUPS_ALLOWED=true -e ADMIN_TOKEN="$VW_ADMIN_TOKEN" -e WEBSOCKET_ENABLED=true -e SMTP_HOST="smtp.example.com" -e SMTP_FROM="$EMAIL" -e SMTP_PORT=587 -e SMTP_SSL=true -e SMTP_USERNAME="smtp-user" -e SMTP_PASSWORD="smtp-password" "$VW_IMAGE"
(Add‑On) Off‑server Backups (rclone to S3/MinIO)
Assumes rclone is installed and a remote (e.g., s3remote) is configured.
sudo tar -C / -czf /root/vaultwarden-$(date +%F).tgz "$VW_DATA"
rclone copy /root/vaultwarden-$(date +%F).tgz s3remote:backups/vaultwarden/ # Check
Troubleshooting (Top issues)
WebSocket not upgrading
grep -n "notifications/hub" "$NGINX_SITE"
sudo nginx -t && sudo systemctl reload nginx
Admin panel not accessible
sudo docker logs vaultwarden | tail -n 100 | sed -n '1,120p'
Key Takeaways & Next Steps
- HTTPS + WebSocket + admin token ready.
- Backups tested; optional add‑ons available.
- Harden
/admin, keep everything updated.
