Triển khai Vaultwarden trên Docker: Tự host máy chủ Bitwarden cho HomeLab của bạn

HomeLab tutorial - IT technology blog
HomeLab tutorial - IT technology blog

Bắt đầu nhanh (5 phút)

Việc quản lý thông tin đăng nhập trên nhiều thiết bị sẽ nhanh chóng trở nên rắc rối khi homelab của bạn ngày càng mở rộng. Vaultwarden giải quyết triệt để vấn đề này. Dự án viết lại API máy chủ Bitwarden bằng Rust, giúp cắt giảm mức tiêu thụ tài nguyên xuống chỉ còn khoảng 30MB RAM so với mức 3GB đến 4GB mà bộ phần mềm .NET và MSSQL chính thức yêu cầu.

Sử dụng tệp docker-compose.yml chuẩn production dưới đây để triển khai Vaultwarden với bộ nhớ lưu trữ bền vững (persistent storage) và tính năng đồng bộ push theo thời gian thực được kích hoạt:

services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      - WEBSOCKET_ENABLED=true
      - SIGNUPS_ALLOWED=true
    volumes:
      - ./vw-data:/data
    ports:
      - 8080:80
      - 3012:3012

Khởi chạy container từ terminal của bạn:

mkdir -p ~/vaultwarden && cd ~/vaultwarden
# Lưu cấu hình ở trên vào file docker-compose.yml
docker compose up -d
docker compose logs -f vaultwarden

Kiểm tra logs. Khi engine đã khởi động xong, hãy truy cập http://<your-server-ip>:8080 trên trình duyệt của bạn. Hãy đăng ký ngay tài khoản admin chính trước khi mở bất kỳ port nào ra mạng ngoài.

Tìm hiểu sâu

Tại sao nên chọn Vaultwarden thay vì Bitwarden chính thức?

Phiên bản Bitwarden chính thức hướng tới hạ tầng doanh nghiệp. Nó phụ thuộc vào hàng chục container microservice, một instance Microsoft SQL Server tốn kém và đòi hỏi lượng RAM rất lớn. Ngược lại, Vaultwarden đóng gói toàn bộ các dịch vụ cần thiết vào một file nhị phân Rust duy nhất đã được biên dịch.

Theo mặc định, nó sử dụng engine SQLite nhúng được kích hoạt sẵn chế độ WAL, mặc dù bạn hoàn toàn có thể kết nối với PostgreSQL hoặc MariaDB nếu khối lượng công việc yêu cầu. Thậm chí một chiếc Raspberry Pi 4 giá $35 với 2GB RAM cũng có thể xử lý mượt mà kho dữ liệu 5.000 mật khẩu cho 10 người dùng hoạt động đồng thời mà không hề bị tăng đột biến độ trễ.

Yêu cầu bắt buộc HTTPS và Web Crypto API

Nếu thử đăng nhập vào một instance Vaultwarden từ xa qua giao thức HTTP thông thường, ứng dụng web sẽ lập tức báo lỗi mã hóa. Đây là cơ chế bảo mật có chủ đích. Các trình duyệt hiện đại bắt buộc môi trường an toàn (secure context) đối với API gốc crypto.subtle của Web Crypto API.

Nếu không có TLS, trình duyệt của client sẽ từ chối trích xuất khóa mã hóa từ master password của bạn. Bạn có thể đáp ứng yêu cầu này bằng cách sử dụng một reverse proxy gọn nhẹ như Caddy để tự động cấp phát và terminate SSL thông qua chứng chỉ Let’s Encrypt:

vault.homelab.local {
    reverse_proxy vaultwarden:80

    # Quy tắc reverse proxy WebSocket để nhận bản cập nhật push tức thì
    reverse_proxy /notifications/hub vaultwarden:3012
    reverse_proxy /notifications/hub/negotiate vaultwarden:80
}

Kiến trúc và đồng bộ hóa theo thời gian thực

Vaultwarden sử dụng hai luồng mạng để duy trì khả năng tương thích hoàn toàn với các ứng dụng Bitwarden chính thức:

  • Port 80: Phục vụ các REST API endpoint tiêu chuẩn, quy trình xác thực người dùng, tài nguyên web vault tĩnh, cũng như các thao tác đọc và ghi vault đã mã hóa.
  • Port 3012: Lắng nghe các kết nối WebSocket. Khi bạn cập nhật một mục trên tiện ích mở rộng trình duyệt ở máy tính, socket này sẽ ngay lập tức kích hoạt delta push tới điện thoại và máy tính bảng của bạn, loại bỏ hoàn toàn thao tác bấm đồng bộ thủ công.

Cấu hình nâng cao

Bảo mật trang quản trị Admin Dashboard bằng Argon2id

Vaultwarden cung cấp trang quản trị bảo trì khẩn cấp tại đường dẫn /admin để cấu hình các biến máy chủ và quản lý lời mời người dùng. Để endpoint này được bảo vệ bởi mật khẩu dạng plain text trong file Compose là một rủi ro bảo mật nghiêm trọng. Thay vào đó, hãy tạo chuỗi hash mã hóa có kèm salt bằng tiện ích tích hợp sẵn của Vaultwarden:

docker run --rm -it vaultwarden/server:latest /vaultwarden hash --preset owasp

CLI sẽ xuất ra chuỗi Argon2id có định dạng tương tự như sau:

$argon2id$v=19$m=65536,t=3,p=4$q+...$aK...

Hãy chèn chuỗi hash này vào tệp docker-compose.yml của bạn. Trong lúc chỉnh sửa, hãy tắt tính năng đăng ký tự do để ngăn chặn người dùng không mong muốn:

    environment:
      - WEBSOCKET_ENABLED=true
      - SIGNUPS_ALLOWED=false
      - ADMIN_TOKEN='$$argon2id$$v=19$$m=65536,t=3,p=4$$q+...$$aK...'
      - INVITATIONS_ALLOWED=true
      - DOMAIN=https://vault.homelab.local

Lưu ý: Hãy escape mỗi ký tự dollar bằng cách nhân đôi nó ($$) trong tệp Docker Compose. Nếu không, Compose engine sẽ coi chuỗi này là một biến hệ thống chưa được gán giá trị và cố gắng nội suy nó.

Thắt chặt xác thực: 2FA và khóa bảo mật phần cứng

Sau khi đăng nhập, hãy vào Account Settings > Security > Two-step Login. Vaultwarden hỗ trợ các ứng dụng xác thực TOTP chuẩn như Aegis và Ente Auth, cùng các token bảo mật phần cứng như Yubikey sử dụng FIDO2 và WebAuthn.

WebAuthn yêu cầu xác thực origin nghiêm ngặt. Biến DOMAIN của bạn phải khớp chính xác với URL HTTPS mà bạn nhập trên thanh địa chỉ trình duyệt, bao gồm cả scheme và port nếu không dùng port tiêu chuẩn.

Kinh nghiệm thực tế

Sao lưu cơ sở dữ liệu nguyên tử (Atomic Backup) không gián đoạn dịch vụ

Tuyệt đối không sao chép trực tiếp file cơ sở dữ liệu SQLite đang hoạt động như db.sqlite3 bằng các lệnh thông thường như cp. Bạn có nguy cơ sao chép phải các transaction chưa được commit từ file WAL, gây hỏng bản snapshot sao lưu. Thay vào đó, hãy gọi online backup API của SQLite thông qua công cụ dòng lệnh trên máy chủ host:

#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR="/opt/backups/vaultwarden"
DATA_DIR="${HOME}/vaultwarden/vw-data"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
mkdir -p "${BACKUP_DIR}"

# Trích xuất an toàn bản snapshot SQLite nguyên tử mà không cần dừng container
sqlite3 "${DATA_DIR}/db.sqlite3" ".backup '${BACKUP_DIR}/vault_${TIMESTAMP}.sqlite3'"

# Nén lưu trữ các khóa mã hóa và tệp đính kèm
tar -czf "${BACKUP_DIR}/data_${TIMESTAMP}.tar.gz" -C "${DATA_DIR}" attachments rsa_key.pem

# Dọn dẹp các bản sao lưu cũ hơn 14 ngày
find "${BACKUP_DIR}" -type f -mtime +14 -delete

Script này thực thi chỉ trong chưa đầy 200 mili-giây trên các hệ thống có cấu hình khiêm tốn. Hãy thiết lập cron job chạy script này hàng đêm vào lúc 03:00, đồng thời đồng bộ thư mục sao lưu ra bên ngoài tới một dịch vụ lưu trữ mã hóa như Backblaze B2 hoặc máy chủ TrueNAS từ xa.

Kết nối các ứng dụng client Bitwarden chính thức

Bạn có thể sử dụng các ứng dụng Bitwarden tiêu chuẩn, không cần chỉnh sửa trên iOS, Android, macOS, Linux và Windows. Để liên kết client với máy chủ tự host của bạn:

  1. Mở extension Bitwarden hoặc ứng dụng gốc trên thiết bị di động.
  2. Nhấp vào biểu tượng bánh răng Cài đặt trên màn hình đăng nhập trước khi nhập thông tin tài khoản.
  3. Nhập tên miền của bạn vào trường Server URL: https://vault.homelab.local.
  4. Lưu cài đặt, nhập email và master password, sau đó hoàn tất bước xác thực 2FA.

Giờ đây, các mục trong vault của bạn sẽ được đồng bộ ngay lập tức thông qua máy chủ riêng, hoàn toàn không có dữ liệu thu thập từ xa (telemetry) hay mật khẩu dạng plain text nào lọt ra khỏi mạng nội bộ của bạn.

Share: