FreeBSD
ZeroClaw は FreeBSD 上でネイティブに動作します(FreeBSD 15.0-RELEASE、amd64 でテスト済み)。Linux/macOS/Windows のパスと異なる点が 2 つあります。
- ビルド済みバイナリと
install.shのサポートはありません。 FreeBSD はブートストラップインストーラーの対象外であるため、システムの Rust ツールチェーンを使ってソースからビルドします。 zeroclaw serviceバックエンドはありません。zeroclaw service installコマンドは systemd、OpenRC、launchd、Windows タスクスケジューラには対応していますが、FreeBSD のrc.dには対応していません。小さなrc.dスクリプトはご自身でインストールします。このページでは、完全でテスト済みのスクリプトを提供します。
設定、プロバイダー、チャネル、デーモン、ゲートウェイなど、それ以外はすべて他のプラットフォームと同じです。
FreeBSD を使用する場合。 FreeBSD のデプロイは、ネットワークアプライアンス、組み込み、jail ベースのホスティングで一般的であり、運用者がベースシステムの安定性、ZFS + jail プリミティブを求める場合や、ポリシー/ライセンス上の理由で FreeBSD が必要な場合に利用されます。ビルド済みバイナリが存在せず、
rc.dのセットアップが手動であるため、このパスは FreeBSD の慣習に慣れた運用者に適しています。特定の FreeBSD 要件がなく、単にプラットフォームを評価しているだけであれば、Linux (systemd) や macOS (launchd) のほうがinstall.shとzeroclaw service installを通じてより迅速に導入できます。コピー&ペーストする代わりにファイルを取得してください。 以下に示すシェルスクリプトとサンプル設定はすべて
dist/freebsd/に同梱されています。それらをホストに直接コピーしてください。このチュートリアルでは、各部分が何をするのか、そしてなぜそうするのかを説明します。
システム依存関係
pkg からツールチェインとランタイムをインストールします:
sh
doas pkg install -y rust git
| パッケージ | なぜ |
|---|---|
rust | バイナリをビルドするための cargo と rustc を提供します。ZeroClaw のワークスペースの MSRV は Rust 1.96.0 です。FreeBSD の rust ポートはより新しい安定版を追跡しているため、pkg install rust で要件を満たせます。 |
git | リポジトリのクローン作成時、およびgitベースのツールを使用する場合に実行時に必要です。 |
sudoではなくdoas。 FreeBSD は基本の権限昇格ツールとしてdoasを同梱しています。sudoはオプションの port です。ここでの例ではdoasを使用します。wheelグループにパスワードなしの昇格を許可する最小限の/usr/local/etc/doas.confは次のとおりです:permit nopass keepenv :wheel
ソースからビルドする
sh
git clone https://github.com/zeroclaw-labs/zeroclaw.git
cd zeroclaw
cargo build --release
リリースバイナリは target/release/zeroclaw に生成されます。デフォルトの機能セットをクリーンビルドする場合、ハードウェアの性能が控えめだと時間がかかりますが、これは想定どおりです。ZeroClaw は大規模な Rust ワークスペースです。
ビルドを削減するには、不要な機能を無効化してください(Linux マシンで ./install.sh --list-features を実行するか、Cargo.toml を参照):
sh
cargo build --release --no-default-features --features agent-runtime
バイナリをインストールする
PATH の通った場所に配置してください。FreeBSD では /usr/local/bin が ports でインストールされたバイナリの慣例的な配置場所です:
sh
doas install -m 755 target/release/zeroclaw /usr/local/bin/zeroclaw
zeroclaw --version
ユーザーごとに管理したい場合は、~/.cargo/bin/zeroclaw でも同様に動作します。
初回起動時の設定
sh
zeroclaw quickstart
これにより ~/.zeroclaw/ がスターター設定とともに作成され、プロバイダーのセットアップが順を追って案内されます。設定のレイアウトと優先順位は他のすべてのプラットフォームと同一です。詳しくは Reference → Config を参照してください。
プロバイダー認証
プロバイダー認証はFreeBSD固有のものではありません。APIキーを使用するプロバイダーでは、ゲートウェイ、zerocode、zeroclaw config set、または環境変数を通じてキーを設定するだけで済みます。OAuthおよびサブスクリプション型のプロバイダー(例: OpenAI/Codex ChatGPTサブスクリプション、Anthropic Claude Pro/Team)は、ベンダー独自のダッシュボードまたはログインフローからトークンを取得し、APIキーと同じ方法で設定します。
認証情報モデルの全体像(API キー、OAuth/サブスクリプショントークン、環境変数によるオーバーライド、シークレットストア)については、Provider Configuration → Credentials および OAuth and subscription auth を参照してください。このページがすべてのプラットフォームにおける信頼できる情報源です。
サービスとして実行する (rc.d)
zeroclaw service install には FreeBSD バックエンドがないため、FreeBSD ネイティブの daemon(8) を使い、rc.d スクリプトでデーモンを監視します。これにより、service zeroclaw start|stop|restart|status、クラッシュ時の再起動、pidfile、ブート時の起動が利用できます。
以下のすべてのスクリプトについて、インストール可能な状態のコピーが
dist/freebsd/にあります(zeroclaw-run.sh、基本的なzeroclaw.rc、強化版のzeroclaw-hardened.rc)。2つのrc.dスクリプトには@@ZEROCLAW_USER@@プレースホルダーが含まれており、インストール時にsedで置き換えるため、コピー&ペーストする代わりにファイルを取得できます。dist/freebsd/README.mdを参照してください。以下の解説では、各部分が何を行うかを説明します。
1. ランチャースクリプト
daemon(8) は最小限の環境で子プロセスを起動するため、完全な PATH をエクスポートしてください(FreeBSD は git や python3 などを /usr/local/bin 配下に配置しますが、これはデフォルトのサービス PATH には 含まれていません)。rc.d スクリプトはこれを daemon -u <user> 経由で実行し、daemon(8) によれば exec の前にそのアカウントの passwd エントリから HOME、USER、SHELL を設定するため、${HOME} はすでにサービスアカウントのホームになっています(ホームが別の場所にあるアカウントや、rc.conf の実行ユーザーのオーバーライドも問題なく機能します)。/usr/local/libexec/zeroclaw-run.sh として保存してください:
sh
#!/bin/sh
# daemon -u <user> has already set HOME from the accountユーザーの passwd エントリ。
export PATH="/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:${HOME}/bin"
exec /usr/local/bin/zeroclaw daemon --config-dir "${HOME}/.zeroclaw"
sh
doas install -m 755 zeroclaw-run.sh /usr/local/libexec/zeroclaw-run.sh
2. rc.d スクリプト
/usr/local/etc/rc.d/zeroclaw として保存します:
sh
#!/bin/sh
#
# PROVIDE: zeroclaw
# REQUIRE: NETWORKING DAEMON
# キーワード: shutdown
. /etc/rc.subr
name=zeroclaw
rcvar=zeroclaw_enable
load_rc_config $name
: ${zeroclaw_enable:=NO}
# これに ${name}_user という名前を付けないでください — そうすると rc.subr が独自の su によるユーザー切り替えを実行してしまいます
# and collide with daemon -u (ユーザー環境の設定に失敗しました).
: ${zeroclaw_runas:="youruser"}
rundir=/var/run/zeroclaw
pidfile="${rundir}/zeroclaw.pid"
logfile=/var/log/${name}.log
launcher=/usr/local/libexec/zeroclaw-run.sh
command=/usr/sbin/daemon
command_args=-r -P ${pidfile} -o ${logfile} -u ${zeroclaw_runas} ${launcher}
start_precmd=zeroclaw_precmd
zeroclaw_precmd()
{
# rundir + logfile はroot所有のまま維持: rc.d(root)がここにデーモンの-P pidfileを
# 書き込み、後でそれを信頼するため、非特権サービスユーザーがそれを
# 偽装できないようにする必要があります。daemon -oは${zeroclaw_runas}に降格する前にlogfileを開きます。
install -d -o root -g wheel -m 755 ${rundir}
install -o root -g wheel -m 640 /dev/null ${logfile}
}
run_rc_command $1
sh
doas install -m 755 zeroclaw /usr/local/etc/rc.d/zeroclaw
フラグの機能:
-r: 子プロセスを監視し、終了した場合は再起動します(クラッシュリカバリ)。-P ${pidfile}:service zeroclaw stopがシグナルを送れるように、スーパーバイザーの pid を書き込みます。-o ${logfile}: 子プロセスの stdout/stderr をログファイルにリダイレクトします。-u ${zeroclaw_runas}: zeroclawをrootではなく非特権ユーザーとして実行します。
su -mではなくdaemon -uを使う理由。 よくあるパターンとしてdaemon ... su -m user -c launcherがあります。これは避けてください。su(1)はSIGTERMを子プロセスに転送しないため、service zeroclaw stopはdaemonスーパーバイザーを終了させますが、孤立したzeroclawプロセスが残り、次のstartで2つ目のコピーが積み重なってしまいます。daemon -u userを使うとdaemon(8)がzeroclawの直接の親プロセスになるため、停止シグナルを転送してクリーンにシャットダウンします。(他の理由でsuベースのスクリプトを使わざるを得ない場合は、その停止パスにpkill -f "zeroclaw daemon"によるスイープを追加してください。)
3. 有効化して起動
sh
doas sysrc zeroclaw_enable=YES
doas sysrc zeroclaw_runas=youruser # ~/.zeroclaw を所有するアカウント
doas service zeroclaw start
doas service zeroclaw status
service zeroclaw stop / restart は期待どおりに動作します。/etc/rc.conf に(sysrc によって書き込まれた)zeroclaw_enable=YES があるため、デーモンは起動時にも開始されます。
4. 無人およびリモート運用のための堅牢化
上記のスクリプトは、対話的な単一インスタンスのインストールには正しく動作します。しかし、サービスをリモート(ssh 経由)で操作したり、複数のコピーを実行したりした瞬間に、3 つの daemon(8) の挙動に驚かされることになります。これら 3 つはすべて本番環境のデプロイで問題を引き起こしましたが、その修正はわずかなものです。以下のすべての修正を取り込んだ完全なスクリプトは dist/freebsd/zeroclaw-hardened.rc として提供されています。基本の zeroclaw スクリプトの代わりにこちらをインストールしてください。
リモートでの service ... start がハングする。 daemon -r は起動時に渡された stdin/stdout/stderr をそのまま継承し、開いたまま保持します。ssh host 'service zeroclaw start' を実行すると、スーパーバイザがあなたの ssh セッションの stdout fd を永久に開いたままにするため、ssh は EOF を検出できず、デーモンは正常に起動しているのにコマンドがハングします。スーパーバイザ自身のディスクリプタをデタッチしましょう。-o ${logfile} はすでに_子プロセスの_出力をルーティングしているため、何も失われません。
sh
command_args=-r -P ${pidfile} -o ${logfile} -u ${zeroclaw_runas} ${launcher}
# ...独自の std{in,out,err} を /dev/null に送信してデーモンを呼び出す:
/usr/sbin/daemon ${command_args} </dev/null >/dev/null 2>&1
定番の command/command_args 形式を使う場合は、リダイレクトを制御できるように、起動処理をカスタムの start_cmd でラップしてください。この変更ひとつで、service zeroclaw start を ssh、CI、または構成管理のプッシュから安全に呼び出せるようになります。
start の繰り返しでオーファンとなったスーパーバイザーが積み重なる。 単純な start はスーパーバイザーがすでに実行中かどうかを確認しないため、2回目の start(またはクラッシュ後に古い pidfile が残った状態での start)は別の daemon を起動し、ゲートウェイポートをめぐって最初のものと競合します。すでに稼働中のスーパーバイザーが存在する場合は拒否するようにして、start を冪等にしましょう。スーパーバイザーは pidfile だけではなく、ランチャーのパスで照合してください(pidfile は古くなっている可能性があります)。これを行う際の FreeBSD 特有の落とし穴が2つあります。
daemon(8)は_スーパーバイザのタイトルを_daemon: /usr/local/libexec/zeroclaw-run.sh[<childpid>] (daemon)に_変更します_。そのためpgrep -f zeroclaw-run.shはスーパーバイザにマッチしますが、バイナリ名に対するpgrep -fはマッチしません。リテラルのdaemon:プレフィックスにバインドしてください。これはスーパーバイザにマッチし、子プロセスやランチャーの手動実行、rc シェル自体には決してマッチしません。daemon の[<childpid>]を開く末尾の[にもバインドしてください。そうすれば、名前が単にzeroclaw-run.shで_始まる_だけの兄弟ランチャーがマッチすることを防げます(これはプールを実行するようになると重要になります。下記の インスタンスのプールを実行する を参照してください)。- FreeBSD の
pgrep -fは、そのリタイトル文字列に対して先頭の^アンカーを尊重しません。pgrep -f '^daemon: ...'は何もマッチしません。^を削除し、特定性についてはdaemon:プレフィックスに頼り、.shのドットを[.]として(角括弧を[[]として)エスケープすることで、それらをリテラルにします。
sh
launcher_pat=daemon: /usr/local/libexec/zeroclaw-run[.]sh[[]
zeroclaw_running()
{
pgrep -f ${launcher_pat} >/dev/null 2>&1
}
daemon -P の pidfile からの read が誤検知を報告する。 daemon -P は pid を 末尾の改行なし で書き込むため、pid を正しく設定していても IFS= read -r pid < "${pidfile}" は 非ゼロ ステータス(改行前のEOF)を返す。これを read -r pid < "$pf" || return 1 のようにガードすると、実行中のすべてのインスタンスが停止しているように見え、冪等であるはずの start が嬉々として重複起動してしまう。成功パスを read の終了ステータスに結びつけてはいけない。代わりに値を検証すること:
sh
pid=""
IFS= read -r pid < "${pidfile}" # ここで `|| return 1` を実行しないこと
case "${pid}" in
''|*[!0-9]*) return 1 ;; # 空または非数値 → 実行中でないものとして扱う
esac
インスタンスのプールを実行する。 N 個のデーモン(例: ワーカープール)を実行するには、それぞれに独自の pidfile と logfile(worker.$i.pid、worker.$i.log)を与え、$i にわたって start/stop をループします。スーパーバイザーのリタイトルはすべてのインスタンスで同一であり、インスタンスごとの引数を含まないため、pidfile が唯一のインスタンスごとのハンドルとなります。stop/status は pidfile から駆動し、完全な停止スイープでは、生きている pidfile が指していない残存スーパーバイザー(手動で起動されたもの、または pidfile が古くなったもの)をすべて停止します。
jail内での実行
Jailは、ZeroClawに独自のパッケージ、サービスユーザー、オプションで独自のIPを備えた隔離されたrootを提供します。ホストが他のサービスを実行している場合や、エージェントを制約したい場合に便利です。サービスのセットアップはホストの場合と同一です。jailの_内部_で実行するだけです。 ここでは、ベースシステムのツールを使った従来型のthick jail(jailマネージャー不要)を順を追って説明します。
ワンステップオプション。
dist/freebsd/zeroclaw-jail-setup.shは以下のステップ1〜3を自動化します。jailを作成し、一致するベースを展開し、/etc/jail.confエントリを追加し、jailを起動し、その中にランチャーと堅牢化されたrc.dスクリプトをインストールします(doas sh zeroclaw-jail-setup.sh、JAIL_NAME/JAIL_PATH/ZPOOL/ZEROCLAW_USERは環境変数で上書き可能)。以下の手動による手順説明では、その動作を解説します。
1. jailを作成する
sh
# jail用のZFSデータセット(UFSを使用している場合は通常のディレクトリを使用してください)。
doas zfs create -o mountpoint=/jails/zeroclaw zroot/jails/zeroclaw # プールの調整
# ホストのリリースに一致するベースを抽出します。
doas fetch -o /tmp/base.txz \
"https://download.freebsd.org/releases/$(uname -m)/$(freebsd-version -u)/base.txz"
doas tar -xpf /tmp/base.txz -C /jails/zeroclaw
doas cp /etc/resolv.conf /jails/zeroclaw/etc/
2. 設定と起動
/etc/jail.conf(ホスト側)に jail エントリを追加します。この例ではホストのネットワークを共有しています。jail に専用のアドレスを割り当てる場合は、代わりに ip4.addr を設定してください。
zeroclaw {
host.hostname = "zeroclaw";
path = "/jails/zeroclaw";
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
exec.clean;
mount.devfs;
persist;
}
sh
doas sysrc jail_enable=YES
doas sysrc jail_list+=ゼロクロウ
doas service jail start zeroclaw
3. jail内にZeroClawをインストールする
上記セクションのすべては、jail の 内部 で実行されます。コマンドの前に doas jexec zeroclaw … を付けるか、doas jexec zeroclaw /bin/sh でシェルを開いてください:
sh
doas jexec zeroclaw pkg install -y rust git # または、ホストでビルドされたバイナリをコピーします
# build + install zeroclaw to /usr/local/bin/zeroclaw exactly as above, then:
doas jexec zeroclaw pw useradd zeroclaw -m -s /usr/sbin/nologin
ランチャーと rc.d スクリプトを jail のファイルシステムにインストールします(ホストから見ると、jail のルートには接頭辞が付きます: /jails/zeroclaw/usr/local/libexec/… および /jails/zeroclaw/usr/local/etc/rc.d/…)。その後、jail の_内部で_サービスを有効化して起動します:
sh
doas jexec zeroclaw sysrc zeroclaw_enable=YES
doas jexec zeroclaw service zeroclaw start
doas jexec zeroclaw service zeroclaw status
Jail固有の注意事項
- ホストからjailのファイルを編集する際は
cp /dev/stdinではなくteeを使用してください。… | doas tee /jails/zeroclaw/usr/local/etc/rc.d/zeroclaw >/dev/nullのようにパイプで渡します。doas cp /dev/stdin …はコピーの途中でcp: /dev/stdin: File changedというエラーで失敗することがあります。 - ゲートウェイは jail 内部でバインドします。 デーモンはデフォルトでループバックをリッスンします。ホストや LAN から接続するには、
--host 0.0.0.0を指定して zeroclaw を起動し(zeroclaw-run.shを編集)、jail に到達可能なアドレスを割り当てるか、ホストからプロキシしてください。 - jail 環境では堅牢化された
rc.dスクリプトを推奨します。 通常、serviceはjexec/sshを介して非対話的に実行しますが、まさにこの状況で基本スクリプトのstartハングや孤立プロセスの積み重ねが問題になります。堅牢化を参照してください。また、jail 内で/var/run/zeroclawを root 所有に保つことで、非特権のサービスユーザーがスーパーバイザーの pidfile を偽造できないようにします。 - 1 つの jail で複数のデーモンを実行する場合(例: ワーカープール)は、ハードニングセクションのプールに関する注記に従ってください。jail は 1 つのプロセステーブルを共有するため、インスタンスごとに 1 つの pidfile/logfile を用意し、
pgrepをランチャーの retitle にバインドします。
Podman + Linuxulator での Linux イメージの実行
上記のネイティブビルドは、ZeroClaw 自体にとっては正しい方法です。しかし、一部の Python ベースのツールやスキルは manylinux 専用のホイール に依存しています。たとえば、polars、pyarrow、oracledb は FreeBSD 向けのホイールを公開していないため、それらをインポートするツールはネイティブな FreeBSD の python3 では動作しません。FreeBSD の Linuxulator(Linux バイナリ互換レイヤー)と Podman を組み合わせれば、FreeBSD ホスト上で 公式の Linux コンテナイメージ を実行でき、それらのツールが必要とする Linux ABI を提供できます。これはネイティブな rc.d デーモンを補完するものです。どちらか一方、または両方を並行して実行できます。
1. 前提条件
Linux ABIを有効にして、Linuxリリースが報告されることを確認します:
sh
doas sysrc linux_enable=YES
doas service linux start # モジュールを読み込み、/compat/linux をマウントします
sysctl compat.linux.osrelease # 例: compat.linux.osrelease: 5.15.0
/etc/rc.conf の linux_enable="YES" を設定すると、起動時に ABI も読み込まれます。次に Podman をインストールします。
sh
doas pkg install -y podman
2. イメージを取得: Linux プラットフォームを強制する
FreeBSD の Podman は、マニフェストリストを解決する際にデフォルトで os=freebsd を使用します。ZeroClaw のイメージは linux/amd64 と linux/arm64 用にのみ公開されているため、単純な podman pull は no image found in manifest list for architecture ..., OS freebsd で失敗します。Linux プラットフォームを明示的に指定してください:
sh
doas podman pull --os linux --arch amd64 ghcr.io/zeroclaw-labs/zeroclaw:debian
latestではなくdebianタグを使用してください。distroless のlatestイメージにはシェルが含まれていないため、エミュレーション下でのデバッグが困難になります。イメージの完全な一覧については Docker & Containers を参照してください。
3. コンテナーを実行する
Linux イメージは Docker & Containers に記載されているとおりに動作し、永続状態を /zeroclaw-data に想定しており、初回実行時に設定をブートストラップします:
sh
doas podman run -d --name zeroclaw --restart=always \
--os linux --arch amd64 \
-p 42617:42617 \
-v /var/db/zeroclaw:/zeroclaw-data \
ghcr.io/zeroclaw-labs/zeroclaw:debian
doas podman exec -it zeroclaw zeroclaw quickstart
Podman が FreeBSD のデフォルトに再解決しないように、(pull だけでなく)すべての run で --os linux --arch amd64 フラグを維持してください。
Linuxulatorに関する注記
- 起動時の永続性。 Podman 自身の
--restart=alwaysは、稼働中の Podman 内でコンテナを再起動するだけで、ホストの再起動を単独で乗り越えることはできません。ホスト再起動後にコンテナを復帰させるには、rc.dスクリプト(ネイティブサービスと同じパターン)または@rebootの cron エントリからpodman startを管理してください。 - ネットワーク.
-p 42617:42617は Podman のブリッジを通じてゲートウェイを公開します。ホスト上でブリッジ/CNI のセットアップが構成されていない場合、--network hostが最もシンプルな代替手段です。その場合、コンテナはホストのネットワークスタックを直接共有します。 - すべてがクリーンにエミュレートされるわけではありません。 Linuxulator は一般的なシステムコール領域をカバーしていますが、特殊なバイナリは未実装の呼び出しに遭遇する場合があります。ツールが正しく動作しない場合は、ZeroClaw のバグだと判断する前に
dmesgでlinux:の警告を確認してください。
ログ
sh
tail -f /var/log/zeroclaw.log
ログレベルは標準の設定 / 環境変数で指定できます。詳細は 運用 → ログと可観測性 を参照してください。
確認
sh
zeroclaw --version
service zeroclaw status
# デーモンがローカルゲートウェイを公開している場合(デフォルト 127.0.0.1:42617):
fetch -qo - http://127.0.0.1:42617/health
"status":"ok" のヘルスペイロードはゲートウェイが稼働中であることを示します。レスポンスの runtime フィールドには、コンポーネントごとのヘルス情報(チャネルやプロバイダーなど)が含まれます。
アンインストール
sh
doas service zeroclaw stop
doas sysrc -x zeroclaw_enable
doas rm /usr/local/etc/rc.d/zeroclaw /usr/local/libexec/zeroclaw-run.sh
doas rm /usr/local/bin/zeroclaw
rm -rf ~/.zeroclaw # オプション — 設定と履歴を削除します
次へ
- サービス管理: ファーストパーティのバックエンドが他のプラットフォームでどのように動作するか
- リファレンス → 設定: 設定ファイルのレイアウト
- クイックスタート: 最初の会話
- 運用 → 概要: 本番環境での実行