Firefishを建ててみた

Firefishを建ててみたときの詰まりどころとかをまとめた記事です。 基本的には公式ドキュメントに準拠する形でやってますが一部環境の問題などでバージョンを落としていたりしますので、予めご了承ください。

firefish.dev

環境

Google CloudのCompute Engineを使っています。 OSはUbuntu 22.04 、スペックはe2-medium(メモリ4GB、 vCPU2)で動かしています。

Firefishを建てるまでにやったこと

ドメインの準備

ここはすでに利用しているドメインがあったのでそのサブドメインを使う形にしました。

また僕の場合は先にGoogle CloudのCompute Engineを用意していたのでこのタイミングでサブドメインにA レコードでIPアドレスを渡して反映しておきました。

ユーティリティの導入

まずは以下のコマンドを実行してユーティリティを入れておきます。

sudo apt update
sudo apt install build-essential python3 curl wget git lsb-release

Node.js とpnpmの導入

次に、Node.js とpnpmを入れます。

まずは以下のコマンドでNode.js をインストールします。

NODE_MAJOR=20
curl -fsSL "https://deb.nodesource.com/setup_${NODE_MAJOR}.x" | sudo -E bash -
sudo apt install nodejs

念のためインストールされたかバージョンを表示して確認しておきます。

node --version
# => 20.6などバージョンが表示される

次にpnpmを使えるようにします。

sudo corepack enable
corepack prepare pnpm@latest --activate

こちらも念のためにインストールされたかバージョンを表示して確認します。

pnpm --version
# => 9.6.0などバージョンが表示される

PostgreSQLとPGroongaの導入

PostgreSQLをインストールしていきます。

sudo sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt update
sudo apt install postgresql-14

sudo systemctl enable --now postgresql

公式ドキュメントではPostgreSQL v16 をインストールしているんですが、今回用意した環境ではPGroongaが上手くインストールできなかったためバージョンを下げています。

ちなみに実際には以下のようなログが出ており、おそらく依存ライブラリのバージョンが古かったんだと思います。

postgresql-16-pgdg-pgroonga : Depends: libgroonga0 (>= 14.0.5)

ただこの辺りメモをしっかりとれていないので、実行手順が微妙に間違っていた可能性もあるので、ちょっとわからないですね。

PostgreSQLもインストールされているかバージョンを表示して確認します。

psql --version
# => 14などバージョンが表示される

次にPGroongaですが、インストールにあたっては以下のドキュメントを参考にしました。

pgroonga.github.io

実際のインストールにあたって必要なコマンドは以下の通りです。

sudo apt install -y software-properties-common
sudo add-apt-repository -y universe
sudo add-apt-repository -y ppa:groonga/ppa
sudo apt update
sudo apt install -y -V postgresql-14-pgroonga

Firefish公式ドキュメントにある手順とは別の方法でPGroongaをインストールしたのは、以下のコマンドで投げたリクエストが404になっており、パッケージが取得できなかったためです。

wget "https://packages.groonga.org/debian/groonga-apt-source-latest-$(lsb_release --codename --short).deb"

ちなみに、こちらは以下のようにdebianの部分をubuntuに変更するとパッケージが取得できていたのでリンクミスかもしれないです。

リンクミスではなく、READMEによるとDebian 12を対象にしているのでこれでOKのようです。

firefish.dev

なのでUbuntuでFirefishを建てる場合は以下のようにリンクを修正すればOKです。

wget "https://packages.groonga.org/ubuntu/groonga-apt-source-latest-$(lsb_release --codename --short).deb"

Redisの導入

以下のコマンドでRedisをインストールします。

curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt update
sudo apt install redis

sudo systemctl enable --now redis-server

Redisがインストールされているかバージョンを表示して確認します。

redis-cli --version
# => 7.4.0などが表示されればOK

FFmpeg

以下のコマンドでインストールします。

sudo apt install ffmpeg

データベースの作成

Firefishで利用するデータベースを作成します。

ますは以下のコマンドでユーザーとパスワードを指定します。

sudo -u postgres createuser --no-createdb --no-createrole --no-superuser --encrypted --pwprompt firefish

実行後、パスワードを設定するように促されます。 ここで入力したパスワードはあとでFirefishの設定変更時に使用するのでメモしておきましょう。

もしパスワードをメモしておくのを忘れた場合は以下のコマンドでパスワードをリセットしておきましょう。

sudo -u postgres psql -c "ALTER USER firefish PASSWORD 'password';"

次に、データベースを作成します。

sudo -u postgres createdb --encoding='UTF8' --owner=firefish firefish_db

最後に、PGroongaの拡張機能を有効化します。

sudo -u postgres psql --command='CREATE EXTENSION pgroonga;' --dbname=firefish_db

Firefishのビルド環境準備

まずはFirefishで利用するユーザーを作成します。

sudo useradd --create-home --user-group --shell /bin/bash firefish

その後、作製したユーザーでログインします。

sudo su --login firefish

次にRustのツールチェインをインストールします。

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
. "${HOME}/.cargo/env"

実行後、以下のコマンドでcargoがインストールされていることを確認します。

cargo --version

次に、Firefishのソースコードをクローンします。

git clone --branch=main https://firefish.dev/firefish/firefish.git

クローン完了後、firefishディレクトリへ移動し、設定ファイルを編集します。 僕はVimを使っているためvimコマンドに変更していますが、慣れているエディタを使うと良いでしょう。

cd firefish
cp .config/example.yml .config/default.yml
vim .config/default.yml

色々設定項目が表示されますが変更箇所はurlとdb.passの二か所です。

url: https://<用意していたサブドメイン>/
port: 3000

db:
  host: localhost
  port: 5432
  db: firefish_db
  user: firefish
  pass: <データベース作成時に設定したパスワード>

用意していたサブドメインとデータベース作成時に設定したパスワードに変更します。

Firefishをビルド&データベースのマイグレーション

以下のコマンドでFirefishのビルドを行います。

pnpm install --frozen-lockfile
NODE_ENV=production NODE_OPTIONS='--max-old-space-size=3072' pnpm run build

次に、マイグレーションを実行します。

pnpm run migrate

マイグレーションが完了したらfirefishユーザーからログアウトします。

exit

ファイアウォールの設定

ufwを使ってファイアウォールを設定します。

sudo apt install ufw
sudo ufw default deny
sudo ufw allow 80
sudo ufw allow 443
sudo ufw --force enable

SSHに関してはここでは詳細は書きませんがポートを変更するなどしてあります。

あとは以下のコマンドで443と80が許可されているのを確認します。

sudo ufw status

リバースプロキシの設定

Firefish公式ドキュメントに則ってCaddyを使います。

sudo apt install debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

最後にCaddyがインストールされているかバージョンを表示して確認します。

caddy version

Caddyがインストールされていることを確認した後は設定ファイルを編集します。

その前に元々の設定ファイルの名前を変更してバックアップとして使えるようにしておきます。

sudo mv /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak

好みのエディタで設定ファイルを開き、編集していきます。

sudo vim /etc/caddy/Caddyfile

設定ファイル二は以下の内容を貼り付けます。

<用意していたサブドメイン> {
    reverse_proxy http://127.0.0.1:3000

    log {
        output file /var/log/caddy/firefish.log
    }
}

その後、Caddyを再起動します。

sudo systemctl restart caddy

Firefishサーバーを公開

まずはserviceを追加します。 以下のようにエディタでfirefish.serviceを開きます。

sudo vim /etc/systemd/system/firefish.service

あとは以下の内容を張り付けます。

[Unit]
Description=Firefish daemon
Requires=redis.service caddy.service postgresql.service
After=redis.service caddy.service postgresql.service network-online.target

[Service]
Type=simple
User=firefish
Group=firefish
UMask=0027
ExecStart=/usr/bin/pnpm run start
WorkingDirectory=/home/firefish/firefish
Environment="NODE_ENV=production"
Environment="npm_config_cache=/tmp"
Environment="NODE_OPTIONS=--max-old-space-size=3072"
# uncomment the following line if you use jemalloc (note that the path varies on different environments)
# Environment="LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2"
StandardOutput=journal
StandardError=journal
SyslogIdentifier=firefish
TimeoutSec=60
Restart=always

CapabilityBoundingSet=
DevicePolicy=closed
NoNewPrivileges=true
LockPersonality=true
PrivateDevices=true
PrivateIPC=true
PrivateMounts=true
PrivateUsers=true
ProtectClock=true
ProtectControlGroups=true
ProtectHostname=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectKernelLogs=true
ProtectProc=invisible
RestrictNamespaces=true
RestrictRealtime=true
RestrictSUIDSGID=true
SecureBits=noroot-locked
SystemCallArchitectures=native
SystemCallFilter=~@chown @clock @cpu-emulation @debug @ipc @keyring @memlock @module @mount @obsolete @privileged @raw-io @reboot @resources @setuid @swap
SystemCallFilter=capset pipe pipe2 setpriority

[Install]
WantedBy=multi-user.target

最後に以下のコマンドを実行してFirefishを起動します。

sudo systemctl enable --now firefish

参考

firefish.dev

pgroonga.github.io