8.2.8 Vaultwarden Deployment and Configuration on a Server
Vaultwarden is a lightweight server-side version of the Bitwarden password manager, written in Rust. It enables you to securely store and sync your passwords on your own server and is fully compatible with official Bitwarden clients.
System Requirements
- An ordered Virtual Server or Dedicated Server
- CPU: from 1 core, RAM: from 1 GB (2 GB is comfortable)
- SSD: from 5 GB
- OS: Ubuntu 22.04 or 24.04 LTS
- Domain name pointing to your server (A record)
- Open ports 80 and 443 (firewall)
- sudo or root access
- Docker and Docker Compose installed
Security
- Never expose Vaultwarden to the public without HTTPS;
- It is recommended to use a separate VPS or dedicated server;
- Set up regular backups and store them separately.
Installing Docker and Docker Compose
Before installing Vaultwarden, you need to install Docker and Docker Compose. Docker allows you to run the application in an isolated container, avoiding complex manual dependency installation and simplifying further updates.
Execute the following commands in sequence to install Docker and Docker Compose, and start the Docker service:
sudo apt update && sudo apt upgrade -y
sudo apt install docker.io docker-compose -y
sudo systemctl enable docker --now
Creating the Project Structure and .env
To organize your data and configuration, create a separate folder for Vaultwarden. This folder will contain:
- The Docker Compose file
- The data directory (volume)
- The
.env
file with environment variables
Navigate to your working directory and create the required directories:
sudo mkdir -p /opt/vaultwarden/data
cd /opt/vaultwarden
Now create the .env
file — here you will store settings that are easy to update without editing the Docker Compose file itself:
ADMIN_TOKEN=Replace_with_a_strong_token
DOMAIN=https://your-domain.com
DATA_FOLDER=/opt/vaultwarden/data
You can generate a strong token with the command:
openssl rand -base64 48
You’ll need this token to access the Vaultwarden admin panel.
Docker Compose File for Vaultwarden
Now create the main configuration file — docker-compose.yml
.
It defines which container to use, what environment variables are set, how volumes are mounted, and which networks the app uses.
Open an editor and create the file:
version: '3'
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: always
environment:
- ADMIN_TOKEN=${ADMIN_TOKEN}
- DOMAIN=${DOMAIN}
- WEBSOCKET_ENABLED=true
volumes:
- ${DATA_FOLDER}:/data
networks:
- vaultwarden-net
expose:
- "80"
- "3012"
networks:
vaultwarden-net:
driver: bridge
Note: We are not exposing any ports externally (ports
), so Vaultwarden will only be available through the internal Docker network, increasing security. External ports are proxied via Nginx.
Configuring Nginx as a Reverse Proxy for SSL (HTTPS)
To ensure the server operates securely and supports HTTPS, use Nginx as a reverse proxy. Nginx will accept external requests, automatically forward them to the Vaultwarden container over a secure connection, and handle the SSL certificate. Install Nginx and Certbot:
sudo apt install nginx certbot python3-certbot-nginx -y
Create an Nginx site configuration file:
sudo nano /etc/nginx/sites-available/vaultwarden.conf
Obtaining and Installing a Let’s Encrypt SSL Certificate
If you cannot obtain the certificate while Nginx is running, stop Nginx:
sudo systemctl stop nginx
Run Certbot to automatically configure HTTPS:
sudo certbot --nginx -d your-domain.com
Follow the prompts and agree to automatic certificate renewal.
Start Nginx again (if you stopped it):
sudo systemctl start nginx
Insert and edit the following content:
# ================================================================
# 1. Redirect all HTTP requests to HTTPS
# ================================================================
server {
listen 80;
listen [::]:80;
server_name your-domain.com; # Replace your-domain.com with your actual domain
# Redirect all requests to HTTPS
return 301 https://$host$request_uri;
}
# ================================================================
# 2. Handle HTTPS on 443 with Let's Encrypt certificate
# ================================================================
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name your-domain.com; # Replace your-domain.com with your actual domain
# Paths to the Let’s Encrypt certificate and key
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# Additional security optimizations (recommended)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# Recommended Diffie-Hellman parameters (optional but future-proof)
# ssl_dhparam /etc/ssl/certs/dhparam.pem;
# Disable server tokens (reduce information leakage)
server_tokens off;
# Root location — proxy to the container’s internal port (localhost:8080)
location / {
proxy_pass http://127.0.0.1:8080; # If the port is mapped to localhost:8080
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;
# Extend timeouts under high load
proxy_read_timeout 90;
proxy_connect_timeout 90;
}
# WebSocket endpoint for notifications
location /notifications/hub {
proxy_pass http://127.0.0.1:3012; # If the port is mapped to localhost:3012
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 X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# If needed: limit request body size (for large attachments)
client_max_body_size 128M;
}
Create a symbolic link to enable the site:
sudo ln -s /etc/nginx/sites-available/vaultwarden.conf /etc/nginx/sites-enabled/
Reload Nginx:
sudo nginx -t
sudo systemctl reload nginx
If the symbolic link was not created previously, run again:
sudo ln -s /etc/nginx/sites-available/vaultwarden.conf /etc/nginx/sites-enabled/
Check Nginx syntax:
sudo nginx -t
Ensure there are no errors. If an error appears, fix it according to the message.
Restart Nginx:
sudo systemctl restart nginx
Docker → Nginx Proxy Setup
Vaultwarden should only be accessible via the Nginx proxy. To achieve this, configure port forwarding in Docker Compose so Nginx can proxy client traffic to the container. After making these changes, restart the service — your application will be accessible via HTTPS and your domain.
Update docker-compose.yml
and restart Vaultwarden:
ports:
- "8080:80"
- "3012:3012"
Apply the changes:
sudo docker-compose up -d
Starting Vaultwarden
Once everything is configured, start all services using Docker Compose:
sudo docker-compose up -d
You can always check the status of your services with:
docker-compose ps
Checking Operation and Testing
- Open
https://your-domain.com
in your browser - Register the first user
- To access the admin panel, use:
https://your-domain.com/admin?admin_token=YOUR_TOKEN
Supported Vaultwarden Clients
Vaultwarden is fully compatible with official Bitwarden clients. This means you can use any Bitwarden app to access your self-hosted Vaultwarden server:
Client Capabilities:
- Synchronize passwords, cards, notes, and files across devices
- Autofill passwords in browsers and apps
- Use two-factor authentication (TOTP, WebAuthn)
- Organize collections and collaborate in teams (organizations)
Official Bitwarden Clients
Platform | Where to get it |
---|---|
Web client | In your browser: https://your-domain.com (your Vaultwarden address) |
Browser extension | Chrome Web Store, Firefox Add-ons |
Desktop client | Windows/macOS/Linux |
Mobile app | Google Play, App Store |
CLI (command line) | Bitwarden CLI |
How to Connect to Your Vaultwarden Server
- On the login screen in any official Bitwarden client, look for the “Self-hosted environment” or “Use a self-hosted server” option.
-
Enter your server address:
https://your-domain.com # your domain where Vaultwarden is deployed
-
Log in or register your account. Your data will be stored directly on your server.
Important: Some older mobile clients may, by default, only work with bitwarden.com. If you don’t see the “Self-hosted” option, update your app to the latest version!
CLI Client
For advanced users and DevOps, Bitwarden CLI is available:
bw login user@domain.com
To specify your server:
bw login user@domain.com --server https://your-domain.com
Changing the Server in the Apps
- On desktop and mobile clients: in the settings (usually on the login screen), select “Self-hosted” and enter your Vaultwarden URL.
- In browser extensions: open the extension settings, find the “Server” option, and enter your domain.
- Via web: simply open https://your-domain.com in your browser.
Table of common issues and quick solutions
Issue | Solution |
---|---|
Site does not open via HTTPS | Check the certificate, domain, Nginx config, firewall |
Admin panel does not work | Check the ADMIN_TOKEN variable, don’t forget ?admin_token= |
“Cannot write to /data” | Check permissions: chown -R 1000:1000 /opt/vaultwarden/data |
Mail notifications not working | Configure SMTP environment variables in Docker Compose |
Container won’t start | Check logs: docker-compose logs vaultwarden |
Certificate does not renew | Run manually: sudo certbot renew |