Self-Hosting the vaultwarden Password Manager
Traducciones al EspañolEstamos traduciendo nuestros guías y tutoriales al Español. Es posible que usted esté viendo una traducción generada automáticamente. Estamos trabajando con traductores profesionales para verificar las traducciones de nuestro sitio web. Este proyecto es un trabajo en curso.
The Vaultwarden project (formerly known as bitwarden_rs) provides a lightweight, single-process, API-compatible service alternative to Bitwarden. Vaultwarden is an open source password management application that can be self-hosted and run on your infrastructure. By running the vaultwarden service, you can use Bitwarden browser extensions and mobile applications backed by your server.
NoteBy self-hosting your password manager, you are assuming responsibility for the security and resiliency of sensitive information stored within Vaultwarden. Before storing important information and credentials within the application, ensure that you are confident with the security of the server. Also, take the necessary backup measures mentioned in this tutorial.
In this Guide
This guide uses the official Vaultwarden Docker image. A reverse proxy ( Caddy) is configured in front of the Docker container. This provides TLS termination for both the web-based vault interface and the websocket server.
This configuration of Vaultwarden also uses the default SQL backend for the application (sqlite3). The SQL datastore for vaultwarden contains the user data of the application and is therefore the primary concern for a backup scheme. Backing up this datastore ensures that sensitive data stored within Vaultwarden is saved in the event of a data loss scenario.
This guide references the latest version of the Vaultwarden Docker image that is available, which is 1.19 at the time of writing. As part of regular maintenance, follow the upgrade instructions provided by the project regularly. Following these instructions ensures your deployment is up to date with current upstream releases. This also ensures that any relevant security updates are applied to the application.
Ubuntu 20.04 is the distribution used in this guide. Generally speaking, any Linux distribution that supports running Docker containers should be equally compatible with the steps explained in this guide.
Before You Begin
Familiarize yourself with our Getting Started guide and complete the steps for setting the hostname and timezone.
Follow the Setting Up and Securing a Compute Instance guide in order to harden the Linode against malicious users. This step is important to ensure Vaultwarden is secured.
Note
If you choose to configure a firewall, remember to open ports 80 and 443 for the Caddy server. The Configure a Firewall section of the guide outlines different firewall software options.Make sure you have registered a Fully Qualified Domain Name (FQDN) and set up A and AAAA DNS records that point to the public IPv4 and IPv6 addresses of the Linode. Consult the DNS Records: An Introduction and DNS Manager guides for help with setting up a domain. A proper domain name is important to acquire a certificate for HTTPS connectivity.
Install Docker
Uninstall any potentially previously-installed packages.
sudo apt-get remove docker docker-engine docker.io containerd runc
If
apt-get
indicates that no packages were found, continue to the next step.Install package prerequisites for compatibility with the upstream Docker repository.
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
Add the official Docker GPG repository key.
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Add the Docker upstream repository.
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
Update the
apt
package cache.sudo apt-get update
Install the required Docker packages.
sudo apt-get install docker-ce docker-ce-cli containerd.io
Start and enable the
docker
daemon.sudo systemctl enable --now docker
Confirm that you can run
docker
commands. The following command should return without errors and show zero running containers.sudo docker ps
Install vaultwarden
This section outlines how to download the Vaultwarden Docker image, setup volume persistence, and manage the Docker container.
Pull the Vaultwarden image.
sudo docker pull vaultwarden/server:latest
Select the desired file system path to store application data. In this guide, the path
/srv/vaultwarden
is used. Create the directory if necessary, and enforce strict permissions for the root user only.sudo mkdir /srv/vaultwarden sudo chmod go-rwx /srv/vaultwarden
Create the Docker container for Vaultwarden.
sudo docker run -d --name vaultwarden -v /srv/vaultwarden:/data -e WEBSOCKET_ENABLED=true -p 127.0.0.1:8080:80 -p 127.0.0.1:3012:3012 --restart on-failure vaultwarden/server:latest
This command uses the following flags to establish a persistent container to serve the Vaultwarden application:
-d
daemonizes the container to run in the background.- Using
--name vaultwarden
gives the container a human-readable name. To avoid the need to reference the running container by a temporary identifier. - By passing the host path
/srv/vaultwarden
to the volume (-v
) flag, data is persisted outside of the container whenever it is stopped. - The environment variable
WEBSOCKET_ENABLED
enables the extra websocket server for Vaultwarden. - Each
-p
flag forwards the respective host ports to the container (port 8080 for the main Vaultwarden web service and port 3012 for websocket traffic). Normal HTTP and HTTPS ports are served with Caddy. --restart=on-failure
ensures that the container remains up in the event of container failure or host restart.
As part of these steps, note that the container listens for traffic on the local loopback interface (
127.0.0.1
) and not a publicly reachable IP address. This is to ensure that any traffic originating from outside the host must connect to the Caddy server, which enforces encrypted TLS connections.
Configure Caddy as a Reverse Proxy
External clients communicate with Caddy, which manages reverse proxying websocket traffic. Caddy also provisions and renews TLS certificates through Let’s Encrypt automatically. The caddy images come in many flavors, each designed for a specific use case.
caddy:<version>
This is the de facto image. If you are unsure about your needs, you probably want to use this one. It is designed to be used both as a throw away container. To mount source code and start the container to start the app. Also, as the base to build other images using this.
Pull the Caddy image.
sudo docker pull caddy:2
Create the following Caddyfile. Be sure to replace
example.com
with the name of the domain that you set up in the Before You Begin section of this guide, and confirm that the domain points to the IP address of the Linode. This domain serves the web interface for Vaultwarden hosted and secured by Caddy’s automatic TLS.- File: /etc/Caddyfile
1 2 3 4 5 6 7 8 9 10 11 12
example.com { encode gzip # The negotiation endpoint is also proxied to Rocket reverse_proxy /notifications/hub/negotiate 0.0.0.0:80 # Notifications redirected to the websockets server reverse_proxy /notifications/hub 0.0.0.0:3012 # Send all other traffic to the regular Vaultwarden endpoint reverse_proxy 0.0.0.0:80 }
Note
The site name you choose in this file must match the desired URL that Vaultwarden is served under. When navigating to the web interface later in this guide, ensure that you type the same hostname chosen in this configuration file (in this example,example.com
).Prepare a directory for Caddy in
/etc
to store state information such as Let’s Encrypt certificates.sudo mkdir /etc/caddy sudo chmod go-rwx /etc/caddy
Start another Docker container to run a persistent
caddy
daemon.sudo docker run -d -p 80:80 -p 443:443 --name caddy -v /etc/Caddyfile:/etc/caddy/Caddyfile -v /etc/caddy:/root/.local/share/caddy --restart on-failure caddy:2
View the logs of the Caddy container in order to confirm that a Let’s Encrypt certificate has been provisioned for the chosen domain.
sudo docker logs caddy
There are likely to be many logs that are returned from this command. Take a moment to read through the logs to verify that lines similar to the following are included in your log output. These lines indicate that certificate provisioning has been successful.
{"level":"info","ts":1634144042.9741306,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"} {"level":"warn","ts":1634144042.9749222,"msg":"input is not formatted with 'caddy fmt'","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":2} {"level":"info","ts":1634144042.9756303,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["127.0.0.1:2019","localhost:2019","[::1]:2019"]} {"level":"info","ts":1634144042.975767,"logger":"http","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443} {"level":"info","ts":1634144042.9757824,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"} {"level":"info","ts":1634144042.9760253,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc00030b960"} {"level":"info","ts":1634144042.976342,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["example.com"]} {"level":"info","ts":1634144042.9765563,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"} {"level":"info","ts":1634144042.9765673,"msg":"serving initial configuration"} {"level":"info","ts":1634144042.9765913,"logger":"tls","msg":"cleaning storage unit","description":"FileStorage:/data/caddy"} {"level":"info","ts":1634144042.9766064,"logger":"tls","msg":"finished cleaning storage units"} {"level":"info","ts":1634144042.9772124,"logger":"tls.obtain","msg":"acquiring lock","identifier":"example.com"} {"level":"info","ts":1634144042.9790497,"logger":"tls.obtain","msg":"lock acquired","identifier":"example.com"} {"level":"info","ts":1634144046.9010673,"logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":["example.com"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""} {"level":"info","ts":1634144046.9011092,"logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":["example.com"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""} {"level":"info","ts":1634144055.8619049,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"example.com","challenge_type":"http-01","ca":"https://acme-v02.api.letsencrypt.org/directory"}
If you find any log lines similar to the following, which indicate failure, double check that the server is reachable from the chosen domain.
{"level":"info","example.com","ca":"https://acme-v02.api.letsencrypt.org/directory","account":"msg": "Unable to deactivate the authorization: <url>} {"level":"error","example.com","msg":"failed to obtain certificate: acme: Error -> One or more domains had a problem"}
In order to avoid rate limiting problems, you should stop the
caddy
server if you find any certificate provisioning issues withsudo docker stop caddy
. You may start the server again withsudo docker start caddy
after resolving any issues found in the aforementioned container logs.
Initial Setup
Navigate to the chosen domain in a local web browser (in this tutorial,
example.com
). Verify that the browser renders the Bitwarden web vault login page, and that the page is served over TLS/SSL.If you see the login page, congratulations! Vaultwarden is running and operational. The first step in using the password manager is to create an account. Do so by clicking on the Create Account button on the login page.
Note
Remember to navigate to the same name configured in yourCaddyfile
defined in the previous section of this guide. A mismatched hostname in your browser can cause TLS errors.A new page appears with several fields.
Fill each field with the appropriate information, choosing a strong and secure master password.
Note
Although a user email is required at time of registration, by default, the deployment of Vaultwarden cannot send email without additional configuration. If you would like to configure SMTP in order to enable Vaultwarden to send email, follow these instructions on the Vaultwarden wiki. Use SMTP information from an SMTP provider when following the instructions.After registering, the system redirects you to the login screen. Log in with the credentials. The web vault view appears.
At this point, the vaultwarden installation is functional.
Disable Anonymous User Sign Up
As an additional security precaution, you may elect to disable user registration. This is recommended on servers that are publicly reachable to avoid abuse of the service.
Stop the running Vaultwarden container and remove it.
sudo docker stop vaultwarden sudo docker rm vaultwarden
Start a new vaultwarden container, but with the
SIGNUPS_ALLOWED
environment variable set tofalse
.sudo docker run -d --name vaultwarden -v /srv/vaultwarden:/data -e WEBSOCKET_ENABLED=true -e SIGNUPS_ALLOWED=false -p 127.0.0.1:8080:80 -p 127.0.0.1:3012:3012 --restart on-failure vaultwarden/server:latest
If you attempt to create a new account after these changes, the following error appears on the account creation page.
This deployment of Vaultwarden does not permit any additional user registrations. You may still want to invite users without needing to change the Vaultwarden container environment variable flags. This is possible by following the upstream documentation to enable the admin panel. The administrator panel provides user invitation functionality.
Backup Vaultwarden SQLite Database
Before relying on this service for any important data, you should take additional steps to safeguard the data stored within Vaultwarden. 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.
Review the Backing Up Your Data guide in order to determine the best location to store the backups. In this example, a local file system path is used.
Note
In a more resilient setup, these local backups should be replicated onto another service or host to guard against single-host failure.Install the
sqlite3
package, which provides thesqlite3
command for the backup script.sudo apt-get install sqlite3
Create a directory for backups.
sudo mkdir /srv/backup sudo chmod go-rwx /srv/backup
Create the following systemd service.
- File: /etc/systemd/system/vaultwarden-backup.service
1 2 3 4 5 6 7 8
[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
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.
sudo systemctl start vaultwarden-backup.service
Verify that a backup file is present:
sudo ls -l /srv/backup/
This command returns with one backup sqlite3 file.
total 136 -rw-r--r-- 1 root root 139264 Feb 24 18:16 backup-2020-02-24T18_16_50-07_00.sq3
To schedule regular backups using this backup service unit, create the following systemd timer unit.
- File: /etc/systemd/system/vaultwarden-backup.timer
1 2 3 4 5 6 7 8 9
[Unit] Description=schedule vaultwarden backups [Timer] OnCalendar=04:00 Persistent=true [Install] WantedBy=multi-user.target
This schedules the backup to occur at 4:00 in the time zone set for the Linode. You may alter this time to trigger at a desired time of day.
Note
ThePersistent=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.
sudo systemctl enable vaultwarden-backup.timer sudo 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
You should see output similar to the following:
● vaultwarden-backup.timer - schedule vaultwarden backups Loaded: loaded (/etc/systemd/system/vaultwarden-backup.timer; enabled; vendor preset: enabled) Active: active (waiting) since Mon 2020-02-24 22:09:44 MST; 7s ago Trigger: Tue 2020-02-25 04:00:00 MST; 5h 50min left
This indicates that a backup is taken in 5 hours and 50 minutes.
CautionEnsure that the backups are kept on a volume or host independent of the Linode in case of a disaster recover recovery scenario. Consider using Linode Block Storage as one potential solution for permanent backup storage and archival.
Using Vaultwarden
vaultwarden provides a compatible API for many Bitwarden apps and browser extensions. In order to configure these applications to use a hosted instance, you may need to configure the mobile application or browser extension. Specifically, you may need to enter a custom domain and API endpoint:
As an example, this is the initial login screen for the Firefox Bitwarden browser extension. In order to configure a custom server, click the gear in the upper left corner.
On the next page, type your custom domain under the Server URL field, such as
https://example.com
. Similar steps can be taken on the iOS and Android mobile applications. Edit the settings of the application before login to use a custom Server URL, and you can log in to a custom instance of Vaultwarden.
Additional Reading
With Vaultwarden running securely over TLS and regularly backed up, you may choose to follow additional documentation provided by the Vaultwarden project. This documentation helps add more functionality to your installation. Some of these features include:
- Support for U2F authentication
- SMTP configuration to support sending emails for features like account creation invitation.
This page was originally published on