ConcurrentをFreeBSDで建てた話。
ConcurrentというSNSソフトウェアがあります。
ユーザーはまずサーバーを選んで登録しますが、選んだサーバーに関係なくすべてのサーバー上のフィードにアクセスできるという、ActivityPubとNostrの間の子のような機能を持つのが特徴です。Blueskyっぽいと言ってもよいかもしれません。
これをFreeBSDサーバー上に構築したので、その記録です。
ドキュメントによると構築にはDockerかKubernetesを使えとのことですが、FreeBSDにはそんなものないので自力で建てます。いや、厳密にはPodmanのような互換品や9年前に放棄されたFreeBSD移植がありますが…。
ともかく、せっかくFreeBSDなのですからここはFreeBSD Jailsを使いましょう。
Jailsはそのままでは若干管理が面倒なので、JailのラッパーであるBastilleBSDを使うことにします。
はじめに: Cloudflareを使用する場合
Cloudflareを使用する予定で、かつすでにキャッシュを設定している場合、Concurrentに使用するドメイン全体に対しキャッシュを無効化することを強く推奨します。
FreeBSDとBastilleBSDの設定
https://bastillebsd.org/getting-started に従って進めていきます。
まずはFreeBSDの更新から。
freebsd-update fetch install
shutdown -r now
FreeBSDは汎用のOSなので、デフォルト状態ではサーバーとして使用するにはややセキュリティに懸念点があります(c.f. https://vez.mrsk.me/freebsd-defaults.html)。最低限の対策を施します。
/etc/sysctl.conf
を開き、以下の設定を追加します。
security.bsd.see_other_uids=0
security.bsd.see_other_gids=0
security.bsd.see_jail_proc=0
security.bsd.unprivileged_read_msgbuf=0
security.bsd.unprivileged_proc_debug=0
kern.randompid=1
security.bsd.hardlink_check_gid=1
security.bsd.hardlink_check_uid=1
hw.kbd.keymap_restrict_change=4
kern.ipc.shm_use_phys=1
net.inet.tcp.blackhole=2
net.inet.udp.blackhole=1
net.inet.tcp.sack.enable=0
net.inet.tcp.drop_synfin=1
net.inet.tcp.icmp_may_rst=0
net.inet.icmp.drop_redirect=1
net.inet.ip.redirect=0
net.inet.ip.process_options=0
net.inet6.ip6.redirect=0
net.inet.ip.random_id=1
これ以上のセキュリティ強化に際してはLynisなどをご利用ください。
BastilleBSDをインストールし、有効化します。
pkg install bastille
service bastille enable
設定を変更します。設定ファイルに各オプションの説明があるので、参考に進めてください。
vi /usr/local/etc/bastille/bastille.conf
ネットワークインターフェースを準備します。
sysrc cloned_interfaces+=lo1
sysrc ifconfig_lo1_name="bastille0"
service netif cloneup
その後、ファイアウォールの設定を行います。
vi /etc/pf.conf
ext_if="vtnet0"
set block-policy return
scrub in on $ext_if all fragment reassemble
set skip on lo
table <jails> persist
nat on $ext_if from <jails> to any -> ($ext_if:0)
rdr-anchor "rdr/*"
block in all
pass out quick keep state
antispoof for $ext_if inet
pass in inet proto tcp from any to any port ssh flags S/SA keep state
pass in inet proto tcp from any to any port { 80 443 }
vtnet0
は実際の物理インターフェース名に変更してください。
ファイアウォールを起動します。SSHで接続している場合、一旦切断されるため再接続しましょう。
service pf enable
service pf start
最後にJail用のOSベースを準備します。
bastille bootstrap 14.0-RELEASE update
これでBastilleBSDを使用する準備ができました。
Jailの準備
まずはConcurrentの各モジュールを実行するJailを作成します。compose.ymlを参考に用意しましょう。
bastille create ccgateway 14.0-RELEASE 10.0.0.100/24
bastille create ccapi 14.0-RELEASE 10.0.0.101/24
bastille create ccwebui 14.0-RELEASE 10.0.0.102/24
bastille create ccurlsummary 14.0-RELEASE 10.0.0.103/24
bastille create ccapbridge 14.0-RELEASE 10.0.0.104/24
bastille create postgres 14.0-RELEASE 10.0.0.200/24
bastille create redis 14.0-RELEASE 10.0.0.201/24
bastille create memcached 14.0-RELEASE 10.0.0.202/24
PostgreSQLは実行にSystemV IPCを必要とするので、設定を変更します。変更後、Jailを再起動します。
bastille config postgres set allow.sysvipc 1
bastille restart postgres
続いて、各Jailにて必要なパッケージをインストールし、サービスを有効化します。
bastille pkg ccgateway install go121 go-wire git-tiny
bastille pkg ccapi install go121 go-wire git-tiny
bastille pkg ccwebui install nginx node npm git-tiny
bastille pkg ccurlsummary install node npm git-tiny
bastille pkg ccapbridge install go121 go-wire git-tiny
bastille pkg postgres install postgresql16-server
bastille pkg redis install redis
bastille pkg memcached install memcached
bastille service ccwebui nginx enable
bastille service ccwebui nginx start
bastille service postgres postgresql enable
bastille service postgres postgresql initdb
bastille service postgres postgresql start
bastille service redis redis enable
bastille service redis redis start
bastille service memcached memcached enable
bastille service memcached memcached start
Concurrentのビルド
Concurrentの各モジュールをビルドします。各リポジトリ・ディレクトリのDockerfileを参考にビルドします。
bastille console ccgateway
mkdir /root/bin
ln -s /usr/local/bin/go121 /root/bin/go
git clone -b v0.5.3 https://github.com/totegamma/concurrent.git
cd concurrent
go mod download && go mod verify
wire ./cmd/gateway
go build -ldflags "-s -w -X main.version=$(git describe) -X \"main.buildMachine=$(uname -srmo)\" -X \"main.buildTime=$(date)\" -X \"main.goVersion=$(go version)\"" -o /root/bin/ccgateway ./cmd/gateway
exit
bastille console ccapi
mkdir /root/bin
ln -s /usr/local/bin/go121 /root/bin/go
git clone -b v0.5.3 https://github.com/totegamma/concurrent.git
cd concurrent
go mod download && go mod verify
wire ./cmd/api
go build -ldflags "-s -w -X main.version=$(git describe) -X \"main.buildMachine=$(uname -srmo)\" -X \"main.buildTime=$(date)\" -X \"main.goVersion=$(go version)\"" -o /root/bin/ccapi ./cmd/api
go install github.com/totegamma/ccadmin@v0.3.0
ln -s /root/go/bin/ccadmin /root/bin/ccadmin
exit
bastille console ccwebui
git clone -b v0.5.3 https://github.com/totegamma/concurrent.git
cd concurrent/web
npm i -g pnpm
pnpm i && pnpm build
cp -r /root/concurrent/web/dist /usr/local/www/concurrent
exit
bastille console ccurlsummary
git clone https://github.com/totegamma/url-summary.git
cd url-summary
npm install
exit
bastille console ccapbridge
mkdir /root/bin
ln -s /usr/local/bin/go121 /root/bin/go
git clone https://github.com/totegamma/ccworld-ap-bridge.git
cd ccworld-ap-bridge
go mod download && go mod verify
wire ./cmd/activitypub
go build -ldflags "-s -w -X main.version=$(git describe) -X \"main.buildMachine=$(uname -srmo)\" -X \"main.buildTime=$(date)\" -X \"main.goVersion=$(go version)\"" -o /root/bin/ccactivitypub ./cmd/activitypub
exit
サービスの設定
続いてNginx、PostgreSQL、Redisの設定をします。
Nginx
設定ファイルを開きます。
bastille cmd ccwebui vi /usr/local/etc/nginx/nginx.conf
既存のserver {}
ブロックを全て削除した後、以下のブロックを追加します。
server {
listen 80;
location /web/ {
alias /usr/local/www/concurrent/;
index index.html index.htm;
try_files $uri $uri/ /index.html =404;
}
}
その後サービスを再起動します。
bastille service ccwebui nginx restart
PostgreSQL
データベースを作成します。
bastille cmd postgres psql -U postgres
CREATE DATABASE concurrent;
\q
Jail間でアクセスできるようにするため、pg_hba.conf
を編集します。
bastille cmd postgres vi /var/db/postgres/data16/pg_hba.conf
最下部に以下を追加します。
host all all 10.0.0.0/8 trust
その後サービスを再起動します。
bastille service postgres postgresql restart
Redis
Jail間でアクセスできるようにするため、redis.conf
を編集します。
bastille cmd redis vi /usr/local/etc/redis.conf
以下のように書き換えます。
bind 127.0.0.1 -::1
→bind 10.0.0.201
protected-mode yes
→protected-mode no
その後サービスを再起動します。
bastille service redis redis restart
Concurrentの設定
まずは設定のテンプレートをダウンロードします。
mkdir /usr/local/etc/concurrent
cd /usr/local/etc/concurrent
fetch https://raw.githubusercontent.com/totegamma/concurrent/v0.5.3/docs/config/config.yaml
fetch https://raw.githubusercontent.com/totegamma/concurrent/v0.5.3/docs/config/gateway.yaml
fetch https://raw.githubusercontent.com/totegamma/concurrent/v0.5.3/docs/config/activitypub.yaml
設定ファイルにJailからアクセスできるよう、マウント設定を追加します。
bastille mount ccgateway /usr/local/etc/concurrent /usr/local/etc/concurrent nullfs ro 0 0
bastille mount ccapi /usr/local/etc/concurrent /usr/local/etc/concurrent nullfs ro 0 0
bastille mount ccapbridge /usr/local/etc/concurrent /usr/local/etc/concurrent nullfs ro 0 0
その後設定ファイルを編集します。
各種サーバーのアドレスをJailのものに設定します。以下のようになるはずです:
config.yaml
# (略)
server:
dsn: "host=10.0.0.200 user=postgres password=postgres dbname=concurrent port=5432 sslmode=disable"
redisAddr: "10.0.0.201:6379"
memcachedAddr: "10.0.0.202:11211"
# (略)
gateway.yaml
services:
- name: concurrent
host: 10.0.0.101
port: 8000
path: /api/v1
injectCors: true
- name: webui
host: 10.0.0.102
port: 80
path: /web
preservePath: true
- name: url-summary
host: 10.0.0.103
port: 8080
path: /summary
- name: activitypub
host: 10.0.0.104
port: 8000
path: /ap
preservePath: true
injectCors: true
- name: webfinger
host: 10.0.0.104
port: 8000
path: /.well-known
preservePath: true
injectCors: true
残りの部分はお好きなように調整してください。ドキュメントなどが参考になります。
なお、この段階ではregistration
をopenにしておくことを推奨します。コマンドラインからでもユーザーの登録はできますが、コマンドラインはデータベース上にユーザーテーブルを作成してくれないようで、最初のユーザーのみはWebから登録する必要がありそうです。
動作の確認
とりあえずこの段階で動くかをチェックします。
以下のコマンドを順に実行します。エラーのようなものが出なければCtrl+Cし次に進んでください。
bastille cmd ccgateway env CONCURRENT_CONFIG=/usr/local/etc/concurrent/config.yaml GATEWAY_CONFIG=/usr/local/etc/concurrent/gateway.yaml ccgateway
bastille cmd ccapi env CONCURRENT_CONFIG=/usr/local/etc/concurrent/config.yaml ccapi
bastille cmd ccurlsummary node '/root/url-summary/main.mjs'
bastille cmd ccapbridge env CONCURRENT_CONFIG=/usr/local/etc/concurrent/config.yaml GATEWAY_CONFIG=/usr/local/etc/concurrent/activitypub.yaml ccactivitypub
リバースプロキシの設定
リバースプロキシを設定します。お好きなものを使用して問題ありませんが、ここでは設定が楽なCaddyを使用します。
pkg install caddy portacl-rc
sysrc portacl_users+=www
sysrc portacl_user_www_tcp="http https"
sysrc portacl_user_www_udp="https"
sysrc caddy_user=www caddy_group=www
service portacl enable
service portacl start
service caddy enable
service caddy start
設定を変更します。
vi /usr/local/etc/caddy/Caddyfile
最下部に以下を追加します。example.tld
は各自のドメインに置き換えてください。
example.tld {
reverse_proxy 10.0.0.100:8080
}
起動
これで起動する準備が完了しました。本来であればサービスファイルを作成するのが望ましいですが、面倒なので以下のシェルスクリプトを起動スクリプトとします。
#!/bin/sh
bastille cmd ccgateway env CONCURRENT_CONFIG=/usr/local/etc/concurrent/config.yaml GATEWAY_CONFIG=/usr/local/etc/concurrent/gateway.yaml ccgateway &
bastille cmd ccapi env CONCURRENT_CONFIG=/usr/local/etc/concurrent/config.yaml ccapi &
bastille cmd ccurlsummary node '/root/url-summary/main.mjs' &
bastille cmd ccapbridge env CONCURRENT_CONFIG=/usr/local/etc/concurrent/config.yaml GATEWAY_CONFIG=/usr/local/etc/concurrent/activitypub.yaml ccactivitypub &
実行権限を付与し、そのまま実行すればConcurrentが立ち上がります。DNSの設定等を済ませた後、https://concurrent.world から登録できるはずです。
管理者権限の付与
作成したアカウントに管理者権限を付与します。以下のコマンドを実行してください。<ccid>
の部分はユーザーIDに置き換えてください。
bastille cmd ccapi ccadmin -H 10.0.0.200 entity role <CCID> _admin
実行後、反映には再起動が必要かもしれません(未検証)。
これで完了です。お疲れさまでした。