PleromaというActivityPubを使ったマイクロブログの実装がある。Elixirで書かれていて、バックエンドとフロントエンドが分離されていて、Mastodonよりやや軽量な感じらしい。
分散SNSにおける標準的なプロトコルであるActivityPubを採用しているため、MastodonやMisskeyと相互にフォローしたり投稿を見たりできる。こういうことができるのがFediverseの面白いところだ。
MastodonはRubyでMisskeyはNodeだが、PleromaはElixirで書かれている。ElixirだからそのバックにはErlang/OTPがいる。この手のたくさんの通信を捌くようなアプリケーションにはうってつけだろう。また、RDBMSとしてPostgreSQLを採用している(9系以上に対応)。このあたりは他のActivityPub系のマイクロブログサーバと同じ感じだろう(MastodonやMisskeyと同様)。ただし、Mastodonと違ってRedisのインストールが不要なので、より手軽に自分のお一人様インスタンスを立てることができる。
公式にFreeBSDへのインストール方法が用意されているので、それに従ってPleromaインスタンスを立てたメモを残す。FreeBSDではなくLinuxを使っていても共通して使える知見も残しておいた。また、公式にDebianへのインストール手順(日本語)も提供されているので、これも参考にしてほしい。
ちなみにどうしてFreeBSDなのかというと、ZFSによる強力なストレージ管理機能(めちゃくちゃ良いLVMみたいな感じに受け取ってもらえたらと思う)が充実しており、ボリュームごとの暗号化や圧縮などをきめ細やかに設定でき、スナップショットしやすいため。加えて、Dockerほどではないが便利なコンテナ環境もあるためである。なにより、軽量ながらしっかりした安定性が好みだ。
僕のアカウントはここ。
構成
以下の構成で自宅サーバにPleromaを立ち上げる。
- ドメイン: plrm.capslock.dev(ネームサーバはCloudflare管理下)
- 母艦: 自宅サーバ FreeBSD 13.1
- 外界との通信とSSL終端: Cloudflare Tunnelにやってもらう
- 仮想化システム: BastilleBSD(Jailベース)
- コンテナ: Pleroma本体とPostgresを分離して構成する
- ストレージ: ZFS(Postgres用にデータセットを構成する)
- Postgres: 15
主な手順は、
- PostgresのためのZFS設定
- Postgres構成
- Pleroma構成
- Cloudflare Tunnelで外部開放
の流れである。
環境
uname -a
FreeBSD *** 13.1-RELEASE-p2 FreeBSD 13.1-RELEASE-p2 GENERIC amd64
BastilleBSD
BastilleBSD とは、FreeBSDの軽量コンテナ環境であるJailにいくつかの追加機能をほどこしたソフトウェア。Jail自体は単なるファイルシステム隔離機構だが、Bastilleを使うことでLinuxのDocker同様に様々なリソースの隔離や管理が行えるようになる。個人的にJailはちょっと管理機構が貧弱だと感じていたり、類似のソフトウェアであるiocageが開発停止(開発者が飽きた)されたりと困っていたので、試してみることにした。
LinuxでPleromaを構築しようとしている人はDockerを使えば良さそう。
また、BastilleBSDはZFSに対応していたり、スナップショットが可能だったりと、Misskeyインスタンスの運用にはそこそこ使えそう。
また、podman同様にデーモンレスなシステムなのもうれしい。
BastilleBSDのインストール
BastilleBSDはpkg
でインストール可能だった。
sudo pkg install bastille
起動時に自動的にBastilleが起動するように設定する。
sudo sysrc bastille_enable=YES
ZFSサポート
ZFSサポートはデフォルトでは無効なので有効化する。今回は事前に準備したtank
という名前のzpoolを使う。
https://bastille.readthedocs.io/en/latest/chapters/zfs-support.html#zfs-support
sudo sysrc -f /usr/local/etc/bastille/bastille.conf bastille_zfs_enable=YES sudo sysrc -f /usr/local/etc/bastille/bastille.conf bastille_zfs_zpool=tank
ベースイメージのダウンロード
BastilleBSDの中身はJailなので、ベースとなるFreeBSDのデータを用意しておく。bastille bootstrap
サブコマンドで、ベースイメージが用意される。これは最初の一回でよい。
sudo bastille bootstrap 13.1-RELEASE update
PostgreSQL
ZFSデータセットの構成
管理しやすくするためにPostgres用のZFSデータセットを構成する。これにより、のちのちスナップショットやバックアップをやりやすくする。
https://lackofimagination.org/2022/04/our-experience-with-postgresql-on-zfs/ を参考にインストールする。
sudo zfs create -p tank/pleroma/postgres sudo zfs set compression=zstd tank/pleroma/postgres sudo zfs set atime=off tank/pleroma/postgres sudo zfs set recordsize=32k tank/pleroma/postgres
Zstdによる圧縮を有効化し、パフォーマンスのためにatimeを切った。ブロックサイズを32KiBに設定した。
Zstd圧縮アルゴリズムについては、以前に書いた拙記事にて解説している。
コンテナ作成
postgresql用にコンテナを作成する。igb0
はネットワークインターフェイスで、環境によって書き換えてほしい。
sudo bastille create pleroma-postgres 13.1-RELEASE 192.168.32.157 igb0 sudo bastille console pleroma-postgres
(at container) pkg install postgresql15-server postgresql15-contrib
また、RUMインデックスのための拡張がcontribでは入らないので https://github.com/postgrespro/rum から入れる。
(at container) pkg install git gmake git clone https://github.com/postgrespro/rum cd rum gmake USE_PGXS=1 gmake USE_PGXS=1 install
いったん母艦に戻って、コンテナにさきほど作成したZFSのデータセットをマウントする。
sudo bastille mount pleroma-postgres /tank/pleroma/postgres /var/db/postgres nullfs rw 0 0 sudo bastille restart pleroma-postgres
さらに、Postgresはいくつかのシステムコールを使うので、Jailからいくつかのシステムコールを許可する。
sudo bastille config pleroma-postgres set sysvmsg=new sudo bastille config pleroma-postgres set sysvsem=new sudo bastille config pleroma-postgres set sysvshm=new sudo bastille sysrc pleroma-postgres postgresql_enable="YES" sudo bastille restart pleroma-postgres sudo bastille console pleroma-postgres
ふたたびコンテナに接続し、postgresを初期化する。
(at container) chown -R postgres /var/db/postgres service postgresql initdb
DB設定
これからDBを組み上げるので、いったんLANからの接続を受け付けるようにする。 必要に応じて書き換えてほしい。 https://www.postgresql.org/docs/15/auth-pg-hba-conf.html
sudo bastille console pleroma-postgres (at container) vi /var/db/postgres/data15/pg_hba.conf
host pleroma pleroma 192.168.32.0/24 trust host all postgres 192.168.32.0/24 trust
次にストレージまわりの設定。
By design it is impossible to write partial pages on ZFS
とのことなので、full page writesを無効化する。
(at container) service postgresql start psql -d postgres -U postgres ALTER SYSTEM set full_page_writes=off; CHECKPOINT;
これでPostgresコンテナの準備は完了。
Pleroma (backend)
ここからは実際にPleromaをインストールしていく。Pleromaはフロントエンドとバックエンドが分離した構成になっていて、好みのフロントエンドを選べるようになっているけれど、特に何もしなくてもデフォルトのフロントエンドがインストールされる。
ここからは基本的に https://docs-develop.pleroma.social/backend/installation/freebsd_en/ の指示に従うが、SSL終端としてNginxを使わずCloudflare Tunnelを使うのでNginxや証明書まわりの手順はスキップする。
まずはPleroma用のBastille jailを生成する。
sudo bastille create pleroma 13.1-RELEASE 192.168.32.158 igb0 sudo bastille console pleroma
必要なソフトウェアをインストールする。
(at container) pkg install elixir postgresql15-client postgresql15-contrib git-lite sudo gmake cmake ImageMagick7-nox11 ffmpeg p5-Image-ExifTool
ユーザ作成
pleroma用のユーザを作成する。
(at container) pw add user pleroma -m echo 'export LC_ALL="en_US.UTF-8"' >> /home/pleroma/.profile su -l pleroma
clone
リポジトリをcloneしてくる。
(as pleroma) cd $HOME git clone -b stable https://git.pleroma.social/pleroma/pleroma.git
インスタンス生成コマンドを実行するとインタラクティブに色々質問されるので、ドメイン名などを指定し、初回の最小限の設定を行う。RUMインデックスというPostgres拡張を使い、レンジクエリの効率性を上げる選択もした。
(as pleroma) cd /home/pleroma/pleroma mix deps.get MIX_ENV=prod mix pleroma.instance gen cp config/generated_config.exs config/prod.secret.exs
自動的に色々設定されたconfig/setup_db.psql
が生成されるので、これを使ってDBを初期化する。
(as root) cd /home/pleroma/pleroma psql -h 192.168.32.157 -U postgres -f config/setup_db.psql
/var/db/postgres/data15/pg_hba.conf
の設定を再確認し、セキュリティを強化したなら、初回マイグレーションを開始する。
su -l pleroma (as pleroma) cd /home/pleroma/pleroma MIX_ENV=prod mix ecto.migrate
Startup Script
起動用スクリプトを作成する。PleromaはFreeBSD用の起動スクリプトを用意してくれているので、コピペでよい。
その前に、いったんサーバを起動して全てのコンパイルを終わらせる(Elixir(Erlang)なので実行時にコンパイルする?)。
su -l pleroma cd $HOME/pleroma MIX_ENV=prod mix phx.server
(なんかRUMうまく動いてないよと言われたので指示に従って有効化する)
MIX_ENV=prod mix ecto.migrate --migrations-path priv/repo/optional_migrations/rum_indexing/
すると無事起動したので、しばらく落ち着かせてからサーバを停止させ、起動スクリプトをコピーしてくる。
(as root) cp /home/pleroma/pleroma/installation/freebsd/rc.d/pleroma /usr/local/etc/rc.d/pleroma chmod +x /usr/local/etc/rc.d/pleroma sysrc pleroma_enable=YES service pleroma start
最後に自分のユーザを作成する。
(as root) sudo -Hu pleroma MIX_ENV=prod mix pleroma.user new windymelt windymelt@3qe.us --admin
すると画面にパスワードリセットリンクが表示されるので、これをメモしておく。 まだトンネルの設定をしていないので、アクセスはできない。
user windymelt created Admin status of windymelt: true Generated password reset token for windymelt URL: https://plrm.capslock.dev/api/v1/pleroma/password_reset/TOKENTOKENTOKEN...
cloudflared
さて、サーバを立てるにあたって誰もが嫌がるのがSSL終端まわりのゴタゴタだが、文明の利器を使うことにする。
CloudflareはCloudflare Tunnelというトンネリングツールを用意しており、ngrokのような感じでLAN内のサーバの特定のポートをインターネットに公開することができる。今回はplrm.capslock.dev
へのアクセスをPleromaサーバに転送してもらう。
ちなみにこれを行う際は、ドメインのネームサーバをCloudflareの管理下に置いており、Cloudflare上にウェブサイトの設定を済ませている必要がある。こうすることで自分の好きなホスト名にPleromaを繋ぐことができる。
今回は簡単のためにPleromaコンテナの中でcloudflaredを動かして、127.0.0.1:4000
をplrm.capslock.dev
に飛ばしてもらう。
(in container) pkg install cloudflared cloudflared update cloudflared tunnel login
あとはだいたい公式ドキュメントの通りにする。
トンネル設定
pleroma-backend
という名前でトンネリングプロファイルを作成する。
cloudflared tunnel create pleroma-backend vi ~/.cloudflared/config.yaml
tunnel: GUIDがここに入る credentials-file: /root/.cloudflared/GUIDがここに入る.json ingress: - hostname: plrm.capslock.dev service: http://127.0.0.1:4000 - service: http_status:404
上掲のようにconfig.yaml
を設定することで、plrm.capslock.dev
は127.0.0.1:4000
にフォワードされる。
加えて、plrm
というホストをDNSに登録するべく、DNS設定用コマンドを呼ぶ。
cloudflared tunnel route dns pleroma-backend plrm.capslock.dev
これで動作確認をする。
cloudflared tunnel run pleroma-backend
トンネルが開通することを確認したら、リセットリンクからパスワードを設定する。
加えて、このインスタンスはお一人様であって新規登録はさせないので、いったん、 https://ホスト/pleroma/admin/#/settings/instance
に遷移し、Registrations openをオフにし、submitする。
Startup Script
コンテナが起動するときに自動的にトンネルが起動してほしいので、rc.conf
に設定を追記してトンネルをバックグラウンドで起動する。
sysrc cloudflared_enable=YES sysrc cloudflared_conf=/root/.cloudflared/config.yaml sysrc cloudflared_mode="tunnel run" service cloudflared start
トンネルが開通していることを確認する。
cloudflared tunnel info pleroma-backend
これでplrm.capslock.devの立ち上げが完了した。
感想
Elixir特有の箇所はあまり慣れていなくて独特のコマンドだな〜などと思ったりもしたものの、基本的にポチポチするだけでインスタンスを作ることができた。
そしてCloudflare Tunnelはかなり便利。このまま1ヶ月運用してみて、費用がどうなるか確認してみたい。便利なngrokとして普通に運用できそうな雰囲気を感じた。
いずれにせよ、引っかかったり困ったりする箇所はあまりなかった。
Pleromaはデフォルトで新規登録を開放する設定になっているので、そこはちょっと注意が必要だなと思った。
また、実際のメモリ使用量は、Elixirのランタイム(Erlang BEAM)が512MiBを切る程度、加えてPostgresが数百MiB、さらにCloudflaredが64MiB程度を消費しているくらいで、ほどほどに軽量な印象がある。
SNSとして使ってみた感想としては、やはりサクサク動いて面白いし、欲しい機能はだいたいあるな、という感じ。最近絵文字を付ける機能も追加されたので、ややMisskeyに近い感じになっている。TwitterやMastodonみたいにintent用の画面を出す方法が分からないので、発見したらシェアボタンも作れるな〜、と思った。