背景
vaultwardenというパスワードマネージャbitwardenの非公式リポジトリがあります。ぶっちゃけ個人利用していたら普通にbitwardenで十分なのですが、やっぱりパスワードをクラウドで暗号化されていて、取り出しはできないといっても向こう側にデータがあるのが嫌だなぁって思ったりします。ということでセルフホストするんですが、個人でセルフホストするならば、vaultwarden+tailscale+GCE(無料枠)で構築した方がお財布に優しいです。
ですが、なぜCloud Runで構築するか?
それは以下の内容に当てはまれば、もしかしたらCloud Runでの構築を一考しても良いかもしれません。
- すでにGCEの無料枠を使い切っている
- 小規模なので常時稼働するほどのリソースが必要ではない
- 構築するのにお金がかかるのが嫌(GCEってインスタンス起動したらお金かかりますもんねぇ)
私はすべて当てはまりました…
方針
というわけでCloud Runで作るのはいいがそもそも、vaultwardenで利用しているDBは何だろう?と調べた結果、デフォルトSQLiteではないか!?
ということで前回紹介した「label-studio + Cloud Run + Litestreamで作る小規模向けアノテーションツール」で使ったLitestreamでのSQLiteのレプリケーションが使えるので、この記事をそのままvaultwardenに適用してみました。
もちろん構築にはCloud ShellおよびCloud Shellエディタを利用するので、構築費用も無料。なんてお財布に優しい。
では、実際にやっていきましょう。
カスタムvaultwardenイメージの作成
以下の順番通り実施することで、カスタムvaultwardenイメージを作成しました。
Google Cloudコンソールの立ち上げ
ブラウザ経由で進めてもいいが、ターミナルソフトで立ち上げるのが気に入っているので以下のコマンドでGoogle Cloudコンソールを起動する
gcloud cloud-shell ssh --authorize-session
vaultwardenのソースを取得
以下のコマンドでソースを取得する
git clone https://github.com/dani-garcia/vaultwarden.git
Cloud Shell エディタを起動する
マニュアル参照の上、起動する
vaultwardenの導入
ターミナルの作業です。
以下のコマンドで必要なファイルを作成します。
cd vaultwarden
cd src
mkdir new
cd new
touch litestream.yml
touch entrypoint.sh
ここからはCloud Shell エディタ上の作業です。
まずlitestream.ymlを以下のように編集します。
dbs:
- path: /data/db.sqlite3
replicas:
- url: gcs://[Google Cloud Storageのバケット名]/[保存したいフォルダ名]
次に、litestream経由でvaultwardenを起動するシェルスクリプトentrypoint.shを編集します。
#!/bin/bash
set -e
if [ -f /data/db.sqlite3 ]; then
echo "rm old file"
rm /data/db.sqlite3
fi
echo "exec litestream restoring"
litestream restore -if-replica-exists -config /etc/litestream.yml /data/db.sqlite3
# Litestreamによってレプリケーションしながら、アプリケーションを起動する
echo "exec litestream"
exec litestream replicate -exec "/start.sh" -config /etc/litestream.yml
gitクローンによって取得したvaultwardenディレクトリ内にあるDockerfileを以下のように修正する。
:
(省略)
:
### =====================================================
# 以下のROCKET_PORTを80から8080に変更する
### -----------------------------------------------------
ENV ROCKET_PROFILE="release" \
ROCKET_ADDRESS=0.0.0.0 \
ROCKET_PORT=8080 \
DEBIAN_FRONTEND=noninteractive
### -----------------------------------------------------
:
(省略)
:
VOLUME /data
### =====================================================
# 以下のEXPOSEを80から8080に変更する
### -----------------------------------------------------
EXPOSE 8080
### -----------------------------------------------------
# Copies the files from the context (Rocket.toml file and web-vault)
# and the binary from the "build" stage to the current stage
WORKDIR /
COPY docker/healthcheck.sh docker/start.sh /
### =====================================================
# 以下の部分を追加
### -----------------------------------------------------
ADD https://github.com/benbjohnson/litestream/releases/download/v0.3.13/litestream-v0.3.13-linux-amd64.tar.gz /tmp/litestream.tar.gz
RUN tar -C /usr/local/bin -xzf /tmp/litestream.tar.gz
COPY --chmod=755 src/new/entrypoint.sh /usr/bin/entrypoint.sh
COPY src/new/litestream.yml /etc/litestream.yml
### =====================================================
:
(省略)
:
### =====================================================
# 以下の部分を変更
### -----------------------------------------------------
#CMD ["/start.sh"]
CMD ["/usr/bin/entrypoint.sh"]
### =====================================================
Dockerイメージファイルの作成
カレントディレクトリを/vaultwardenに移動し、以下のコマンドを実行しDockerイメージを作成する
docker build -f Dockerfile -t vaultwarden .
ArtifactRegistryへの登録
リポジトリ作成
Google CloudコンソールからArtifactRegistryに移動しvaultwardenのリポジトリを登録する
(必要に応じて実行)リージョンasia-northeast1のDockerリポジトリに対する認証を設定
以下のコマンドを実行し、Dockerリポジトリに対する認証設定をする。
gcloud auth configure-docker asia-northeast1-docker.pkg.dev
タグ付け
ビルドしたDockerイメージに対してArtifactRegistry用にタグ付けをする。
以下のコマンドを実行し、作成したDockerイメージのIMAGE IDを取得する
docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
vaultwarden latest 5064a45a61ea 16 seconds ago 250MB
※上記「docker image list」の出力結果はイメージです。
そのIMAGE IDを用いて以下のコマンドでタグ付けをする。
docker tag 5064a45a61ea asia-northeast1-docker.pkg.dev/[GCPのプロジェクト名]/vaultwarden/202407261200
docker tag [IMAGE ID] [ArtifactRegistryの場所]/[GCPのプロジェクト名]/[リポジトリ名]/[リポジトリで利用するイメージ名]
ArtifactRegistryへ登録
タグ付け後、以下のコマンドでArtifactRegistryに登録する。
docker push asia-northeast1-docker.pkg.dev/[GCPのプロジェクト名]/vaultwarden/202407261200
CloudRunのデプロイ
以下のコマンドで直接Cloud Runサービスを立ち上げることができる。
gcloud run deploy vaultwarden --image asia-northeast1-docker.pkg.dev/[GCPのプロジェクト名]/vaultwarden/202407261200:latest
gcloud run deploy [リポジトリ名] --image [ArtifactRegistryの場所]/[GCPのプロジェクト名]/[リポジトリ名]/[リポジトリで利用するイメージ名]:[tag]
GCPのアクセス権関係の付与
CloudRunで動作するvaultwardenサービスはlitestream.ymlで設定したGCSにアクセスするため、デプロイ後にGoogle Cloudコンソール上でCloudRunサービスにアクセスし、YAML内のserviceAccountNameからサービスアカウント名を確認し、そのサービスアカウントに対して権限を付与する。
storage.buckets.get
storage.buckets.getIamPolicy
storage.buckets.update
storage.objects.create
storage.objects.delete
storage.objects.get
storage.objects.getIamPolicy
storage.objects.list
storage.objects.update
resourcemanager.projects.get
resourcemanager.projects.list
storage.managedFolders.get
storage.managedFolders.list
カスタムドメインでの運用
以下CloudRunサービスにある統合で「インテグレーションを追加」を押して「カスタムドメイン-Google Cloud Load Balancing」を選択する。あとは追加したいドメインを記述して作成することで、カスタムドメイン接続に必要な情報が生成されるので、それを利用する。
カスタムドメインの設定後はLoad BalancerやCloud ArmorやIAPを設定すれば必要最低限のネットアクセスが可能なのでセキュアなサイト構築ができるので、そこは環境に合わせて設定するように。
その他設定
以下の設定は忘れずに
- インスタンス数の最大を1にする
- litestreamが動作しているか、GCSを確認する
- ユーザを作成してから見に行くと良い
- インスタンス数が0になってから再度アクセスし、litestreamのレストアが機能していることを確認する
- 必要に応じてCloud Runのスペックを変更する(私はとりあえずデフォルトで動かして、ログを見て調整する予定)