---
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を指定する必要がある
