Bitwarden: How to setup a self-hosted password manager using Vaultwarden | Pieter Hollander (2024)

NB: This post hasn’t been updated since May 2021, as I nowadays don’t use this approach anymore. However, it can still be useful as a reference, although version numbers and configuration settings may have changed.

Bitwarden is an open-source password manager. Using Vaultwarden, a Bitwarden compatible server implementation written in Rust formerly known as Bitwarden_RS, it is possible to create a self-hosted server, using little resources, enabling you to use all its features.

Bitwarden makes it possible to share and sync usernames and passwords across all devices and webbrowsers.

In this example I’ll be using two pc’s: One for compiling and one for hosting, because the VPS I run this on isn’t powerful enough to compile the binaries.

On compile machine

Install dependencies

sudo apt update && apt list -u && sudo apt dist-upgrade -ysudo apt install dirmngr git libssl-dev pkg-config build-essential curl wget libmariadb-dev-compat libmariadb-dev libpq-devcurl -sL https://deb.nodesource.com/setup_12.x | sudo bash -sudo apt install nodejscurl https://sh.rustup.rs -sSf | shsource $HOME/.cargo/env

Compile vaultwarden

git clone https://github.com/dani-garcia/vaultwarden.gitcd vaultwarden/git checkout "$(git tag --sort=v:refname | tail -n1)" # checkout most recent versioncargo build --features sqlite,postgresql,mysql --releasecd ..

Compile vault

Clone and checkout repository

git clone https://github.com/bitwarden/web.gitcd webgit checkout "$(git tag --sort=v:refname | tail -n1)" # checkout most recent version

NB: Do not run the following command as root. Building the web vault will fail.

npm run sub:init

Patch web vault to work with Vaultwarden

Download the most recent Vaultwarden patch for the Bitwarden web vault. This can be done using one of two ways:

A. Download and apply a patch based on the version that you just checked out using git.

wget https://raw.githubusercontent.com/dani-garcia/bw_web_builds/master/patches/$(git tag --sort=v:refname | tail -n1).patchgit apply $(git tag --sort=v:refname | tail -n1).patch

B. Does this give a 404 Not Found error? In that case there might not be new changes in the most recent Bitwarden web release that need to be patched in order to work with Vaultwarden.

For example:

wget https://raw.githubusercontent.com/dani-garcia/bw_web_builds/master/patches/v2.19.0.patchgit apply v2.19.0.patch

Build the web vault

NB: Do not run the following commands as root. Building the web vault will fail.

npm installnpm audit fixnpm run distcd ..

Copy

export SSH="user@host.example.org"scp -r vaultwarden/target/release/vaultwarden ${SSH}:~scp vaultwarden/.env.template ${SSH}:~scp -r web/build ${SSH}:~/web-vault

on remote host

sudo adduser --system --group --disabled-login --home /opt/bitwarden bitwardensudo cp -r ~/vaultwarden /opt/bitwardensudo cp -r ~/web-vault /opt/bitwarden/rm ~/vaultwardenrm -rf ~/web-vaultsudo mkdir /etc/bitwardensudo nano /etc/bitwarden/bitwarden.conf

Use this file as a template. Alter all uncommented variables to match your environment.

## Vaultwarden Configuration File## Uncomment any of the following lines to change the defaults#### Be aware that most of these settings will be overridden if they were changed.## in the admin interface. Those overrides are stored within DATA_FOLDER/config.json .## Main data folder# DATA_FOLDER=data## Database URL## When using SQLite, this is the path to the DB file, default to %DATA_FOLDER%/db.sqlite3# DATABASE_URL=data/db.sqlite3## When using MySQL, specify an appropriate connection URI.## Details: https://docs.diesel.rs/diesel/mysql/struct.MysqlConnection.html# DATABASE_URL=mysql://user:password@host[:port]/database_name## When using PostgreSQL, specify an appropriate connection URI (recommended)## or keyword/value connection string.## Details:## - https://docs.diesel.rs/diesel/pg/struct.PgConnection.html## - https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING# DATABASE_URL=postgresql://user:password@host[:port]/database_name## Database max connections## Define the size of the connection pool used for connecting to the database.# DATABASE_MAX_CONNS=10## Individual folders, these override %DATA_FOLDER%# RSA_KEY_FILENAME=data/rsa_key# ICON_CACHE_FOLDER=data/icon_cache# ATTACHMENTS_FOLDER=data/attachments# SENDS_FOLDER=data/sends## Templates data folder, by default uses embedded templates## Check source code to see the format# TEMPLATES_FOLDER=/path/to/templates## Automatically reload the templates for every request, slow, use only for development# RELOAD_TEMPLATES=false## Client IP Header, used to identify the IP of the client, defaults to "X-Real-IP"## Set to the string "none" (without quotes), to disable any headers and just use the remote IP# IP_HEADER=X-Real-IP## Cache time-to-live for successfully obtained icons, in seconds (0 is "forever")# ICON_CACHE_TTL=2592000## Cache time-to-live for icons which weren't available, in seconds (0 is "forever")# ICON_CACHE_NEGTTL=259200## Web vault settings# WEB_VAULT_FOLDER=web-vault/# WEB_VAULT_ENABLED=true## Enables websocket notificationsWEBSOCKET_ENABLED=true## Controls the WebSocket server address and portWEBSOCKET_ADDRESS=127.0.0.1# WEBSOCKET_PORT=3012## Job scheduler settings#### Job schedules use a cron-like syntax (as parsed by https://crates.io/crates/cron),## and are always in terms of UTC time (regardless of your local time zone settings).#### How often (in ms) the job scheduler thread checks for jobs that need running.## Set to 0 to globally disable scheduled jobs.# JOB_POLL_INTERVAL_MS=30000#### Cron schedule of the job that checks for Sends past their deletion date.## Defaults to hourly (5 minutes after the hour). Set blank to disable this job.# SEND_PURGE_SCHEDULE="0 5 * * * *"#### Cron schedule of the job that checks for trashed items to delete permanently.## Defaults to daily (5 minutes after midnight). Set blank to disable this job.# TRASH_PURGE_SCHEDULE="0 5 0 * * *"## Enable extended logging, which shows timestamps and targets in the logs# EXTENDED_LOGGING=true## Timestamp format used in extended logging.## Format specifiers: https://docs.rs/chrono/latest/chrono/format/strftime# LOG_TIMESTAMP_FORMAT="%Y-%m-%d %H:%M:%S.%3f"## Logging to file## It's recommended to also set 'ROCKET_CLI_COLORS=off'LOG_FILE=/var/log/bitwarden/bitwarden.log## Logging to Syslog## This requires extended logging## It's recommended to also set 'ROCKET_CLI_COLORS=off'# USE_SYSLOG=false## Log level## Change the verbosity of the log output## Valid values are "trace", "debug", "info", "warn", "error" and "off"## Setting it to "trace" or "debug" would also show logs for mounted## routes and static file, websocket and alive requests# LOG_LEVEL=Info## Enable WAL for the DB## Set to false to avoid enabling WAL during startup.## Note that if the DB already has WAL enabled, you will also need to disable WAL in the DB,## this setting only prevents vaultwarden from automatically enabling it on start.## Please read project wiki page about this setting first before changing the value as it can## cause performance degradation or might render the service unable to start.# ENABLE_DB_WAL=true## Database connection retries## Number of times to retry the database connection during startup, with 1 second delay between each retry, set to 0 to retry indefinitely# DB_CONNECTION_RETRIES=15## Disable icon downloading## Set to true to disable icon downloading, this would still serve icons from $ICON_CACHE_FOLDER,## but it won't produce any external network request. Needs to set $ICON_CACHE_TTL to 0,## otherwise it will delete them and they won't be downloaded again.# DISABLE_ICON_DOWNLOAD=false## Icon download timeout## Configure the timeout value when downloading the favicons.## The default is 10 seconds, but this could be to low on slower network connections# ICON_DOWNLOAD_TIMEOUT=10## Icon blacklist Regex## Any domains or IPs that match this regex won't be fetched by the icon service.## Useful to hide other servers in the local network. Check the WIKI for more details## NOTE: Always enclose this regex within single quotes!# ICON_BLACKLIST_REGEX='^(192\.168\.0\.[0-9]+|192\.168\.1\.[0-9]+)$'## Any IP which is not defined as a global IP will be blacklisted.## Useful to secure your internal environment: See https://en.wikipedia.org/wiki/Reserved_IP_addresses for a list of IPs which it will block# ICON_BLACKLIST_NON_GLOBAL_IPS=true## Disable 2FA remember## Enabling this would force the users to use a second factor to login every time.## Note that the checkbox would still be present, but ignored.# DISABLE_2FA_REMEMBER=false## Maximum attempts before an email token is reset and a new email will need to be sent.# EMAIL_ATTEMPTS_LIMIT=3## Token expiration time## Maximum time in seconds a token is valid. The time the user has to open email client and copy token.# EMAIL_EXPIRATION_TIME=600## Email token size## Number of digits in an email token (min: 6, max: 19).## Note that the Bitwarden clients are hardcoded to mention 6 digit codes regardless of this setting!# EMAIL_TOKEN_SIZE=6## Controls if new users can register# SIGNUPS_ALLOWED=true## Controls if new users need to verify their email address upon registration## Note that setting this option to true prevents logins until the email address has been verified!## The welcome email will include a verification link, and login attempts will periodically## trigger another verification email to be sent.# SIGNUPS_VERIFY=false## If SIGNUPS_VERIFY is set to true, this limits how many seconds after the last time## an email verification link has been sent another verification email will be sent# SIGNUPS_VERIFY_RESEND_TIME=3600## If SIGNUPS_VERIFY is set to true, this limits how many times an email verification## email will be re-sent upon an attempted login.# SIGNUPS_VERIFY_RESEND_LIMIT=6## Controls if new users from a list of comma-separated domains can register## even if SIGNUPS_ALLOWED is set to false# SIGNUPS_DOMAINS_WHITELIST=example.com,example.net,example.org## Controls which users can create new orgs.## Blank or 'all' means all users can create orgs (this is the default):# ORG_CREATION_USERS=## 'none' means no users can create orgs:# ORG_CREATION_USERS=none## A comma-separated list means only those users can create orgs:# ORG_CREATION_USERS=admin1@example.com,admin2@example.com## Token for the admin interface, preferably use a long random string## One option is to use 'openssl rand -base64 48'## If not set, the admin panel is disabledADMIN_TOKEN=____PASSWORD____## Enable this to bypass the admin panel security. This option is only## meant to be used with the use of a separate auth layer in front# DISABLE_ADMIN_TOKEN=false## Invitations org admins to invite users, even when signups are disabled# INVITATIONS_ALLOWED=true## Name shown in the invitation emails that don't come from a specific organization# INVITATION_ORG_NAME=Vaultwarden## Per-organization attachment limit (KB)## Limit in kilobytes for an organization attachments, once the limit is exceeded it won't be possible to upload more# ORG_ATTACHMENT_LIMIT=## Per-user attachment limit (KB).## Limit in kilobytes for a users attachments, once the limit is exceeded it won't be possible to upload more# USER_ATTACHMENT_LIMIT=## Controls the PBBKDF password iterations to apply on the server## The change only applies when the password is changed# PASSWORD_ITERATIONS=100000## Whether password hint should be sent into the error response when the client request itSHOW_PASSWORD_HINT=false## Domain settings## The domain must match the address from where you access the server## It's recommended to configure this value, otherwise certain functionality might not work,## like attachment downloads, email links and U2F.## For U2F to work, the server must use HTTPS, you can use Let's Encrypt for free certsDOMAIN=https://vault.example.org## Allowed iframe ancestors (Know the risks!)## https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/frame-ancestors## Allows other domains to embed the web vault into an iframe, useful for embedding into secure intranets## This adds the configured value to the 'Content-Security-Policy' headers 'frame-ancestors' value.## Multiple values must be separated with a whitespace.# ALLOWED_IFRAME_ANCESTORS=## Yubico (Yubikey) Settings## Set your Client ID and Secret Key for Yubikey OTP## You can generate it here: https://upgrade.yubico.com/getapikey/## You can optionally specify a custom OTP server# YUBICO_CLIENT_ID=11111# YUBICO_SECRET_KEY=AAAAAAAAAAAAAAAAAAAAAAAA# YUBICO_SERVER=http://yourdomain.com/wsapi/2.0/verify## Duo Settings## You need to configure all options to enable global Duo support, otherwise users would need to configure it themselves## Create an account and protect an application as mentioned in this link (only the first step, not the rest):## https://help.bitwarden.com/article/setup-two-step-login-duo/#create-a-duo-security-account## Then set the following options, based on the values obtained from the last step:# DUO_IKEY=<Integration Key># DUO_SKEY=<Secret Key># DUO_HOST=<API Hostname>## After that, you should be able to follow the rest of the guide linked above,## ignoring the fields that ask for the values that you already configured beforehand.## Authenticator Settings## Disable authenticator time drifted codes to be valid.## TOTP codes of the previous and next 30 seconds will be invalid#### According to the RFC6238 (https://tools.ietf.org/html/rfc6238),## we allow by default the TOTP code which was valid one step back and one in the future.## This can however allow attackers to be a bit more lucky with there attempts because there are 3 valid codes.## You can disable this, so that only the current TOTP Code is allowed.## Keep in mind that when a sever drifts out of time, valid codes could be marked as invalid.## In any case, if a code has been used it can not be used again, also codes which predates it will be invalid.# AUTHENTICATOR_DISABLE_TIME_DRIFT = false## Rocket specific settings, check Rocket documentation to learn more# ROCKET_ENV=stagingROCKET_ADDRESS=127.0.0.1# ROCKET_PORT=8000# ROCKET_TLS={certs="/path/to/certs.pem",key="/path/to/key.pem"}## Mail specific settings, set SMTP_HOST and SMTP_FROM to enable the mail service.## To make sure the email links are pointing to the correct host, set the DOMAIN variable.## Note: if SMTP_USERNAME is specified, SMTP_PASSWORD is mandatorySMTP_HOST=smtp.example.orgSMTP_FROM=vault@example.org# SMTP_FROM_NAME=VaultwardenSMTP_PORT=587# NB: Ports 587 (submission) and 25 (smtp) are standard without encryption and with encryption via STARTTLS (Explicit TLS). Port 465 is outdated and used with Implicit TLS.SMTP_SSL=true# NB: (Explicit) - SMTP_SSL by default configures Explicit STARTTLS, it will upgrade an insecure connection to a secure one. Unless SMTP_EXPLICIT_TLS is set to true.# SMTP_EXPLICIT_TLS=true# NB: (Implicit) SMTP_EXPLICIT_TLS configures Implicit TLS. It's currently mislabelled (see bug #851) - SMTP_SSL Needs to be set to true for this option to work.# SMTP_USERNAME=usernameSMTP_USERNAME=vault@example.orgSMTP_PASSWORD=____PASSWORD____# SMTP_TIMEOUT=15## Defaults for SSL is "Plain" and "Login" and nothing for Non-SSL connections.## Possible values: ["Plain", "Login", "Xoauth2"].## Multiple options need to be separated by a comma ','.# SMTP_AUTH_MECHANISM="Plain"## Server name sent during the SMTP HELO## By default this value should be is on the machine's hostname,## but might need to be changed in case it trips some anti-spam filters# HELO_NAME=## SMTP debugging## When set to true this will output very detailed SMTP messages.## WARNING: This could contain sensitive information like passwords and usernames! Only enable this during troubleshooting!# SMTP_DEBUG=false## Accept Invalid Hostnames## DANGEROUS: This option introduces significant vulnerabilities to man-in-the-middle attacks!## Only use this as a last resort if you are not able to use a valid certificate.# SMTP_ACCEPT_INVALID_HOSTNAMES=false## Accept Invalid Certificates## DANGEROUS: This option introduces significant vulnerabilities to man-in-the-middle attacks!## Only use this as a last resort if you are not able to use a valid certificate.## If the Certificate is valid but the hostname doesn't match, please use SMTP_ACCEPT_INVALID_HOSTNAMES instead.# SMTP_ACCEPT_INVALID_CERTS=false## Require new device emails. When a user logs in an email is required to be sent.## If sending the email fails the login attempt will fail!!# REQUIRE_DEVICE_EMAIL=false## HIBP Api Key## HaveIBeenPwned API Key, request it here: https://haveibeenpwned.com/API/Key# HIBP_API_KEY=# vim: syntax=ini
sudo chmod 600 /etc/bitwarden/bitwarden.confsudo chown bitwarden:bitwarden /etc/bitwarden/bitwarden.confsudo mkdir /opt/bitwarden/datasudo mkdir /opt/bitwarden/data/db-backupsudo chown -R bitwarden:bitwarden /opt/bitwardensudo mkdir /var/log/bitwardensudo chown -R bitwarden:bitwarden /var/log/bitwarden

Add nginx vault.conf. The following config assumes that you have already installed and configured certbot / letsencrypt and retrieved a certificate.

sudo nano /etc/nginx/conf.d/vault.conf
server { listen 80; server_name vault.example.org; location /.well-known/acme-challenge/ { root /var/www/acme; } location / { return 301 https://$host$request_uri; }}server { listen 443 ssl http2; server_name vault.example.org; client_max_body_size 128M; ssl_certificate /etc/letsencrypt/live/vault.example.org/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/vault.example.org/privkey.pem; ssl_dhparam /etc/ssl/certs/dhparam_4096.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers "ECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; ssl_ecdh_curve secp384r1; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; ssl_stapling on; ssl_stapling_verify on; resolver 127.0.0.1 valid=300s; resolver_timeout 5s; add_header X-Content-Type-Options nosniff; add_header Strict-Transport-Security "max-age=63072000; preload"; keepalive_timeout 300s; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location /notifications/hub { proxy_pass http://127.0.0.1:3012; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location /notifications/hub/negotiate { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://127.0.0.1:8000; }}
sudo nginx -tsudo systemctl restart nginx
sudo nano /etc/systemd/system/bitwarden.service
[Unit]Description=Vaultwarden: Bitwarden compatible serverDocumentation=https://github.com/dani-garcia/vaultwardenAfter=network.target auditd.service# If using an alternative DB backend, uncomment one of the following additional "After" and "Require" sections.## PostgreSQL# After=postgresql.service# Requires=postgresql.service## MariaDB# After=mariadb.service# Requires=mariadb.service## MySQL# After=mysqld.service# Requires=mysqld.service[Service]RestartSec=2sType=simpleUser=bitwardenGroup=bitwardenEnvironmentFile=/etc/bitwarden/bitwarden.confWorkingDirectory=/opt/bitwarden/ExecStart=/opt/bitwarden/vaultwardenRestart=always# Isolate vaultwarden from the rest of the systemPrivateTmp=truePrivateDevices=trueProtectHome=trueNoNewPrivileges=trueProtectSystem=strict# Only allow writes to the following directoriesReadWritePaths=/opt/bitwarden/data/ /var/log/bitwarden# Set reasonable connection and process limitsLimitNOFILE=1048576LimitNPROC=64[Install]WantedBy=multi-user.target
sudo systemctl daemon-reloadsudo systemctl enable bitwardensudo systemctl start bitwarden

Set up Fail2ban

If you are using Fail2Ban, you can add this configuration to keep out unwanted guests:

sudo apt install -y fail2ban
sudo nano /etc/fail2ban/filter.d/bitwarden.conf
[INCLUDES]before = common.conf[Definition]failregex = ^.*Username or password is incorrect\. Try again\. IP: <HOST>\. Username:.*$ignoreregex =
sudo nano /etc/fail2ban/jail.d/bitwarden.local
[bitwarden]enabled = trueport = 80,443,8081filter = bitwardenaction = iptables-allports[name=bitwarden]logpath = /var/log/bitwarden/bitwarden.logmaxretry = 3bantime = 14400findtime = 14400
sudo nano /etc/fail2ban/filter.d/bitwarden-admin.conf
[INCLUDES]before = common.conf[Definition]failregex = ^.*Invalid admin token\. IP: <HOST>.*$ignoreregex =
sudo nano /etc/fail2ban/jail.d/bitwarden-admin.local
[bitwarden-admin]enabled = trueport = 80,443filter = bitwarden-adminaction = iptables-allports[name=bitwarden]logpath = /var/log/bitwarden/bitwarden.logmaxretry = 5bantime = 14400findtime = 14400
sudo systemctl restart fail2ban

Set up logrotation

Over time, the Vaultwarden log file can grow to a significant size. Using logrotate, we can periodically rotate logs.

sudo nano /etc/logrotate.d/bitwarden
/var/log/bitwarden/*.log { # Perform logrotation as the bitwarden user and group su bitwarden bitwarden # Rotate daily daily # Rotate when the size is bigger than 5MB size 5M # Compress old log files compress # Keep 4 rotations of log files before removing or mailing to the address specified in a mail directive rotate 4 # Truncate the original log file in place after creating a copy copytruncate # Don't panic if not found missingok # Don't rotate log if file is empty notifempty # Add date instaed of number to rotated log file dateext # Date format of dateext dateformat -%Y-%m-%d-%s}

NB: To view a compressed log file without manually decompressing:

zcat logfile.gzzless logfile.gzzgrep -i keyword_search logfile.gz

Backup

If you’d like to backup the Vaultwarden server, please use the following steps to do so

sudo apt install -y sqlite3

Export the sqlite database:

sqlite3 /opt/bitwarden/data/db.sqlite3 ".backup '/opt/bitwarden/data/db-backup/backup.sqlite3'"

If you have already set up backups for other services, add these paths to your list of backup targets:

/opt/bitwarden/data/db-backup/opt/bitwarden/data/attachments/opt/bitwarden/data/rsa_key.der/opt/bitwarden/data/rsa_key.pem/opt/bitwarden/data/rsa_key.pub.der/opt/bitwarden/data/icon_cache

Upgrade Vaultwarden and web vault

On build machine

Update system packages

sudo apt updatesudo apt dist-upgrade -y

Remove old build and sources

rm -rf vaultwarden web

Upgrade Rust

curl https://sh.rustup.rs -sSf | shsource $HOME/.cargo/env

Build Vaultwarden

git clone https://github.com/dani-garcia/vaultwarden.gitcd vaultwarden/git checkout "$(git tag --sort=v:refname | tail -n1)" # checkout most recent versioncargo build --features sqlite,postgresql,mysql --releasecd ..

Build Bitwarden web vault

Clone Bitwarden web vault repository
git clone https://github.com/bitwarden/web.gitcd webgit checkout "$(git tag --sort=v:refname | tail -n1)" # checkout most recent version

NB: Do not run the following command as root. Building the web vault will fail.

npm run sub:init
Download the most recent Vaultwarden patch for the Bitwarden web vault

This can be done using one of two ways:

A. Download and apply a patch based on the version that you just checked out using git.

wget https://raw.githubusercontent.com/dani-garcia/bw_web_builds/master/patches/$(git tag --sort=v:refname | tail -n1).patchgit apply $(git tag --sort=v:refname | tail -n1).patch

B. Does this give a 404 Not Found error? In that case there might not be new changes in the most recent Bitwarden web release that need to be patched in order to work with Vaultwarden.

For example:

wget https://raw.githubusercontent.com/dani-garcia/bw_web_builds/master/patches/v2.19.0.patchgit apply v2.19.0.patch
Compile web vault
npm installnpm audit fixnpm run distcd ..

Copy upgraded binary and vault

export SSH="user@host.example.org"scp -r vaultwarden/target/release/vaultwarden ${SSH}:~scp -r web/build ${SSH}:~/web-vault

On remote / public machine

sudo systemctl stop bitwarden.servicesudo cp -r ~/vaultwarden /opt/bitwardensudo rm -rf /opt/bitwarden/web-vaultsudo cp -r ~/web-vault /opt/bitwarden/rm ~/vaultwardenrm -rf ~/web-vaultsudo chown -R bitwarden:bitwarden /opt/bitwardensudo systemctl start bitwarden.servicesystemctl status bitwarden.service

Update notes

  • 2020-07: Improved web-vault instructions, added upgrade steps.
  • 2020-08: Noticed missing nginx config example. Added this.
  • 2020-09: Added some cleanup steps.
  • 2020-10: Updated to latest versions. Added new configuration options. Include MySQL and PostgreSQL backends next to the existing SQLite backend in compile steps.
  • 2020-12: Update to latest versions. Added logrotate config.
  • 2021-04: A reader notified me that the Bitwarden admin Fail2ban regex in /etc/fail2ban/filter.d/bitwarden-admin.conf should be updated. Bitwarden no longer prepends the log entry with “Unauthorized Error: “. This has been corrected.
  • 2021-05: Changed bitwarden_rs references to vaultwarden after rebrand. Updated example /etc/bitwarden/bitwarden.conf with new options. Changed patch apply order as it now includes a submodule file and needs npm run sub:init to be run before applying.
Bitwarden: How to setup a self-hosted password manager using Vaultwarden | Pieter Hollander (2024)
Top Articles
Latest Posts
Article information

Author: Greg Kuvalis

Last Updated:

Views: 5800

Rating: 4.4 / 5 (55 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Greg Kuvalis

Birthday: 1996-12-20

Address: 53157 Trantow Inlet, Townemouth, FL 92564-0267

Phone: +68218650356656

Job: IT Representative

Hobby: Knitting, Amateur radio, Skiing, Running, Mountain biking, Slacklining, Electronics

Introduction: My name is Greg Kuvalis, I am a witty, spotless, beautiful, charming, delightful, thankful, beautiful person who loves writing and wants to share my knowledge and understanding with you.