How to run Vaultwarden server on linux

I’ve been using Bitwarden’s premium service for two years, and am really satisfied with it.

I’ve also heard of Vaultwarden, but I didn’t bother to run it myself, until yesterday.

This is a footage of building and running Vaultwarden on linux, without docker.

A. Build

Following instructions are from this page.

a. Build vaultwarden binary

I created a working directory for vaultwarden:

$ mkdir vaultwarden

cloned the vaultwarden’s source repository in it:

$ cd vaultwarden
# now in the working directory,
$ git clone ./src

then built the binary with cargo:

$ cd src
# now in the cloned source directory,
$ cargo build --features sqlite --release

b. Download web-vault

The web UI needs to be downloaded or built separately.

I downloaded the latest gzip file from the release page:

$ cd ..
# got back to 'vaultwarden' directory,
$ wget
$ tar xzvf bw_web_v2023.1.1.tar.gz

c. Run

I symlinked the binary, created data directory, and checked if the binary runs ok:

# now in the working directory,
$ ln -sf src/target/release/vaultwarden ./vaultwarden
$ mkdir data
$ ./vaultwarden

If you can see messages like this:

|                        Starting Vaultwarden                        |
|                      Version 1.27.0-1ba8275d                       |
| This is an *unofficial* Bitwarden implementation, DO NOT use the   |
| official channels to report bugs/features, regardless of client.   |
| Send usage/configuration questions or feature requests to:         |
|                             |
| Report suspected bugs/issues in the software itself at:            |
|            |

[2023-02-15 11:13:15.048][start][INFO] Rocket has launched from

it is working!

Then I pressed [ctrl+c] to stop it, and began configuration.

B. Configure a reverse proxy

For using the web UI, we need to configure a reverse proxy with this guide.

I issued a SSL certificate with certbot, and added a reverse proxy site file for nginx:

# /etc/nginx/sites-enabled/MY_SITE_DOMAIN
# for Web UI of Vaultwarden

# The `upstream` directives ensure that you have a http/1.1 connection
# This enables the keepalive option and better performance
# Define the server IP and ports here.
upstream vaultwarden-default {
  zone vaultwarden-default 64k;
  keepalive 2;
upstream vaultwarden-ws {
  zone vaultwarden-ws 64k;
  keepalive 2;

# Redirect HTTP to HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name MY_SITE_DOMAIN;
    return 301 https://$host$request_uri;

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name MY_SITE_DOMAIN;

    ssl_certificate /etc/letsencrypt/live/MY_SITE_DOMAIN/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/MY_SITE_DOMAIN/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/MY_SITE_DOMAIN/fullchain.pem;

    client_max_body_size 128M;

    location / {
      proxy_http_version 1.1;
      proxy_set_header "Connection" "";

      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://vaultwarden-default;

    location /notifications/hub/negotiate {
      proxy_http_version 1.1;
      proxy_set_header "Connection" "";

      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://vaultwarden-default;

    location /notifications/hub {
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";

      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header Forwarded $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;

      proxy_pass http://vaultwarden-ws;

    # Optionally add extra authentication besides the ADMIN_TOKEN
    # Remove the comments below `#` and create the htpasswd_file to have it active
    #location /admin {
    #  # See:
    #  auth_basic "Private";
    #  auth_basic_user_file /path/to/htpasswd_file;
    #  proxy_http_version 1.1;
    #  proxy_set_header "Connection" "";
    #  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://vaultwarden-default;

I could see my vault page by restarting nginx and running vaultwarden,

but before that, I had to do some more configuration.

C. Configure things

Duplicated the .env.template file and edited it:

# now in the working directory,
$ cp src/.env.template ./.env
$ vi ./.env

a. Enable admin page

There is a guide for enabling admin page.

Created a randomly generated string with:

$ openssl rand -base64 48

and then set ADMIN_TOKEN=xyz0123456789abcdefghijklmnopqrstuvw.

b. Disable registrations

It is advised to disable registration of (unwanted) new users.

I could do it by just setting SIGNUPS_ALLOWED=false.

c. Setup SMTP

A little more efforts were needed on SMTP configuration.

SMTP is essential for sending various emails, eg. welcome messages and validation emails.

There are several options of SMTP server/relay services, so choose wisely.

In my case, I created a SendGrid account for it, setting following values:

z. Save configurations

Finally, restarted nginx and ran vaultwarden.

Then I could access the admin page at url: YOUR_SERVER_URL/admin.

Signed in with my ADMIN_TOKEN, checked things up,

and then pressed the blue Save button on the bottom left:


Vaultwarden became ready for service!

D. Make it start automatically

For some more convenience, I created a systemd service with this guide,

so it could be launched automatically on reboots.


# Only sqlite

# The user/group vaultwarden is run under. the working directory (see below) should allow write and read access to this user/group
# Use an environment file for configuration.
# The location of the compiled binary
# Set reasonable connection and process limits
# Isolate vaultwarden from the rest of the system
# Only allow writes to the following directory and set it to the working directory (user and password data are stored here)


I had to comment out line: ProtectHome=true because my working directory was inside my home directory.

E. Make it more secure

a. Setup for Fail2ban

See the guide here.

I created filter and jail files for fail2ban:

Files for web vault:


# /etc/fail2ban/filter.d/vaultwarden.local

before = common.conf

failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
ignoreregex =


# /etc/fail2ban/jail.d/vaultwarden.local

enabled = true
port = 80,443,8081
filter = vaultwarden
banaction = %(banaction_allports)s
#logpath = /path/to/vaultwarden.log
logpath = /var/log/syslog
maxretry = 3
bantime = 14400
findtime = 14400

Files for admin page:


# /etc/fail2ban/filter.d/vaultwarden-admin.local

before = common.conf

failregex = ^.*Invalid admin token\. IP: <ADDR>.*$
ignoreregex =


# /etc/fail2ban/jail.d/vaultwarden-admin.local

enabled = true
port = 80,443
filter = vaultwarden-admin
banaction = %(banaction_allports)s
#logpath = /path/to/vaultwarden.log
logpath = /var/log/syslog
maxretry = 3
bantime = 14400
findtime = 14400


$ sudo systemctl reload fail2ban

to make the changes work.

These settings will block abusive/malicious attackers from brute-forcing into the vault.

b. Disable registration, invitations, and/or password hints

See following guides: this one and that one.

Z. Connect Bitwarden app with my Vaultwarden server

I wanted to add my Vaultwarden account in my Android app.

By pressing the ‘gear shaped’ button on the top right,


I could see the screen for entering my own Vaultwarden server url:


After signing in with my account info, I could use the app just like my premium Bitwarden account!


Maintaining a server with critical information is quite stressful.

So if I had a choice between keeping my secrets on my own server, and keeping them in a paid service, I would choose the latter, Bitwarden’s premium service.

Nevertheless, building and running a service manually is fun, so it was worth trying :-)