Cloudflare+Let'sEncryptを使い、セルフホスティングBitwardenをTraefik経由で公開する

1.はじめに

初投稿です。自宅サーバでBitwardenをセルフホスティングしてるけど、万が一色々吹っ飛んだら嫌だなーと思い、設定を外に残しておきたくなったので…バックアップは取ってるんだけどね。
また、本記事ではdockerなりTraefikなり使うけど、完全に独学なので間違っている箇所などあると思うのであんまり信用しないでください。何かあっても責任は取りません。

2.構成情報

  • OS: Ubuntu Server 22.04 64bit  (on ESXi8)

  • docker version: 24.0.6

  • docker-compose version: 1.29.2

  • Traefik version: 2.10.5

  • Bitwarden version: 2023.9.0

  • domain: hogehoge.net

  • certs: Let's Encrypt (BitwardenをサブドメインにしたいのでTraefikを使ってDNSチャレンジで取得)

3.Traefikの構築

と言ってもコンテナなので大したことじゃないけど。
/opt/docker/traefikに色々置く前提で。
後に使うdocker-shareという名前のdockerネットワークを作っておく。名前はご自由に。ただし、docker-compose.ymlの設定を記載しているところは置換が必要となる。

mkdir -p /opt/docker/traefik
cd /opt/docker/traefik
docker network create docker-share

docker-compose.ymlを配置。おそらく一番ここおかしいんじゃね?と指摘が来そうな箇所。
labels はTraefikも外部公開したい場合に必要。不要なら記載不要。外部からの疎通確認のために書いておくとラクかもしれない。

vi docker-compose.yml

version: '3.3'
services:
  traefik:
    image: traefik:2.10.5
    restart: always
    container_name: traefik
    command:
      # Global settings
      # - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--api.dashboard=true"
      # Providers
      - "--providers.docker=true"
      - "--providers.docker.exposedByDefault=false"
      - "--providers.file.filename=/etc/traefik/dynamic.yaml"
      # Entrypoints
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.websecure.http.tls=true"
      - "--entrypoints.websecure.http.tls.certResolver=letsencrypt"
      - "--entrypoints.websecure.http.tls.domains[0].main=hogehoge.net"
      - "--entrypoints.websecure.http.tls.domains[0].sans=*.hogehoge.net"
      # LetsEncrypt settings
      - "--certificatesresolvers.letsencrypt.acme.email=your@mail.com"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare"
      - "--certificatesResolvers.letsencrypt.acme.dnschallenge.resolvers=1.1.1.1:53,1.0.0.1:53"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      #- '--certificatesresolvers.cloudflare.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory'
    environment:
      - TZ=Asia/Tokyo
      - LEGO_DISABLE_CNAME_SUPPORT=true
      - CF_API_EMAIL=your@mail.com
      - CF_API_KEY=XXXXXXXXXXXXXXXX
      - CF_DNS_API_TOKEN=XXXXXXXXXXXXXXXX
      - CF_ZONE_API_TOKEN=XXXXXXXXXXXXXXXX
    labels:
      # global redirect to https
      - 'traefik.enable=true'
      - 'traefik.http.routers.traefik.rule=Host(`traefik.hogehoge.net`)'
      - 'traefik.http.routers.traefik.entrypoints=websecure'
      - 'traefik.http.routers.traefik.tls.certresolver=letsencrypt'
      - 'traefik.http.routers.traefik.service=api@internal'
      - 'traefik.http.routers.traefik.middlewares=strip'
      # - 'traefik.http.routers.traefik.middlewares=tf_basicauth'
      - 'traefik.http.middlewares.strip.stripprefix.prefixes=/traefik'
      # - 'traefik.http.middlewares.tf_basicauth.basicauth.realm=tf_realm'
      # - 'traefik.http.middlewares.tf_basicauth.basicauth.users=traefik:$$apr1$$XXXXXXXX$$YYYYYYYYYYYYYYYY'
    ports:
      - 80:80
      - 443:443
      - 3080:8080 # webUI
    volumes:
      - "./letsencrypt:/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./dynamic.yaml:/etc/traefik/dynamic.yaml"
      #- "./traefik.toml:/traefik.toml"
    networks:
      - docker-share

networks:
  docker-share:
    external: true

dynamic.yamlの配置。暗号化周りとか。

vi dynamic.yaml

tls:
  options:
    default:
      minVersion: VersionTLS12
      cipherSuites:
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
        - TLS_AES_128_GCM_SHA256
        - TLS_AES_256_GCM_SHA384
        - TLS_CHACHA20_POLY1305_SHA256
      curvePreferences:
        - CurveP521
        - CurveP384
      sniStrict: true
http:
  middlewares:
    secHeaders:
      headers:
        browserXssFilter: true
        contentTypeNosniff: true
        frameDeny: true
        customFrameOptionsValue: "SAMEORIGIN"
        sslRedirect: true
        #HSTS Configuration
        stsIncludeSubdomains: true
        stsPreload: true
        stsSeconds: 15768000

CloudflareのSSL/TLS暗号化モードをフル(厳密)にする。

Traefikコンテナを起動。

docker-compose up -d

外部公開している場合はブラウザからhttps://traefik.hogehoge.netを開く。
いかにもTraefikなページが表示されればOK。
一旦、コンテナを止める。

docker-compose down

4.Bitwardenの構築

こちらは途中までほぼ公式のままに進めていく。

同じく、/opt/docker/bitwardenに色々置く感じに。
細かいパーミッション周りは公式サイトを参考に補完して…

mkdir -p /opt/docker/bitwarden
cd /opt/docker/bitwarden

Bitwardenのダウンロードとインストール。

curl -Lso bitwarden.sh "https://func.bitwarden.com/api/dl/?app=self-host&platform=linux" && chmod 700 bitwarden.sh
./bitwarden.sh install

いくつか対話形式で初期設定を行う。一つ目はBitwardenのURL。
今回はhogehoge.netのサブにしたいので、bitwarden.hogehoge.netとする。

Enter the domain name for your Bitwarden instance (ex. bitwarden.example.com):bitwarden.hogehoge.net

Bitwardenは標準機能でLet'sEncryptを取得することが出来る。
しかし、証明書はTraefikが取ってくれているので今回ここでは不要。

Do you want to use Let's Encrypt to generate a free SSL certificate? (y/n):n

ここは好きにして。

Enter the database name for your Bitwarden instance (ex. vault):vault

書いてあるまま。サイトを開いて、INSTALLATION IDとINSTALLATION KEYを生成してコピペ。

Enter your installation id (get at https://bitwarden.com/host):XXXXXXXX-XXXX-XXXX-XXXXXXXXXXXX
Enter your installation key:XXXXXXXXXXXXXXXXXXXX

リージョンはUSでいいでしょう。空EnterもしくはUSと入力。

Enter your region (US/EU) [US]:US

これもTraefikでやるのでいいえ。

Do you have a SSL certificate to use? (y/N):N

上と同様にいいえ。

Do you want to generate a self-signed SSL certificate? (y/N):N

bitwardenの下にbwdataディレクトリが作られてる。

cd bwdata/

config.ymlを編集。
httpポートとhttpsポートを適当なのに変更。(Traefikと被るため)

vi config.yml

# http_port: 80
http_port: 8080
# https_port: 443
https_port: 8443

dockerディレクトリに移動し、docker-compose.override.ymlを作成。
LabelsがBitwardenとTraefikの連携部分。

cd docker/
vi docker-compose.override.yml

version: '3'
services:
  nginx:
    ports:
      - '8080:8080'
      - '8443:8443'
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=docker-share"
      - "traefik.http.routers.bitwarden.rule=Host(`bitwarden.hogehoge.net`)"
      - "traefik.http.routers.bitwarden.entrypoints=websecure"
      - "traefik.http.services.bitwarden.loadbalancer.server.port=8080"
    networks:
      - docker-share
      - default
      - public

networks:
  docker-share:
    external: true

bitwarden.shがあるディレクトリまでcd。

cd /opt/docker/bitwarden

rebuildを実行。

./bitwarden.sh rebuild

rebuild完了後、起動する。

./bitwarden.sh start

起動し、OKとなったら今度はTraefikのコンテナを起動する。

cd /opt/docker/traefik/
docker-compose up -d

ブラウザからhttps://bitwarden.hogehoge.netにアクセスし、Bitwardenのページが表示されればOK。
あとは、Bitwardenの使い方の話になるので使って覚えるなりすればいいかなと。
と、投げすぎるのもあれなので…
せめてアカウントの追加登録が出来ない設定くらいはここに書いておこう。
globalSettings__disableUserRegistrationがデフォルトでfalseなので、アカウントを作り終わったらtrueに変えましょう。(要コンテナ再起動)

cd /opt/docker/bitwarden/bwdata/env/
vi global.override.env

# globalSettings__disableUserRegistration=false
globalSettings__disableUserRegistration=true

cd /opt/docker/bitwarden/
./bitwarden.sh restart

5.終わり

参考リンク


この記事が気に入ったらサポートをしてみませんか?