Vaultwarden with Docker + HTTPS (Caddy)
Affiliate links. Disclosure
Versions/date: Vaultwarden 1.37.4 (latest GitHub release, published 2026-10-06 08:40 JST — https://github.com/dani-garcia/vaultwarden/releases/tag/1.37.4); Caddy v2.11.7 (latest GitHub release, published 2026-10-03 14:58 JST — https://github.com/caddyserver/caddy/releases/tag/v2.11.7). Docker Hub has the tags
vaultwarden/server:1.37.4andcaddy:2.11.7. Last checked: 2026-10-24.Vaultwarden is "an alternative server implementation of the Bitwarden Client API, written in Rust and compatible with official Bitwarden clients". Its README states: "This project is not associated with Bitwarden or Bitwarden, Inc." (README)
Vaultwarden needs HTTPS, because the Bitwarden web vault uses browser crypto APIs that most browsers only allow over a secure connection. The recommended setup is Vaultwarden in Docker behind a reverse proxy like Caddy, which gets certificates automatically. Pin the image tags, protect the admin page with an Argon2-hashed token, and back up the data folder.
Why HTTPS is required
The wiki says HTTPS "is pretty much required nowadays". The Bitwarden web vault uses Web Crypto APIs, and most browsers only allow those over HTTPS. The recommended approach is a reverse proxy. Vaultwarden's built-in Rocket TLS is "not recommended" (Enabling HTTPS). If you have no preference, the wiki suggests trying Caddy first, because it gets Let's Encrypt certificates automatically.
Prerequisites (per the wiki)
- Docker with Compose (install)
- A domain (
<YOUR_DOMAIN>, e.g.vaultwarden.example.com) pointing at your server - A server that's publicly reachable on ports 80 and 443, for the ACME HTTP-01 challenge
compose.yaml (official "Caddy with HTTP challenge" example)
From Using Docker Compose. We changed only the image tags (to pinned versions); the wiki uses vaultwarden/server:latest and caddy:2:
services:
vaultwarden:
image: vaultwarden/server:1.37.4
container_name: vaultwarden
restart: always
environment:
DOMAIN: "https://<YOUR_DOMAIN>"
SIGNUPS_ALLOWED: "true" # set to "false" once your account exists
volumes:
- ./vw-data:/data
caddy:
image: caddy:2.11.7
container_name: caddy
restart: always
ports:
- 80:80
- 443:443
- 443:443/udp
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy-config:/config
- ./caddy-data:/data
environment:
DOMAIN: "https://<YOUR_DOMAIN>"
EMAIL: "<YOUR_EMAIL>" # used for Let's Encrypt
LOG_FILE: "/data/access.log"Caddyfile (official; the wiki says it doesn't need editing)
{$DOMAIN} {
log {
level INFO
output file {$LOG_FILE} {
roll_size 10MB
roll_keep 10
}
}
tls {$EMAIL}
encode zstd gzip
reverse_proxy vaultwarden:80 {
header_up X-Real-IP {remote_host}
}
}The wiki notes that encode zstd gzip "may have compatibility issues with some browsers (e.g., attachment downloading on Firefox)". If you run into that, try disabling it.
Start it
docker compose up -dOnly Caddy is exposed publicly; Compose creates a private network for the two services. To update later: docker compose pull && docker compose up -d. If you pinned tags, change them first.
Official security notes (Hardening Guide)
- Disable signups once your account exists. By default, anyone can register. Set
SIGNUPS_ALLOWED: "false"and recreate the container. You can optionally disable invitations too. - Hide password hints: Vaultwarden shows hints on the login page, which attackers could abuse. You can turn this off.
- Don't use Rocket TLS on public instances. It doesn't support strict SNI or ECC certificates.
- **Redact
access_tokenin proxy logs:** WebSocket notification requests put a JWT in the URL. If you keep or ship access logs (as the Caddyfile above does), redact that parameter. - Consider a non-root user (
user: 1000:1000). Mount only the data you need, and use:rowhere possible. Never mount/var/run/docker.sockwithout a good reason. - Brute-force mitigation: without 2FA, passwords can in theory be brute-forced. The wiki suggests fail2ban, but be careful behind several proxies.
- Admin page: an
ADMIN_TOKENacts as the admin password. Keep it secret, and preferably store it hashed as an argon2id PHC string, generated withvaultwarden hash(admin page docs). If you don't set it, the admin page stays disabled.
Signups stay open (SIGNUPS_ALLOWED: "true") and the server is public as soon as Caddy has a certificate, so create your account immediately, then disable signups.
Backups (from the official wiki, checked 2026-10-25)
Source: the Vaultwarden wiki's Backing up your vault page (checked 2026-10-25).
The wiki recommends regular, preferably automated backups (for example a cron job), with at least one copy stored somewhere else. It advises against relying on filesystem or VM snapshots. In the compose file above, the data folder is ./vw-data on the host (mounted at /data). With the default SQLite backend, the wiki lists what is in it:
| Item | Wiki says |
|---|---|
db.sqlite3 (plus -wal / -shm files, which aren't always present) | Backup required. Holds almost all vault data. |
attachments/ | Backup required. File attachments aren't stored in the database. Only exists once an attachment has been created. |
sends/ | Backup optional (Send attachments are meant to be short-lived). |
config.json | Backup recommended if you use the admin page. It holds secrets such as the admin token and SMTP credentials in plain text, so encrypt it. |
rsa_key* files | Backup recommended. They sign login tokens. Losing them logs users out. Encrypt the private key. |
icon_cache/ | Backup optional. |
Database: the wiki recommends SQLite's .backup command (it uses the Online Backup API, which is safe while the database is in use):
sqlite3 data/db.sqlite3 ".backup '/path/to/backups/db-$(date '+%Y%m%d-%H%M').sqlite3'"The Docker image doesn't include sqlite3 or cron, so the wiki says to install them on the host and run the job there (here the path would be vw-data/db.sqlite3). Since 1.32.1 there is also a built-in command: docker exec -it vaultwarden /vaultwarden backup. Back up attachments/ (and the other files above) along with the database.
Restore (per the wiki): stop Vaultwarden, then replace each file or folder in the data folder with its backed-up copy. If you're restoring a .backup copy, first delete any existing db.sqlite3-wal. The wiki also recommends running a test restore now and then, while keeping a copy of your original data.
Run a test restore before you rely on a backup.
Sources
- https://github.com/dani-garcia/vaultwarden/wiki/Using-Docker-Compose
- https://github.com/dani-garcia/vaultwarden/wiki/Enabling-HTTPS
- https://github.com/dani-garcia/vaultwarden/wiki/Hardening-Guide
- https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page
- https://github.com/dani-garcia/vaultwarden/wiki/Backing-up-your-vault (checked 2026-10-25)
- https://github.com/dani-garcia/vaultwarden/releases/tag/1.37.4
- https://github.com/caddyserver/caddy/releases/tag/v2.11.7

