DockerでVaultwardenを構築:HomeLab向けのセルフホスト型Bitwardenサーバー

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

クイックスタート(5分)

HomeLabの規模が大きくなるにつれて、複数デバイス間の認証情報管理は急速に煩雑化します。Vaultwardenはこの課題をスマートに解決してくれます。BitwardenサーバーのAPIをRustで再実装しており、公式の.NETとMSSQLスタックが必要とする3GB〜4GBのメモリに対して、わずか30MB程度のRAM消費へと劇的に削減します。

永続ストレージとリアルタイムプッシュ同期を有効化した、本番運用に対応するdocker-compose.ymlファイルは以下の通りです:

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

ターミナルからコンテナを起動します:

mkdir -p ~/vaultwarden && cd ~/vaultwarden
# 上記の設定をdocker-compose.ymlに保存します
docker compose up -d
docker compose logs -f vaultwarden

ログを確認してください。エンジンが起動したら、ブラウザでhttp://<your-server-ip>:8080にアクセスします。外部ネットワークにポートを開放する前に、まず最初の管理者アカウントを登録してください。

詳細解説

公式BitwardenではなくVaultwardenを選ぶ理由

公式のBitwardenはエンタープライズインフラを想定して設計されています。十数個のマイクロサービスコンテナや高価なMicrosoft SQL Serverインスタンス、そして大量のメモリリソースを消費します。対してVaultwardenは、必要なすべてのサービスをコンパイル済みの単一Rustバイナリに凝縮しています。

デフォルトではWALモードが有効化された組み込みSQLiteエンジンが使用されますが、ワークロードの必要性に応じてPostgreSQLやMariaDBと連携させることも可能です。わずか35ドルのRaspberry Pi 4(RAM 2GB)であっても、10人の同時アクティブユーザーによる5,000件のパスワードライブラリを遅延なく軽快に処理できます。

HTTPSの必須要件とWeb Crypto API

暗号化されていないプレーンなHTTP経由でリモートのVaultwardenインスタンスにログインしようとすると、Webアプリは即座に暗号化エラーで失敗します。これは意図された挙動です。最近のWebブラウザは、ネイティブのcrypto.subtle Web Crypto APIに対してセキュアコンテキストを必須要件として強制しているためです。

TLSがない状態では、クライアントブラウザはマスターパスワードからの暗号化キー導出を拒否します。この要件を満たすには、Caddyのような軽量リバースプロキシを利用し、Let’s Encrypt証明書を介してSSL/TLSを自動終端するのが便利です:

vault.homelab.local {
    reverse_proxy vaultwarden:80

    # 即時プッシュ更新のためのWebSocketリバースプロキシ設定
    reverse_proxy /notifications/hub vaultwarden:3012
    reverse_proxy /notifications/hub/negotiate vaultwarden:80
}

アーキテクチャとリアルタイム同期

Vaultwardenは、本家Bitwardenアプリとの完全な互換性を維持するために2つのネットワーク経路を使用します:

  • ポート 80: 標準的なREST APIエンドポイント、ユーザー認証フロー、静的Web保管庫アセット、暗号化された保管庫データの読み書きを処理します。
  • ポート 3012: WebSocket接続をリッスンします。デスクトップのブラウザ拡張機能でエントリを更新すると、このソケットを介してスマートフォンやタブレットへ即座に差分プッシュ通知がトリガーされ、手動同期の操作が不要になります。

高度な設定

Argon2idによる管理ダッシュボードの保護

Vaultwardenには、サーバー変数の設定やユーザー招待を管理するための非常用管理ダッシュボード(/admin)が用意されています。Composeファイル内でこのエンドポイントを平文パスワードのまま保護することは重大なセキュリティリスクとなります。代わりに、Vaultwardenの内蔵ユーティリティを使ってソルト付きの暗号化ハッシュを生成しましょう:

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

CLIから次のような形式のArgon2id文字列が出力されます:

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

このハッシュをdocker-compose.ymlファイルに入力します。その際、不要な第三者の登録を防ぐために新規登録を無効化(SIGNUPS_ALLOWED=false)しておきましょう:

    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

注: Docker Composeファイル内では、ドル記号を2重($$)にしてエスケープしてください。エスケープしない場合、Composeエンジンが未設定のシステム環境変数として展開しようとしてしまいます。

認証の強化:2FAとハードウェアセキュリティキー

ログイン後、アカウント設定 > セキュリティ > 2段階ログインに移動します。Vaultwardenは、AegisやEnte Authなどの標準的なTOTP認証アプリに加え、FIDO2およびWebAuthnを用いたYubikeyなどのハードウェアセキュリティキーにも対応しています。

WebAuthnでは厳密なオリジン検証が要求されます。そのため、DOMAIN変数の値は、ブラウザのアドレスバーに入力する正確なHTTPS URL(非標準ポートの場合はポート番号も含める)と一致している必要があります。

実践的な運用Tips

ダウンタイムなしのアトミックなデータベースバックアップ

稼働中のSQLiteデータベースファイル(db.sqlite3)をcpなどの通常のコマンドで直接コピーしてはいけません。WALファイル内のコミットされていないトランザクションを拾ってしまい、結果としてバックアップスナップショットが破損する恐れがあります。代わりに、ホストのCLIツール経由でSQLiteのオンラインバックアップAPIを呼び出します:

#!/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}"

# コンテナを停止することなく、アトミックなSQLiteスナップショットを安全にダンプ
sqlite3 "${DATA_DIR}/db.sqlite3" ".backup '${BACKUP_DIR}/vault_${TIMESTAMP}.sqlite3'"

# 暗号化キーと添付ファイルをアーカイブ
tar -czf "${BACKUP_DIR}/data_${TIMESTAMP}.tar.gz" -C "${DATA_DIR}" attachments rsa_key.pem

# 14日以上前のアーカイブを削除
find "${BACKUP_DIR}" -type f -mtime +14 -delete

このスクリプトは、一般的なスペックのマシンでも200ミリ秒未満で完了します。cronを利用して毎晩午前3時に自動実行し、バックアップディレクトリの内容をBackblaze B2やリモートのTrueNASサーバーなどの暗号化ストレージへオフサイト同期することをおすすめします。

公式Bitwardenクライアントアプリの接続

iOS、Android、macOS、Linux、Windows向けの公式かつ無改造のBitwardenアプリをそのまま使用できます。クライアントをセルフホストしたサーバーに接続する手順は以下の通りです:

  1. Bitwardenのブラウザ拡張機能またはネイティブアプリを開きます。
  2. 認証情報を入力する前に、ログイン画面にある設定(歯車アイコン)をクリックします。
  3. サーバーURL欄に独自のドメインを入力します(例: https://vault.homelab.local)。
  4. 設定を保存し、メールアドレスとマスターパスワードを入力して2段階認証を完了します。

これで、テレメトリや平文の認証情報がホームネットワーク外に送信されることなく、プライベートサーバー経由で安全かつ瞬時に保管庫データが同期されます。

Share: