SyoBoN's Home


FreeBSDでConcurrentを建てる

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/[email protected]
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 -::1bind 10.0.0.201

protected-mode yesprotected-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

実行後、反映には再起動が必要かもしれません(未検証)。

これで完了です。お疲れさまでした。

CC BY-SA

このサイト上の文章はCC BY-SAライセンスの下公開されています。

© SyoBoN Some rights reserved.