p:: Self-Hosted, Web Apps
Vaultwarden
Unofficial Bitwarden compatible server written in Rust, formerly known as bitwarden_rs
Self-Hosting the vaultwarden Password Manager
Using Docker Compose
Caddy with HTTP challenge
Select the desired file system path to store application data.
mkdir /srv/vaultwarden
chmod go-rwx /srv/vaultwarden
Prepare a directory for Caddy in /etc
to store state information such as Let’s Encrypt certificates.
mkdir /etc/caddy
chmod go-rwx /etc/caddy
vim /etc/caddy/Caddyfile
{$DOMAIN}:443 {
log {
level INFO
output file {$LOG_FILE} {
roll_size 10MB
roll_keep 10
}
}
# Use the ACME HTTP-01 challenge to get a cert for the configured domain.
tls {$EMAIL}
# This setting may have compatibility issues with some browsers
# (e.g., attachment downloading on Firefox). Try disabling this
# if you encounter issues.
encode gzip
# Notifications redirected to the WebSocket server
reverse_proxy /notifications/hub vaultwarden:3012
# Proxy everything else to Rocket
reverse_proxy vaultwarden:80 {
# Send the true remote IP to Rocket, so that vaultwarden can put this in the
# log, so that fail2ban can ban the correct IP.
header_up X-Real-IP {remote_host}
}
}
Install the Compose standalone
cd /etc/caddy/
nano docker-compose.yaml
services:
vaultwarden:
image: vaultwarden/server:1.28.0
container_name: vaultwarden
restart: always
environment:
- WEBSOCKET_ENABLED=true
ports:
- 8080:80
- 3012:3012
volumes:
- /srv/vaultwarden:/data
caddy:
image: caddy:2.5.1
container_name: caddy
restart: always
ports:
- 80:80 # Needed for the ACME HTTP-01 challenge.
- 443:443
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy-config:/config
- ./caddy-data:/data
environment:
- DOMAIN=https://vaultwarden.example.com # Your domain.
- [email protected] # The email address to use for ACME registration.
- LOG_FILE=/data/access.log
docker-compose up -d
View the logs of the Caddy container in order to confirm that a Let’s Encrypt certificate has been provisioned for the chosen domain.
docker-compose logs caddy
...
{"level":"info","ts":1652005351.7653973,"logger":"tls.obtain","msg":"certificate obtained successfully","identifier":"vaultwarden.example.com"}
...
Navigate to the chosen domain and verify that the browser renders the Bitwarden web vault login page, and that the page is served over TLS/SSL.
Disable Anonymous User Sign Up
docker-compose down
Start a new vaultwarden container, but with the SIGNUPS_ALLOWED
environment variable set to false
.
cd /etc/caddy/
nano docker-compose.yaml
services:
vaultwarden:
image: vaultwarden/server:1.24.0
container_name: vaultwarden
restart: always
environment:
- WEBSOCKET_ENABLED=true
- SIGNUPS_ALLOWED=false
ports:
- 8080:80
- 3012:3012
volumes:
- /srv/vaultwarden:/data
caddy:
image: caddy:2.5.1
container_name: caddy
restart: always
ports:
- 80:80 # Needed for the ACME HTTP-01 challenge.
- 443:443
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy-config:/config
- ./caddy-data:/data
environment:
- DOMAIN=https://vaultwarden.example.com # Your domain.
- [email protected] # The email address to use for ACME registration.
- LOG_FILE=/data/access.log
docker-compose up -d
Backup Vaultwarden SQLite Database
Encrypted data is stored within a flat file sqlite3 database. In order to reliably backup this data, you should not simply copy the file. Instead, use the sqlite3 .backup command. This command ensures that the database is in a consistent state when the backup is taken.
Install the sqlite3
package, which provides the sqlite3
command for the backup script.
apt install sqlite3 -y
Create a directory for backups.
mkdir /srv/backup
chmod go-rwx /srv/backup
Create the following systemd service.
vim /etc/systemd/system/vaultwarden-backup.service
[Unit]
Description=backup the vaultwarden sqlite database
[Service]
Type=oneshot
WorkingDirectory=/srv/backup
ExecStart=/usr/bin/env sh -c 'sqlite3 /srv/vaultwarden/db.sqlite3 ".backup backup-$(date -Is | tr : _).sq3"'
ExecStart=/usr/bin/find . -type f -mtime +30 -name 'backup*' -delete
ExecStart=rclone copy /srv/backup dropbox:vaultwarden
This service unit creates a timestamped file and cleans up any backups older than 30 days.
To take an initial backup and verify the systemd service works, start the backup service.
systemctl start vaultwarden-backup.service
Verify that a backup file is present:
ls -lh /srv/backup/
total 1.4M
-rw-r--r-- 1 root root 1.4M May 8 11:56 backup-2022-05-08T11_56_40+00_00.sq3
To schedule regular backups using this backup service unit, create the following systemd timer unit.
vim /etc/systemd/system/vaultwarden-backup.timer
[Unit]
Description=schedule vaultwarden backups
[Timer]
OnCalendar=12:00
Persistent=true
[Install]
WantedBy=multi-user.target
The Persistent=true
line instructs systemd to fire the timer if the timer was unable to trigger at its previous target time. For example, this could happen if the system was being rebooted.
Start and enable this timer unit.
systemctl enable vaultwarden-backup.timer
systemctl start vaultwarden-backup.timer
Finally, to view the timer’s next execution time, check the status of the timer.
systemctl status vaultwarden-backup.timer
â—Ź vaultwarden-backup.timer - schedule vaultwarden backups
Loaded: loaded (/etc/systemd/system/vaultwarden-backup.timer; enabled; vendor preset: enabled)
Active: active (waiting) since Sun 2022-05-08 11:58:39 UTC; 13s ago
Trigger: Sun 2022-05-08 12:00:00 UTC; 1min 6s left
Triggers: â—Ź vaultwarden-backup.service
May 08 12:00:39 instance-2 systemd[1]: Started schedule vaultwarden backups.
ls -lh /srv/backup/
total 2.7M
-rw-r--r-- 1 root root 1.4M May 8 11:56 backup-2022-05-08T11_56_40+00_00.sq3
-rw-r--r-- 1 root root 1.4M May 8 12:00 backup-2022-05-08T12_00_00+00_00.sq3