p:: Self-Hosted, Web Apps

Vaultwarden

GitHub - dani-garcia/vaultwarden: Unofficial Bitwarden compatible server written in Rust, formerly known as bitwarden_rs

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

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.

Rclone

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