With the increase in online attacks and cybercrime, there is a serious need to securely generate, store, and manage passwords with utmost complexity for different online services and accounts. There are dozens of SaaS solutions that you can signup for and get started within seconds. For some users like myself, using self-hosted application is preferred and tools like Vaultwarden come into the picture.
Vaultwarden is a free to use and open source password management solution whose development was inspired by Bitwarden. Vaultwarden allows you to store, generate and manage your passwords in a secure manner. It has support for multi-factor authentication, end-to-end encryption of data, and multiple browser extensions as well as mobile apps for ease of use. Vaultwarden is committed to the open-source spirit of ensuring the software application is forever free to use. Vaultwarden is ideal for various use cases, and suitable for individuals, families, or smaller organizations.
How To Install Vaultwarden on Linux
The easiest way to using Vaultwarden is running it in a container. A container makes the application highly portable, meaning you can run Vaultwarden consistently across different environments. In this article we are using Docker Container Engine on a Linux machine. Windows and macOS users can use similar docker environment tools such as Portainer.
In this setup we’re using domain name passwords.techwizpro.com with A record 49.13.153.179.

Start with the installation of Docker Engine.
I have Docker Engine version 25 on my Ubuntu system.
$ docker --version
Docker version 25.0.3, build 4debf41
Compose plugin is version 2.x
$ docker compose version
Docker Compose version v2.24.5
Create a directory where Vaultwarden data will be stored.
mkdir ~/vaultwarden && cd ~/vaultwarden
Create new compose file.
vim docker-compose.yml
Modify DOMAIN value to your FQDN.
version: '3'
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: always
environment:
DOMAIN: "https://passwords.techwizpro.com"
volumes:
- ./vw_data:/data
To start the container run the commands below.
$ docker compose up -d
[+] Running 7/7
✔ vaultwarden 6 layers [⣿⣿⣿⣿⣿⣿] 0B/0B Pulled 6.9s
✔ c57ee5000d61 Pull complete 0.7s
✔ a15201bfb52f Pull complete 0.6s
✔ b58597132f48 Pull complete 0.4s
✔ b3ef181c63dc Pull complete 0.8s
✔ d9668859131d Pull complete 1.2s
✔ a5e23e066860 Pull complete 1.3s
[+] Running 1/2
⠦ Network vaultwarden_default Created 0.6s
✔ Container vaultwarden Started 0.5s
The service will be available on host port 8080. We shall use Nginx to proxy request on domain to this port.
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
vaultwarden vaultwarden/server:latest "/start.sh" vaultwarden 6 seconds ago Up 5 seconds (health: starting) 3012/tcp, 0.0.0.0:8080->80/tcp, :::8080->80/tcp
You can now access Vaultwarden on your server IP and port 8080. But I recommend you use Nginx or any other web server to proxy.

Configure Nginx Reverse Proxy
We can now configure Nginx as a reverse proxy server for Vaultwarden. Nginx can be run in a container, package installed on the OS, or using Nginx Proxy Manager solution. See guides below.
- How To Run Nginx Proxy Manager in Docker Container
- Install LEMP Stack on Rocky Linux 8|AlmaLinux 8 – See Nginx section
Examples on installation on Debian and RHEL based Linux systems.
### Debian / Ubuntu ###
sudo apt update && sudo apt install nginx
sudo systemctl enable --now nginx
### RHEL 8/9 or Fedora ###
sudo dnf -y install nginx
sudo systemctl enable --now nginx
Create Nginx Virtual Host file for Vaultwarden.
sudo vim /etc/nginx/conf.d/vaultwarden.conf
Edit the configuration file and adjust params to suit your use.
# 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;
server 127.0.0.1:8080;
keepalive 2;
}
# Needed to support websocket connections
# See: https://nginx.org/en/docs/http/websocket.html
# Instead of "close" as stated in the above link we send an empty value.
# Else all keepalive connections will not work.
map $http_upgrade $connection_upgrade {
default upgrade;
'' "";
}
# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name passwords.techwizpro.com;
client_max_body_size 525M;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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;
}
# Optionally add extra authentication besides the ADMIN_TOKEN
# Remove the comments below `#` and create the htpasswd_file to have it active
#
#location /admin {
# # See: https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-http-basic-authentication/
# auth_basic "Private";
# auth_basic_user_file /path/to/htpasswd_file;
#
# proxy_http_version 1.1;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection $connection_upgrade;
#
# 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;
#}
}
Confirm you have no nginx syntax errors:
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
1 – Using Let’s Encrypt SSL
Install certbot tool used to generate Let’s Encrypt SSL certificates.
# Ubuntu / Debian
sudo apt update
sudo apt install certbot python3-certbot-nginx
# Fedora
sudo dnf install certbot python3-certbot-nginx
# CentOS / RHEL / Alma / Rocky 8
sudo dnf -y install epel-release
sudo yum -y install certbot python3-certbot-nginx
# CentOS 7
sudo yum -y install epel-release
sudo yum -y install certbot python2-certbot-nginx
Generate Let’s Encrypt for the domain.
DOMAIN="passwords.techwizpro.com"
export ALERTS_EMAIL="[email protected]"
sudo certbot --nginx --redirect -d $DOMAIN --preferred-challenges http --agree-tos -n -m $ALERTS_EMAIL --keep-until-expiring
Let’s Encrypt SSL generation process.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Account registered.
Requesting a certificate for passwords.techwizpro.com
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/passwords.techwizpro.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/passwords.techwizpro.com/privkey.pem
This certificate expires on 2024-05-15.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Deploying certificate
Successfully deployed certificate for passwords.techwizpro.com to /etc/nginx/conf.d/vaultwarden.conf
Congratulations! You have successfully enabled HTTPS on https://passwords.techwizpro.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Since we specified --nginx
option certbot will modify vaultwarden.conf
file and inject SSL settings.
cat /etc/nginx/conf.d/vaultwarden.conf
2 – Using custom or Self-signed certificates
See our article on how to Generate OpenSSL Self-Signed Certificates with Ansible
If using Custom SSL or Self-signed certificates, you can update the file manually as shown below.
# 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;
server 127.0.0.1:8080;
keepalive 2;
}
# Needed to support websocket connections
# See: https://nginx.org/en/docs/http/websocket.html
# Instead of "close" as stated in the above link we send an empty value.
# Else all keepalive connections will not work.
map $http_upgrade $connection_upgrade {
default upgrade;
'' "";
}
# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name passwords.techwizpro.com;
if ($host = passwords.techwizpro.com) {
return 301 https://$host$request_uri;
}
return 404;
}
server {
# For older versions of nginx appened http2 to the listen line after ssl and remove `http2 on`
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name passwords.techwizpro.com;
# Specify SSL Config when needed - adjust for custom paths
ssl_certificate /path/to/certificate/letsencrypt/live/passwords.techwizpro.com/fullchain.pem;
ssl_certificate_key /path/to/certificate/letsencrypt/live/passwords.techwizpro.com/privkey.pem;
ssl_trusted_certificate /path/to/certificate/letsencrypt/live/passwords.techwizpro.com/fullchain.pem;
client_max_body_size 525M;
location / {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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;
}
# Optionally add extra authentication besides the ADMIN_TOKEN
# Remove the comments below `#` and create the htpasswd_file to have it active
#
#location /admin {
# # See: https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-http-basic-authentication/
# auth_basic "Private";
# auth_basic_user_file /path/to/htpasswd_file;
#
# proxy_http_version 1.1;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection $connection_upgrade;
#
# 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;
#}
}
Restart Nginx web server for the changes to be loaded into memory.
sudo systemctl restart nginx
Access Vaultwarden over https
The final step is accessing Vaultwarden using https and configured domain name.

Create first account by inputing all the required information.

Once the account is created provide email address to login to Vaultwarden backend.

Provide the master password as configured earlier.

Here is the screenshot of Vaultwarden dashboard. Here you can create an organization and store login information to your website and other online services.

This is an example on how to create login item.


Configure Bitwarden clients
Vaultwarden is compatible with the official Bitwarden clients. Download and configure then appropriately.
References: