リレーの運用
nostrfy リレーの運用:起動と停止、ログと統計、設定のホットリロード、複数インスタンス、大規模チューニング。
起動と停止
リレーをバックグラウンドのデーモンとして起動します:
nostrfy --config nostrfy.toml start=> nostrfy started (pid 12345)
またはターミナルでフォアグラウンド実行:
nostrfy --config nostrfy.toml start --foreground停止:
nostrfy --config nostrfy.toml stop起動を確認:
curl http://127.0.0.1:8080/health=> {"status":"ok"}
ログと統計
デーモンは次のファイルに書き込みます: daemon.log_file。ファイルが max_log_size_bytes を超えると自動的にローテーションします(nostrfy.log.1、.2……最大 max_log_files 世代):
tail -f nostrfy.logログレベルは RUST_LOG 環境変数で制御します(例: RUST_LOG=debug)。
統計
CLI からライブ統計を取得:
nostrfy statsまたは HTTP 経由:
curl http://127.0.0.1:8080/relay/stats接続数、承認/拒否されたイベント、DB サイズなどが表示されます。
Prometheus メトリクス
curl http://127.0.0.1:8080/metricsホットリロード(SIGHUP)
設定ファイルを編集したら、再起動せずにリロードできます:
kill -HUP $(cat nostrfy.pid)| リロード時に有効 | 再起動が必要 |
|---|---|
| リレー ID、public_url | private_key |
| 大部分の [limits]、reject_ephemeral、enabled_git、enabled_nip78_auth | api_host、metrics_enabled、LiveKit 設定 |
| — | enabled_nips / disabled_nips、server.host / port / ws_paths |
| — | database.*(search_index を含む)、blossom.* |
再起動が必要な設定が変更されると、ログが警告します。
複数インスタンスの実行
nostrfy は 1 台のサーバーで複数の独立したリレー(異なるポート)を実行できます。各インスタンスには独自の server.port、[daemon] の pid_file/log_file/stats_file (共有すると 2 番目のインスタンスが already running で拒否されます)、 database.path、および(使用する場合)独自の api_host / blossom.host:
[server]
port = 8080
[database]
path = "/var/lib/nostrfy-a"
[daemon]
pid_file = "/var/run/nostrfy-a.pid"
log_file = "/var/log/nostrfy-a.log"
stats_file = "/var/lib/nostrfy-a/stats.json"
[server]
port = 8081
[database]
path = "/var/lib/nostrfy-b"
[daemon]
pid_file = "/var/run/nostrfy-b.pid"
log_file = "/var/log/nostrfy-b.log"
stats_file = "/var/lib/nostrfy-b/stats.json"各インスタンスは独自の設定で管理します:nostrfy --config /etc/nostrfy/a.toml start など。
大規模デプロイ
このリレーは単一ホストで数十万接続まで拡張できるよう設計されています — ライブ配信はイベントに一致し得る購読者だけを起こし、接続あたりのメモリは小さく保たれます。数百万規模にはホストレベルのチューニングが必要です:
| 設定 | 値 | 理由 |
|---|---|---|
ulimit -n / systemd LimitNOFILE | 目標接続数の 2 倍以上(+1000) | 接続ごとに fd を 1 つ消費します |
net.core.somaxconn | ≥ 1024 | 接続バースト時の保留 accept キュー |
net.ipv4.tcp_fin_timeout | 低くする(例:10) | TIME_WAIT ソケットをより早く回収 |
vm.overcommit_memory | 1 または 2 | LMDB マップは大きなスパース仮想予約です |
FreeBSD では、対応するパラメータは kern.maxfiles / kern.maxfilesperproc と ulimit -n で、kern.ipc.somaxconn が net.core.somaxconn に対応します。1 接続あたりのカーネルメモリは約 80 KiB、ユーザー空間は約 10 KiB なので、100 万接続ではデータベースとは別に約 90 GiB のカーネル + ユーザーメモリが必要です。
スループット(毎秒イベント数)
イベントの書き込みは 2 つのコストに制約されます:Schnorr 署名検証(1 イベントあたり約 30〜50 µs)と、LMDB ライターが各コミットバッチ後に実行する同期ディスクフラッシュです。どちらも nostrfy.toml で調整できます:
| 設定 | 理由 |
|---|---|
database.disabled_fsync = true | OS ページキャッシュへコミット(マイクロ秒);電源断で失われるのは最後のフラッシュ以降の書き込みのみ — ここから始めましょう |
| CPU コア ≥ 8 vCPU | バッチ EVENT パスがコアをまたいで並列に署名検証 |
database.search_index = false | 書き込み重視のインスタンス向けに、イベントごとの NIP-50 語インデックス書き込みを省きます |
並列署名検証は、保留中のバッチ内のすべての署名を一度にワーカースレッドプールで検証します(上限 8。16 イベント未満のバッチはインラインで検証)。各イベントの軽量チェックは先に実行されるため、拒否理由の文言は逐次処理と同一です — Schnorr の処理だけが各コアに分散されます。シングルスレッドビルドは逐次のままです。
固定の不正対策リミット
リレーが濫用下でも応答し続けるよう、いくつかのハードリミットは固定されています(設定不可):
- 1 つのフィルターが持つのは最大 512 個
ids、authorsまたはkindsエントリ;#...タグ値はフィルターごとに別の 512 値の予算。より大きなフィルターは拒否されます(CLOSED invalid: ...)。 max_connections_per_sec_per_ipは最大 10,000 個のソース IP を追跡します。満杯になると、未見の IP は拒否されます(フェイルクローズ)。idsフィルター内のイベント id はプレフィックスでも構いませんが、完全な 32 バイト id と偶数長のプレフィックスのみ一致します(奇数長/空のエントリは履歴とライブ配信の両方で無視されます)。- 過長なインデックスキー(タグ値、内容の単語、LMDB のキーサイズ制限を超える
dタグ)は索引時にスキップされます;イベント自体は保存されます。