LassPass を捨てて独自ドメインの bitwarden へ移行しました

LassPassよ、ありがとう。

今年2月、LassPass の規約が改変されました。

パスワード管理「LastPass」の無料版、3月にスマホかデスクトップかの選択必須に
https://www.itmedia.co.jp/news/articles/2102/17/news056.html

LastPassはパスワード管理ソフトとして、とても有用でした。増え続けるパスワードは管理が煩雑となります。ブラウザでログインする際に、自動で補完してくれたりするので便利に使っていました。
しかし、これも無料化から実質有料化へとなってしまいました。自分はスマホとデスクトップ両方に LassPass を入れていたので、有料化しなければいけません。

月3ドルの費用自体は別に対した事は無いのですが、今後も規約が変わっていくとも限りません。パスワード保存量に対して課金とか、そういった事になったら大変です。

それならば今の内に…という訳で、ソースが公開されている Bitwarden へ移行する事に決めました。

そこはへそ曲がりな自分

で、その Bitwarden ですが意外とメモリを食う、そして Docker を利用しなければならない…という理由で移行に二の足を踏んでいたのですが、Unofficial版として軽量な bitwarden_rs があるという事を発見。情報によれば、AWS t2.micro (メモリ 1GB) や Google Cloud f1miro (メモリ 0.6GB)でも問題なく動くとの事。

これならばいざ移行するのも楽ですし、自分はデータセンターのラック契約しているのでそこにぶちこんでしまおうと思いました。ベースとなるOSは CentOS7 です。ここに docker と docker-compose をインストールします。このインストール方法はぐぐればいくらでも出てくるので割愛します。

必須条件

  1. docker と docker コンテナ が動作しているサーバと知識
  2. 独自ドメイン
  3. 独自ドメインのメールアドレスがある事

こんな感じです。独自ドメインでの運用となりますが、構築前にこの独自ドメイン(自分の場合はサブドメイン)をDNSで設定しておきました。同様に、そのドメインで受信できるメールアドレスも作成してあります。何故これが必要なのかというと、docker-compose up する際にデータをダウンロードしたあと、自動で Let’s Encrypt によるSSL取得を行うからです。

このSSLが取得できないと、bitwarden_rs は起動しません。これ重要です。

インストール

Using Docker Compose のページにインストール方法が書いてあります。自分は /home/bitwarden 以下にファイルを置く事にしました。(めんどいので root になって作業しています)

# mkdir -p /home/bitwarden
# cd /home/bitwarden
# vi docker-compose.yml
version: '3'

services:
  bitwarden:
    image: bitwardenrs/server:latest
    container_name: bitwarden
    restart: always
    environment:
      - WEBSOCKET_ENABLED=true  # Enable WebSocket notifications.
    volumes:
      - ./bw-data:/data

  caddy:
    image: caddy:2
    container_name: caddy
    restart: always
    ports:
      - 80:80  # Needed for the ACME HTTP-01 challenge.
      - 443:443
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy-config:/config
      - ./caddy-data:/data
    environment:
      - DOMAIN=bitwarden.example.com  # ここを自分の独自ドメインに修正する事
      - EMAIL=admin@example.com       # 独自ドメインに属したメールアドレスを記載する
      - LOG_FILE=/data/access.log
# vi Caddyfile
{$DOMAIN}:443 {
  log {
    level INFO
    output file {$LOG_FILE} {
      roll_size 10MB
      roll_keep 10
    }
  }

  # Use the ACME HTTP-01 challenge to get a cert for the configured domain.
  tls {$EMAIL}

  # This setting may have compatibility issues with some browsers
  # (e.g., attachment downloading on Firefox). Try disabling this
  # if you encounter issues.
  encode gzip

  # Notifications redirected to the WebSocket server
  reverse_proxy /notifications/hub bitwarden:3012

  # Proxy everything else to Rocket
  reverse_proxy bitwarden:80 {
       # Send the true remote IP to Rocket, so that bitwarden_rs can put this in the
       # log, so that fail2ban can ban the correct IP.
       header_up X-Real-IP {remote_host}
  }
}

Caddyfile の方は特に変更する必要はありません。
docker-compose.yml はそれぞれの環境に合わせて変更しましょう。

起動

まずは普通に起動してログを確認します。
自動でダウンロードしてセットアップをしてくれるので、とても楽ですね。

# docker-compose up
Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/
Creating network "bitwarden_default" with the default driver
Creating bitwarden ... done
Creating caddy     ... done
Attaching to bitwarden, caddy
bitwarden    | /--------------------------------------------------------------------\
bitwarden    | |                       Starting Bitwarden_RS                        |
bitwarden    | |                           Version 1.19.0                           |
bitwarden    | |--------------------------------------------------------------------|
bitwarden    | | This is an *unofficial* Bitwarden implementation, DO NOT use the   |
bitwarden    | | official channels to report bugs/features, regardless of client.   |
bitwarden    | | Send usage/configuration questions or feature requests to:         |
bitwarden    | |   https://bitwardenrs.discourse.group/                             |
bitwarden    | | Report suspected bugs/issues in the software itself at:            |
bitwarden    | |   https://github.com/dani-garcia/bitwarden_rs/issues/new           |
bitwarden    | \--------------------------------------------------------------------/
bitwarden    |
bitwarden    | [INFO] No .env file found.
bitwarden    |
bitwarden    | [2021-03-14 21:52:08.360][parity_ws][INFO] Listening for new connections on 0.0.0.0:3012.
bitwarden    | [2021-03-14 21:52:08.360][start][INFO] Rocket has launched from http://0.0.0.0:80
caddy        | {"level":"info","ts":1615784814.3830686,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
caddy        | {"level":"info","ts":1615784814.3857284,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["127.0.0.1:2019","localhost:2019","[::1]:2019"]}
caddy        | {"level":"info","ts":1615784814.3862705,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc00043b110"}
caddy        | {"level":"info","ts":1615784814.3863149,"logger":"http","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
caddy        | {"level":"info","ts":1615784814.3863366,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
caddy        | {"level":"info","ts":1615784814.3870745,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["password.example.com"]}
caddy        | {"level":"info","ts":1615784814.387291,"logger":"tls","msg":"cleaned up storage units"}
caddy        | {"level":"info","ts":1615784814.3875294,"msg":"autosaved config","file":"/config/caddy/autosave.json"}
caddy        | {"level":"info","ts":1615784814.3875446,"msg":"serving initial configuration"}
caddy        | {"level":"info","ts":1615784814.3878062,"logger":"tls.obtain","msg":"acquiring lock","identifier":"password.example.com"}
caddy        | {"level":"info","ts":1615784814.3883169,"logger":"tls.obtain","msg":"lock acquired","identifier":"password.example.com"}
caddy        | {"level":"info","ts":1615784814.400098,"logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":["password.example.com"]}
caddy        | {"level":"info","ts":1615784814.4001138,"logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":["password.example.com"]}
caddy        | {"level":"info","ts":1615759721.647704,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"password.example.com","challenge_type":"http-01","ca":"https://acme-v02.api.letsencrypt.org/directory"}
caddy        | {"level":"info","ts":1615759721.9695313,"logger":"tls.issuance.acme","msg":"served key authentication","identifier":"password.example.com","challenge":"http-01","remote":"34.209.232.166:24640"}
caddy        | {"level":"info","ts":1615759724.0847294,"logger":"tls.issuance.acme","msg":"served key authentication","identifier":"password.example.com","challenge":"http-01","remote":"64.78.149.164:49556"}
caddy        | {"level":"info","ts":1615759724.1678112,"logger":"tls.issuance.acme","msg":"served key authentication","identifier":"password.example.com","challenge":"http-01","remote":"3.128.26.105:64616"}
caddy        | {"level":"info","ts":1615759724.201121,"logger":"tls.issuance.acme","msg":"served key authentication","identifier":"password.example.com","challenge":"http-01","remote":"52.28.236.88:30412"}
caddy        | {"level":"info","ts":1615759726.9565146,"logger":"tls.issuance.acme.acme_client","msg":"validations succeeded; finalizing order","order":"https://acme-v02.api.letsencrypt.org/acme/order/1848454658/898498416294"}
caddy        | {"level":"info","ts":1615759728.2850935,"logger":"tls.issuance.acme.acme_client","msg":"successfully downloaded available certificate chains","count":2,"first_url":"https://acme-v02.api.letsencrypt.org/acme/cert/046b9784841fd24fcffd5aa0dcc9b9922b7b0a"}
caddy        | {"level":"info","ts":1615759728.285504,"logger":"tls.obtain","msg":"certificate obtained successfully","identifier":"password.example.com"}
caddy        | {"level":"info","ts":1615759728.2855206,"logger":"tls.obtain","msg":"releasing lock","identifier":"password.example.com"}

password.example.com というドメインで設定した例です。
途中で、https://acme-v02.api.letsencrypt.org/ を叩いて SSL を取得しに行っていますね。Let’s Encrypt なので有効期限は当然90日です。bitwarden は再起動時に自動で SSL を更新しに行ってくれるので、特にやることはありません。

この状態でブラウザからアクセスするとこんな感じでログが表示されます。

bitwarden    | [2021-03-14 21:58:03.801][request][INFO] POST /api/accounts/register
bitwarden    | [2021-03-14 21:58:03.903][response][INFO] POST /api/accounts/register (register) => 200 OK
bitwarden    | [2021-03-14 21:58:12.979][request][INFO] POST /api/accounts/prelogin
bitwarden    | [2021-03-14 21:58:12.980][response][INFO] POST /api/accounts/prelogin (prelogin) => 200 OK
bitwarden    | [2021-03-14 21:58:13.109][request][INFO] POST /identity/connect/token
bitwarden    | [2021-03-14 21:58:13.193][bitwarden_rs::api::identity][INFO] User pass@example.com logged in successfully. IP: 100.100.100.100
bitwarden    | [2021-03-14 21:58:13.193][response][INFO] POST /identity/connect/token (login) => 200 OK
bitwarden    | [2021-03-14 21:58:13.280][request][INFO] GET /api/sync?excludeDomains=true
bitwarden    | [2021-03-14 21:58:13.281][response][INFO] GET /api/sync?<data..> (sync) => 200 OK
bitwarden    | [2021-03-14 21:58:13.305][parity_ws::io][INFO] Accepted a new tcp connection from 172.22.0.2:43348.

F/WとL/Bを設定してから独自ドメインにアクセスすると、ログイン画面が出てきました。ちゃんと SSL 化されているのでとても安全です。これで問題無い事が判ったので、正式に起動し直します。

# docker-compose up -d
#docker-compose up -d
Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/
Starting bitwarden ... done
Starting caddy     ... done

#docker ps
CONTAINER ID   IMAGE                       COMMAND                  CREATED             STATUS                       PORTS                                                NAMES
19a01014e0d5   caddy:2                     "caddy run --config …"   About an hour ago   Up About an hour             0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp, 2019/tcp   caddy
cb78f854156   bitwardenrs/server:latest   "/usr/bin/dumb-init …"   About an hour ago   Up About an hour (healthy)   80/tcp, 3012/tcp                                     bitwarden
489c42ea88e8   portainer/portainer         "/portainer"             2 hours ago         Up 2 hours                   0.0.0.0:9000->9000/tcp                               portainer

ちゃんと起動していますね。設定だと *:80 と *:443 を占拠するので気をつけてください。
あとは定期的にこんな感じで crontab に書いておけば、最新版にアップデートしてくれます。

# docker-compose pull && docker-compose down && docker-compose up -d

アカウントを作成して、ログインするとこんな感じになりました。

残作業

これもめんどくさいのでぐぐってください。
基本的には、LassPass から CSV でエクスポートして、bitwarden の[ツール]から[データのインポート]をクリックして、「インポートするファイルの形式を選択」から[LassPass (csv)] を選択して、エクスポートした csv を読み込ませれば完了です。

LassPass からの移行方法

あとはブラウザ用のアドオンを入れたり、スマホアプリで Bitwarden パスワードマネージャー をインストールするだけです。気をつけなければいけないのは、このままログインしようとすると、 Bitwarden のサイトの方へ行ってしまいます。左上の歯車を押すと、サーバの URL を入力する画面が出てきますので、そこに自分の設定した独自ドメインを記載してください。

これでしばらく運用して問題が無ければ、 LassPass のアカウントをざっくりと削除して完了です!
今までありがとうございました!

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください