Tutorial

Easily Deploy Bitwarden Server with Docker and Set Up Your Own Password Manager

2025-08-26 #Docker#Self-hosted#Bitwarden#Password Manager

Introduction

In the digital age, password security is crucial. However, setting complex and unique passwords for every account, and managing them efficiently across different devices, is a challenging task. Therefore, using a password manager is highly recommended.

Here is a comparison of common password management solutions:

  • Apple Built-in Password Manager : Usage is restricted on non-Apple devices, and it lacks TOTP integration.
  • Google Built-in Password Manager : Less restricted than Apple, but still limited. It also does not support TOTP, and Chrome's open permissions are too high.
  • 1Password : User-friendly and full-featured, but requires a subscription (Personal $2.99/month, Family $4.99/month).
  • Bitwarden.com : Offers a free plan, but features are limited (no TOTP support), and the premium version costs $1/month.
  • KeePass : An open-source client where users must handle database synchronization themselves.

From the perspective of security and convenience, using 1Password's service directly is recommended. However, if you do not want to pay a recurring fee or prefer not to store all your passwords on someone else's server, self-hosting becomes a more ideal solution.

This tutorial will introduce how to use Vaultwarden (a lightweight, highly efficient Bitwarden server implementation) and Docker Compose to quickly deploy a powerful private password vault completely under your control.

What is Bitwarden?

Bitwarden is a free, open-source password manager supporting all major platforms (desktop, mobile, browser extensions, etc.).

Users can use the official hosting service provided by bitwarden.com, or choose to deploy the official open-source server themselves.

However, note that in both official hosting and self-hosted cases, advanced features (like TOTP) are locked behind payment restrictions.

What is Vaultwarden?

Vaultwarden is an open-source, unofficial Bitwarden server implementation written in Rust. It is extremely lightweight, efficient, and fully compatible with official Bitwarden clients.

Vaultwarden's source code is hosted on GitHub, currently with 48k Stars, and is widely recognized.

With Vaultwarden, you not only control your own data but also unlock all premium features of Bitwarden for free, such as the built-in TOTP authenticator, while still being able to seamlessly use official clients.

1. Environment Preparation

Before starting, you need your own VPS or a NAS system that supports Docker containers.

1. Installing Docker and Docker Compose

This is the foundation of our containerized deployment. If your server does not have it installed yet, you can refer to the following tutorial.

2. Prepare a Domain Name

To access your password manager securely via HTTPS, you need a domain name and must resolve it to your server's IP address.

3. Create Project Directory

Create a dedicated directory for Vaultwarden to store configuration files and data.

1
mkdir -p /opt/vaultwarden

2. Deploying Vaultwarden with Docker Compose

Creating the compose.yml File

In the project directory (/opt/vaultwarden), create a file named compose.yml.

1
2
3
cd /opt/vaultwarden

vim compose.yml

Paste the following content into the file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: always
ports:
- 127.0.0.1:6666:80 # 仅监听本地端口,由反向代理访问
environment:
DOMAIN: "https://vault.yourdomain.com" # 将这里替换为你的实际域名
WEBSOCKET_ENABLED: "true" # 开启 WebSocket,用于客户端实时同步
# SIGNUPS_ALLOWED: "false" # 关闭公开注册,生效需要删除前面的 #
INVITATIONS_ALLOWED: "false" # 关闭邀请功能
volumes:
- ./data:/data

Configuration Explanation:

  • image: Uses the vaultwarden/server:latest image.
  • ports: Maps port 80 of the container to port 6666 of the host. 127.0.0.1 means Vaultwarden can only be accessed via localhost (or a reverse proxy).
  • environment:
    • DOMAIN : Set the domain name to be used.
    • WEBSOCKET_ENABLED: Enabling WebSocket allows real-time communication and sync between your clients and the server.
    • SIGNUPS_ALLOWED: Setting it to false disables new user registration.

      Note: You can remove the leading # to enable this line after registering your account, then restart the service.

  • volumes: Persists all Vaultwarden data (including users, password database, and settings) in the data directory under the current host folder, ensuring data is not lost when the container is updated or rebuilt.

Starting the Vaultwarden Service

In the directory where compose.yml is located, execute the following command to pull the image and start the service:

1
docker compose up -d

3. Configuring Reverse Proxy (Critical Step)

Never expose a password manager without HTTPS to the public internet. We need to use Nginx or another reverse proxy tool to enable SSL/TLS encryption for Vaultwarden.

Below is an Nginx configuration example. You need to obtain an SSL certificate for your domain (e.g., via Let's Encrypt).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# /etc/nginx/conf.d/vault.yourdomain.com.conf
server {
listen 80;
server_name vault.yourdomain.com;

# 将所有 HTTP 请求重定向到 HTTPS
location / {
return 301 https://$host$request_uri;
}
}

server {
listen 443 ssl http2;
server_name vault.yourdomain.com;

# SSL 证书路径
ssl_certificate /path/to/your/fullchain.pem;
ssl_certificate_key /path/to/your/privkey.pem;

# 安全相关的 SSL 设置 (推荐)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;

location / {
client_max_body_size 525M;
proxy_pass http://127.0.0.1:6666;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}

Test and reload Nginx configuration:

1
2
nginx -t
systemctl reload nginx

4. Using Your Self-Hosted Password Vault

  1. Create Account: Visit https://vault.yourdomain.com in your browser and register a user.

  2. Configure Client:

    • Open the Bitwarden browser extension or mobile App.
    • In the login interface, set the server to Self-hosted.
    • In the “Server URL” field, fill in your Vaultwarden access address: https://vault.yourdomain.com
    • Save, and log in with your registered account credentials.

Data Backup

Backups are critical. We must perform regular backups of Vaultwarden's data to avoid losing passwords.

Manual Backup

You can run the following command at any time to create an instant backup.

1
tar zcvf /root/backup/vaultwarden-backup-$(date +%F).tar.gz -C /opt vaultwarden
  • This command backs up the entire /opt/vaultwarden directory to the /root/backup/ directory.
  • $(date +%F) automatically appends the current date (e.g., 2025-08-26) to the file name.
  • The -C /opt vaultwarden parameter avoids including the parent directory /opt/ in the archive file, making the restoration process cleaner.

Automatic Backup (Crontab)

To automate this, we can use crontab to set up scheduled backup tasks.

  1. Edit Crontab

    Run crontab -e to edit the list of scheduled tasks.

  2. Add Scheduled Tasks

    Add the following two lines in the editor:

    1
    2
    3
    4
    5
    # 每天凌晨 3:00 备份 Vaultwarden 数据
    0 3 * * * tar zcvf /root/backup/vaultwarden-backup-$(date +\%F).tar.gz -C /opt vaultwarden >/dev/null 2>&1

    # 每天凌晨 3:05 删除超过 7 天的旧备份
    5 3 * * * find /root/backup -name "vaultwarden-backup-*.tar.gz" -mtime +15 -delete
    • The first command creates a timestamped backup daily at 3:00 AM.
      • Note: In crontab, the % character must be escaped as \%.
      • >/dev/null 2>&1 redirects both standard output and error output to the null device to avoid producing unnecessary email notifications.
    • The second command searches for and deletes all Vaultwarden backup files in the /root/backup directory that are older than 15 days daily at 3:05 AM to save disk space.

Save and exit the editor. The cron service will automatically load the new scheduled tasks.

In addition to creating archive backups, make sure to save the backup files on different devices to prevent loss due to VPS provider failures or NAS drive errors.

For Linux servers, you can use rsync or rclone to regularly sync the /root/backup directory to a storage device.

Conclusion

Congratulations! You now have a secure, powerful password manager completely under your control. By using Docker and Vaultwarden, you can easily protect your digital identity while enjoying a convenient experience that rivals commercial solutions.

Comments
Share

Comments