quartz-research-note/content/BlueskyのPDSをCloudflare Tunnel環境でセルフホストする.md

115 lines
9.8 KiB
Markdown
Raw Normal View History

---
date: "2024-02-08T15:53:17+0900"
---
#self-hosted #bsky
立ちました。
[[Bluesky]]
[@tomoya.matsuuratomoya.com on Bluesky](https://bsky.app/profile/tomoya.matsuuratomoya.com)
公式リポジトリ
- [GitHub - bluesky-social/pds: Bluesky PDS (Personal Data Server) container image, compose file, and documentation](https://github.com/bluesky-social/pds)
- 公式のリポジトリのコードはインストールスクリプトと、管理ツール`pdsadmin`コマンドのシェルスクリプトがあるだけで、実際のDockerイメージになるパッケージとかはatprotoのリポジトリ内にある
- [atproto/packages/pds at main · bluesky-social/atproto · GitHub](https://github.com/bluesky-social/atproto/tree/main/packages/pds)
日本語のリソース
- [一番詳しい ATProtocol PDS のセットアップガイド](https://zenn.dev/neody/articles/2efd51216be32c?cache)
- [Self-hosting PDSを建てる - Bluesky](https://scrapbox.io/Bluesky/Self-hosting_PDS%E3%82%92%E5%BB%BA%E3%81%A6%E3%82%8B)
- [さくらの VPS で Bluesky PDS Personal Data Server をセルフホストしてみる - WWW WATCH](https://hyper-text.org/archives/2024/02/bluesky_pds_self_hosting/)
- [DockerなしでBlueskyのPDSを建てる方法 | 点と接線。](https://riq0h.jp/2024/02/25/085804/)
基本的には公式のリソースに従うのが一番。インストールスクリプトを実行すると`/pds`ディレクトリ以下に必要なリソースをコピーして、Dockerのインストールも含めて面倒を見てくれるので、すでにDockerで色々立ち上げてる人には逆にめんどくさいかもしれない。DNSの設定とかをDockerホスト側の設定含めチェックする必要があるからこういうやり方にしている…っぽい。
私はせっかく[[Proxmox]]環境なので、諦めて一個LXCコンテナを増やすことにした。
## Cloudflare環境でのハンドル解決問題
BlueskyのATプロトコルはDNSレベルでのハンドル解決を行う。そのため、例えばサーバーを`bsky.matsuuratomoya.com`でホストすると、通常はアカウントはサブドメインの`tomoya.bsky.matsuuratomoya.com`で解決されなければならない。
ここで、私の環境では問題が二つ。
- `bsky.matsuuratomoya.com`と`${handle}.bsky.matsuuratomoya.com`はどちらもpdsのサーバーのIPアドレスにAレコードで解決されなければならない。
- また実際のトラフィックはポート80、443をサーバーまで到達できるようにしなければならない。
立ち上げたサーバーが固定グローバルIPを持つ場合特に問題ない。私のサーバーはIPoE環境なので、IPv4で任意のポートを空けることができない。そのためWebサービスの公開には[[Cloudflare Tunnel]]を使っている。
この場合、必然的にネームサーバーもCloudflareのものを使うことになる。Cloudflareは自動でHTTPの接続をSSL化してくれるので、Let's Encryptとかの面倒な設定が要らないため便利。だが無料プランでは残念ながら二階層以上のサブドメイン、つまり`${handle}.bsky.matsuuratomoya.com`にはSSL証明書を発行してくれない。
解決策は次のどれかである
1. Cloudflareにお金を払ってSSL証明書を発行してもらう
2. サブサブドメイン部分だけどうにか別の方法で証明書を用意する
3. **自分一人のハンドル解決だけどうにかする設定にする**(今回はこれ)
## シングルユーザーインスタンス限定の解法
`/pds/pds.env`で`PDS_SERVICE_HANDLE_DOMAINS=.matsuuratomoya.com`のように指定すると、PDSサーバー自体のアドレスを`https://pds.matsuuratomoya.com`にしたまま、ハンドルのIDは`${handle}.matsuuratomoya.com`で設定できる。
もちろん、実際にはこの状態でアカウントをいくつも作っていっても、ハンドルIDが自分の立ち上げてる他のサーバーのアドレスとかち合ったりするので普通は運用できない。
しかし、使うユーザーが一人だけの場合は、`_atproto.${handle}.matsuuratomoya.com`にTXTレコードでアカウントのDID永続性のあるアカウントIDを指定することでハンドルを解決すれば問題なく動かすことができる。
というわけで、まずは公式の`install.sh`で`pds.matsuuratomoya.com`上に一通りサーバーを立ち上げて、`/pds/pds.env`に`PDS_SERVICE_HANDLE_DOMAINS=.matsuuratomoya.com`を追記する。
ついでに、管理メールの送信用のSMTPの設定も済ましておく。
```
PDS_EMAIL_SMTP_URL=smtps://${_SMTP_USERNAME}:${_SMTP_PASSWORD}@${_SMTP_HOST}
PDS_EMAIL_FROM_ADDRESS=hogehoge@matsuuratomoya.com
```
(`PDS_EMAIL_FROM_ADDRESS`に関してはなぜかドキュメントに載っていなかった気がする)
その後`pdsadmin create-invite-code`でアカウント招待コードを作っておく。(`pdsadmin account create`だと先にハンドル解決ができないため招待コードを経由する)
### Cloudflare Tunnelを立ち上げる
Cloudflare Tunnelを立ち上げる。私は別の用途で色々使っているトンネルがあるのでここでは省略。
一度も使ったことがないなら、おすすめは`/pds`以下に`compose.override.yml`というファイルを作ってコンテナを追加するのが多分楽。
```
services:
tunnel:
container_name: cloudflared-tunnel
image: cloudflare/cloudflared:latest
volumes:
- ./cloudflared:/~/.cloudflared
restart: unless-stopped
command: tunnel run
privileged: true
environment:
- TUNNEL_TOKEN=<設定画面で出てきたトークン>
```
トンネルが開通したら、サーバーのローカルIP同じdocker composeで立ち上げてるなら`localhost`でいいに転送する。特にドキュメントに書かれてないが内部的には3000番でサーバーが立ち上がっているところに、[[Caddy]]でリバースプロキシをかけている。なので、トンネルではpds.matsuuratomoa.comに来るHTTPをそのまま3000番に転送してあげれば良い。
つまりdocker composeで立ち上がっているcaddyのサーバーは無用の長物になっているため、気になる人はオリジナルの`compose.yml`でコメントアウトしてもいいと思う。私はどうせアップデートかけた時にcompose.ymlが巻き戻る気がしててめんどくさいのでやってない
### PDSにログインする
https://bsky.app にアクセスして、アカウントを作成する。この時pdsがきちんと立ち上がっていれば、サーバーのアドレスにpds.matsuuratomoya.comを指定して次に進めるはず。
ここで先ほど作成した招待コードでアカウント作成を進める。アカウント名はなんでもいいが、`me`や`at`、`bsky`などシングルユーザーインスタンスなら使っても良さそうな短いハンドル名はコード上で予約IDとして多分スパム防止弾かれてしまう。これは後々設定ファイルで弄れるようにしてほしい…。
しょうがないので私は冗長だが`tomoya.matsuuratomoya.com`というハンドルを設定した。
ここで重要なのは、**このインスタンスでログインしている間、インスタンス上のアカウントのハンドル解決はあくまで内部的に**行われるということだ。
どういうことかというと、アカウント作成後、設定画面からハンドル変更で独自ドメインを指定することができる。
ここで例えばDNSを使用して`matsuuratomoya.com`というルートドメインをアカウントに設定することも、`_atproto`にTXTレコードをきちんと設定すれば、できる。ログアウトした状態なら正常にこのアカウントのプロフィールも表示できる。
ただし、`matsuuratomoya.com`を含むハンドルは`pds.matsuuratomoya.com`でログインしてる限り、あくまで内部でのハンドル解決が優先されDNSへの問い合わせはされない、ということらしい。ここがドキュメントでは明言されておらず自分のプロフィールが表示されないのに丸一日悩まされた。
### 他サーバーとの連携
肝心のFederationだが、残念ながら現在は一通り設定を済ませた後公式のDiscord([AT Protocol PDS Admins Discord](https://discord.gg/UWS6FFdhMe))でPDSサーバーのアドレスを添えて連携リクエストをbsky公式に出す必要があるそうしないとbluesky.socialのアカウントからは見えないようになっている
作れるアカウントも現在は10アカウントまで、投稿数にも一人で使う分には問題ない程度の制限がある。今後どのくらい盛り上がるんでしょうね。
## 要点まとめ
- 自分のpdsはcloudflare tunnelでpds.matsuuratomoya.comをポート3000に転送
- `/pds/pds.env`で`PDS_SERVICE_HANDLE_DOMAINS=.matsuuratomoya.com`のようにルートドメインにする必要ありCloudflareではサブサブドメインに証明書が出ないので
- その上で、自分のpdsでログインしてる時の、自分のドメインに属するアカウントのハンドル解決は`_atproto`レコードや`.well-known/atproto-did`を介さず行われるので何がしかのハンドルを設定する必要がある(私の場合は`@tomoya.matsuuratomoya.com`に設定でき、`@matsuuratomoya.com`にはできない)
- しかし以前としてログアウト状態や他のインスタンスからはDNS解決できる必要があるので、`_atproto.tomoya.matsuuratomoya.com`にTXTレコードでdidを指定する必要がある