きっかけ
今まで YunoHost という初心者向けのセルフホスト特化の OS を使って色々立てていたが、YunoHost 向けにカスタムされたアプリ しかホストできない制約のため、飽きてきていた。少し前からウォッチしている r/selfhosted で発見した面白いサービスを試すため、YunoHost を卒業することにした。
VPS の選定
YunoHost は Linode の Shared CPU Plan の RAM 2GB で動かしていたが、コスト削減のために見直すことに。 要件としては
- RAM 2 GB 以上
- 日本からのレイテンシが 100 ms 以下
- ディスクが SATA SSD 及び NVMe SSD
の2点のみで、できるだけ安価なものを絞った。
プロバイダー | vCPU | RAM | ディスク容量 | リージョン | 価格 (月) | 備考 |
---|---|---|---|---|---|---|
Linode | 1 vCPU | 2 GB | 50 GB | 東京 | $10 | - |
OVH (Starter) | 1 vCPU | 2 GB | 20 GB | シンガポール | $3.5 | - |
OVH (Value) | 1 vCPU | 2 GB | 40 GB | シンガポール | $6 | - |
VirMach | 2 vCPU | 2 GB | 50 GB | 東京 | $10 | 初年度のみ $60/年 |
ディスク容量が少々不安だが、OVH の Starter プランに決定。理由はもちろん価格である。ディスク容量が足りなくなってきたら Value プランに変更すればいいだろうということで、とりあえず契約。
今まで使ってきた Vultr や Linode などと比べて、購入から実際に使用できるようになるまで少し時間がかかった。具体的には覚えていないが、メールを遡ってみると PayPal のレシートが届いてから OVH からログイン情報が届くまで20分程度かかっている。
構成
OS は Debian で、サービスはすべて Docker で運用し、リバースプロキシは Traefik を採用。証明書の発行は Cloudflare で行う。また、各イメージは Watchtower で自動的にアップデートし、Gotify に通知する。
基本的には BaptisteBdn/docker-selfhosted-apps を参考にした。
Docker の導入
公式ドキュメント に従ってインストールする。Docker のバージョンアップに伴って Docker Compose のインストール方法やコマンドが変わっていた。
Traefik (+ socket-proxy) の導入
ファイル構成
|
|
ファイルの作成
BaptisteBdn/docker-selfhosted-apps を参考にし、各ファイルを作成する。
- docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
version: "3" networks: proxy: external: true services: traefik: # The official v2 Traefik docker image image: traefik:latest container_name: traefik restart: unless-stopped depends_on: - socket-proxy ports: # The HTTP port - "80:80" - "443:443" networks: - proxy labels: - "traefik.enable=true" # global redirect to https - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)" - "traefik.http.routers.http-catchall.entrypoints=http" - "traefik.http.routers.http-catchall.middlewares=redirect-to-https" # middleware redirect - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https" - "traefik.http.middlewares.redirect-to-https.redirectscheme.permanent=true" # Watchtower update - "com.centurylinklabs.watchtower.enable=true" volumes: # So that Traefik can listen to the Docker events - "/var/run/docker.sock:/var/run/docker.sock" # To read certs - "./ssl/tls-certs.yml:/ssl/tls-certs.yml:ro" - "./ssl/<ドメイン名>.pem:/ssl/<ドメイン名>.pem:ro" - "./ssl/<ドメイン名>.key:/ssl/<ドメイン名>.key:ro" - "./traefik.yml:/traefik.yml:ro" socket-proxy: image: tecnativa/docker-socket-proxy container_name: traefik-socket-proxy restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock:ro environment: CONTAINERS: 1 labels: - "com.centurylinklabs.watchtower.enable=true" networks: - proxy
参考元にならって socket-proxy も導入している。Traefik が docker.sock に対して自由にアクセスできると、Traefik が攻撃を受けたときにホストにも影響が及んでしまうため、プロキシを挟んで docker.sock を保護するらしい。(合ってる?)
-
.env
1 2 3
# DOMAIN.TLD = example.com DOMAIN=example TLD=com
自分のドメインで置き換える。
-
tls-certs.yml
1 2 3 4 5 6 7 8 9
tls: certificates: - certFile: ssl/<ドメイン名>.pem keyFile: ssl/<ドメイン名>.key stores: default: defaultCertificate: certFile: ssl/<ドメイン名>.pem keyFile: ssl/<ドメイン名>.key
-
traefik.yml
1 2 3 4 5 6 7 8 9 10 11 12 13
providers: docker: exposedByDefault: false network: proxy file: filename: ./ssl/tls-certs.yml entryPoints: http: address: ":80" https: address: ":443" tls: entryPoints: https
Cloudflare で証明書を発行する
Cloudflare のダッシュボード から発行する。なお、ドメインはすでに登録してあり、DNS レコードも設定してあるものとする。
証明書を発行したいドメインを選択し、[SSL/TLS] > [オリジン サーバー] > [証明書を作成] > [作成] から発行する。
キーフォーマットは PEM を指定し、オリジン証明書とプライベートキーをそれぞれ <Traefikのディレクトリ>/ssl/
に <ドメイン名>.pem
<ドメイン名>.key
で保存する。(各ファイルは Traefik の docker-compose.yml の30-31行目で指定してあるので、該当箇所を変更すれば場所やファイル名は自由である)
[SSL/TLS] > [概要] から SSL/TLS 暗号化モードを「フル (厳密)」に設定する。
起動
準備が終わったらコンテナを起動する。
|
|
ログの確認は下記のコマンドで行う。
|
|
Gotify の導入
ファイル構成
|
|
ファイルの作成
-
docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
version: "3" networks: proxy: external: true services: gotify: image: gotify/server container_name: gotify restart: unless-stopped volumes: - "./data:/app/data" environment: - GOTIFY_DEFAULTUSER_PASS=${GOTIFY_DEFAULTUSER_PASS} networks: - proxy labels: - "traefik.enable=true" - "traefik.http.routers.gotify.rule=Host(`${TRAEFIK_GOTIFY}`)" - "traefik.http.routers.gotify.entrypoints=https" - "traefik.http.routers.gotify.tls=true" # Watchtower Update - "com.centurylinklabs.watchtower.enable=true"
-
.env
1 2
TREAFIK_GOTIFY=gotify.example.com GOTIFY_DEFAULTUSER_PASS=<パスワード>
ドメインは好きなものに置き換え、パスワードは適当に設定。1 DNS レコードの追加を忘れずに。
起動
|
|
パスワードの設定
Gotify にブラウザからアクセスし、ユーザー名: admin
パスワード: admin
でログインしたあと、メニューの [admin] をクリックするとパスワードを変更できるので、忘れずに設定すること。
Watchtower の導入
ファイル構成
|
|
ファイルの作成
-
docker-compose.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
version: "3" services: watchtower: image: containrrr/watchtower container_name: watchtower restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - WATCHTOWER_CLEANUP=true - WATCHTOWER_LABEL_ENABLE=true #- WATCHTOWER_MONITOR_ONLY=true #- WATCHTOWER_POLL_INTERVAL=30 - WATCHTOWER_SCHEDULE=0 0 4 * * MON - WATCHTOWER_NOTIFICATIONS=gotify - WATCHTOWER_NOTIFICATION_GOTIFY_URL=${GOTIFY_URL} - WATCHTOWER_NOTIFICATION_GOTIFY_TOKEN=${GOTIFY_TOKEN} labels: - "com.centurylinklabs.watchtower.enable=true"
-
.env
1 2
GOTIFY_URL=https://gotify.example.com/ GOTIFY_TOKEN=xxxxxxxxxxxxxxx
GOTIFY_URL
は先程設定した Gotify のリンクを設定する。
GOTIFY_TOKEN
は下記の方法で取得できる。
- ブラウザから Gotify にログインする
- メニューの [APPS] > [CREATE APPLICATION] からアプリの作成画面へ行き、適当なアプリ名を設定して表示されたトークンをコピーする
起動
|
|
作業は以上。
まとめ
Docker Compose 自体は噂通り簡単だった。
Traefik の証明書周りは参考資料が少なく大変だったが、公式ドキュメントや断片的な情報を集めて動くように直すのはやはり面白い。
次は色々サービス動かす編。
-
これ動いてなくないか? ↩︎