Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

FreeBSD

ZeroClaw fonctionne nativement sur FreeBSD (testé sur FreeBSD 15.0-RELEASE, amd64). Deux éléments diffèrent des chemins Linux/macOS/Windows :

  1. Pas de binaire précompilé et pas de prise en charge de install.sh. FreeBSD n’est pas une cible de l’installateur d’amorçage, vous devez donc compiler depuis les sources avec la chaîne d’outils Rust du système.
  2. Pas de backend zeroclaw service. La commande zeroclaw service install connaît systemd, OpenRC, launchd et le Planificateur de tâches Windows, mais pas le rc.d de FreeBSD. Vous devez installer vous-même un petit script rc.d. Cette page vous en fournit un, complet et testé.

Tout le reste, la configuration, les fournisseurs, les canaux, le démon, la passerelle, est identique à n’importe quelle autre plateforme.

Quand utiliser FreeBSD. Les déploiements FreeBSD sont courants dans l’hébergement de type appliance réseau, embarqué et basé sur les jails, où les opérateurs recherchent la stabilité du système de base, les primitives ZFS + jail, ou ont besoin de FreeBSD pour des raisons de politique interne ou de licence. Comme il n’existe pas de binaire précompilé et que la configuration rc.d est manuelle, cette voie convient aux opérateurs à l’aise avec les conventions FreeBSD. Si vous évaluez simplement les plateformes sans exigence spécifique liée à FreeBSD, Linux (systemd) ou macOS (launchd) offrent une mise en route plus rapide via install.sh et zeroclaw service install.

Récupérez les fichiers au lieu de les copier-coller. Chaque script shell et exemple de configuration présenté ci-dessous est fourni dans dist/freebsd/ : copiez-les directement sur votre hôte. Le guide pas à pas explique le rôle de chaque élément et sa raison d’être.

Dépendances système

Installez la chaîne d’outils et l’environnement d’exécution depuis pkg :

sh

doas pkg install -y rust git
PaquetPourquoi
rustFournit cargo et rustc pour compiler le binaire. La MSRV de l’espace de travail de ZeroClaw est Rust 1.96.0 ; le port rust de FreeBSD suit une version stable plus récente, donc pkg install rust la satisfait.
gitClonage du dépôt, et requis à l’exécution si vous utilisez des outils basés sur git.

doas, et non sudo. FreeBSD fournit doas comme outil d’élévation de privilèges de base ; sudo est un port optionnel. Les exemples présentés ici utilisent doas. Un fichier /usr/local/etc/doas.conf minimal accordant au groupe wheel une élévation sans mot de passe est :

permit nopass keepenv :wheel

Compiler depuis les sources

sh

git clone https://github.com/zeroclaw-labs/zeroclaw.git
cd zeroclaw
cargo build --release

Le binaire de release est généré dans target/release/zeroclaw. Une compilation propre avec l’ensemble de fonctionnalités par défaut prend un certain temps sur du matériel modeste, ce qui est normal ; ZeroClaw est un grand espace de travail Rust.

Pour alléger le build, désactivez les fonctionnalités dont vous n’avez pas besoin (voir ./install.sh --list-features sur une machine Linux, ou Cargo.toml) :

sh

cargo build --release --no-default-features --features agent-runtime

Installer le binaire

Placez-le quelque part dans le PATH. /usr/local/bin est l’emplacement conventionnel pour les binaires installés via les ports sur FreeBSD :

sh

doas install -m 755 target/release/zeroclaw /usr/local/bin/zeroclaw
zeroclaw --version

(~/.cargo/bin/zeroclaw fonctionne tout aussi bien si vous préférez une installation par utilisateur.)

Configuration au premier lancement

sh

zeroclaw quickstart

Cela crée ~/.zeroclaw/ avec une configuration de démarrage et vous guide à travers la configuration du fournisseur. La structure et la priorité de la configuration sont identiques à toutes les autres plateformes : voir Référence → Config.

Authentification du fournisseur

L’authentification des fournisseurs n’est pas spécifique à FreeBSD. Les fournisseurs à clé API ont simplement besoin que la clé soit définie via la passerelle, zerocode, zeroclaw config set, ou l’environnement. Les fournisseurs OAuth et par abonnement (p. ex. un abonnement ChatGPT OpenAI/Codex, Anthropic Claude Pro/Team) obtiennent leur jeton depuis le tableau de bord ou le flux de connexion du fournisseur lui-même, que vous configurez ensuite de la même manière qu’une clé API.

Pour le modèle complet des identifiants (clés API, jetons OAuth/abonnement, redéfinitions par variables d’environnement et le magasin de secrets), consultez Provider Configuration → Credentials et OAuth and subscription auth. Cette page fait référence pour toutes les plateformes.

Exécution en tant que service (rc.d)

Étant donné que zeroclaw service install n’a pas de backend FreeBSD, supervisez le démon avec daemon(8), l’outil natif de FreeBSD, via un script rc.d. Cela vous offre service zeroclaw start|stop|restart|status, le redémarrage en cas de plantage, un pidfile et le démarrage automatique au boot.

Des copies prêtes à installer de chaque script ci-dessous se trouvent dans dist/freebsd/ (zeroclaw-run.sh, le zeroclaw.rc de base et le zeroclaw-hardened.rc renforcé). Les deux scripts rc.d contiennent un espace réservé @@ZEROCLAW_USER@@ que vous remplacez avec sed lors de l’installation, vous pouvez donc récupérer les fichiers au lieu de les copier-coller : voir dist/freebsd/README.md. Le guide ci-dessous explique le rôle de chaque élément.

1. Script de lancement

daemon(8) démarre le processus enfant avec un environnement minimal, exportez donc un PATH complet (FreeBSD place git, python3, etc. sous /usr/local/bin, qui n’est pas dans le PATH par défaut des services). Le script rc.d exécute ceci via daemon -u <user>, qui, conformément à daemon(8), définit HOME, USER et SHELL à partir de l’entrée passwd de ce compte avant l’exec, de sorte que ${HOME} correspond déjà au répertoire personnel du compte de service (les comptes dont le répertoire personnel se trouve ailleurs, ainsi que les remplacements de compte d’exécution dans rc.conf, fonctionnent sans modification). Enregistrez sous /usr/local/libexec/zeroclaw-run.sh :

sh

#!/bin/sh
# daemon -u <user> has already set HOME from the accountentrée passwd de l'utilisateur.
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. Script rc.d

Enregistrez sous /usr/local/etc/rc.d/zeroclaw :

sh

#!/bin/sh
#
zeroclaw
# REQUIRE: NETWORKING DAEMON
# MOT-CLÉ : shutdown

. /etc/rc.subr

name=zeroclaw
rcvar="zeroclaw_enable"

load_rc_config $name

: ${zeroclaw_enable:=NON}
# Ne nommez PAS ceci ${name}_user — rc.subr exécuterait alors son propre changement d'utilisateur via su
# and collide with daemon -u (échec de la définition de l'environnement utilisateur).
: ${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 restent détenus par root : rc.d (root) écrit ici le pidfile
    # de daemon -P et s'y fie ensuite, donc l'utilisateur de service non privilégié ne doit pas
    # pouvoir le falsifier. daemon -o ouvre le logfile avant de basculer vers ${zeroclaw_runas}.
    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ôle des indicateurs :

  • -r : supervise et redémarre le processus enfant s’il se termine (récupération après plantage).
  • -P ${pidfile} : écrit le pid du superviseur afin que service zeroclaw stop puisse lui envoyer un signal.
  • -o ${logfile} : redirige la sortie stdout/stderr du processus enfant vers un fichier journal.
  • -u ${zeroclaw_runas} : exécute zeroclaw en tant qu’utilisateur non privilégié, et non root.

Pourquoi daemon -u et non su -m. Un schéma courant est daemon ... su -m user -c launcher. Évitez-le : su(1) ne transmet pas SIGTERM à son processus enfant, donc service zeroclaw stop tue le superviseur daemon mais laisse derrière lui un processus zeroclaw orphelin, et le start suivant empile une seconde copie. daemon -u user fait de daemon(8) le parent direct de zeroclaw, qui transmet ainsi le signal d’arrêt et s’arrête proprement. (Si vous êtes contraint d’utiliser un script basé sur su pour d’autres raisons, ajoutez un nettoyage pkill -f "zeroclaw daemon" à son chemin d’arrêt.)

3. Activer et démarrer

sh

doas sysrc zeroclaw_enable=YES
doas sysrc zeroclaw_runas=youruser     # le compte qui possède ~/.zeroclaw

doas service zeroclaw start
doas service zeroclaw status

service zeroclaw stop / restart fonctionnent comme prévu. Comme zeroclaw_enable=YES est présent dans /etc/rc.conf (écrit par sysrc), le démon démarre également au démarrage du système.

4. Renforcement pour le fonctionnement sans surveillance et à distance

Le script ci-dessus est correct pour une installation interactive à instance unique. Trois comportements de daemon(8) vous surprendront dès que vous piloterez le service à distance (via ssh) ou que vous exécuterez plus d’une copie. Ces trois problèmes ont affecté un déploiement en production ; les correctifs sont minimes. Un script complet intégrant tous les correctifs ci-dessous est disponible sous dist/freebsd/zeroclaw-hardened.rc : installez-le à la place du script zeroclaw de base.

service ... start distant se bloque. daemon -r hérite et maintient ouverts les stdin/stdout/stderr avec lesquels il a été lancé. Exécutez ssh host 'service zeroclaw start' et le superviseur maintient le fd stdout de votre session ssh ouvert indéfiniment, de sorte que ssh ne reçoit jamais EOF et la commande se bloque même si le daemon a démarré correctement. Détachez les descripteurs propres au superviseur : -o ${logfile} redirige déjà la sortie de l’enfant, donc rien n’est perdu :

sh

command_args=-r -P ${pidfile} -o ${logfile} -u ${zeroclaw_runas} ${launcher}
# ...invoquer le daemon avec ses propres std{in,out,err} redirigés vers /dev/null :
/usr/sbin/daemon ${command_args} </dev/null >/dev/null 2>&1

Si vous utilisez le formulaire standard command/command_args, encapsulez le démarrage dans un start_cmd personnalisé afin de contrôler la redirection. Ce seul changement est ce qui rend l’appel à service zeroclaw start sûr depuis ssh, CI ou un déploiement via un outil de gestion de configuration.

Des start répétés empilent des superviseurs orphelins. Un simple start ne vérifie pas si un superviseur est déjà en cours d’exécution, donc un second start (ou un start après un crash ayant laissé un pidfile obsolète) lance un autre daemon qui se dispute le port de la passerelle avec le premier. Rendez start idempotent en le faisant refuser lorsqu’un superviseur actif existe déjà. Identifiez le superviseur par le chemin du lanceur, et non par le pidfile seul (le pidfile peut être obsolète). Deux pièges spécifiques à FreeBSD lorsque vous faites cela :

  • daemon(8) renomme son superviseur en daemon: /usr/local/libexec/zeroclaw-run.sh[<childpid>] (daemon). Ainsi pgrep -f zeroclaw-run.sh correspond au superviseur, mais un pgrep -f sur le nom du binaire ne correspond pas. Liez sur le préfixe littéral daemon: : cela correspond au superviseur et jamais au processus enfant, à un lancement manuel du lanceur, ni au shell rc lui-même. Liez aussi le [ final qui ouvre le [<childpid>] de daemon, afin qu’un lanceur frère dont le nom commence simplement par zeroclaw-run.sh ne puisse pas correspondre (cela compte lorsque vous exécutez un pool, voir Exécuter un pool d’instances ci-dessous).
  • FreeBSD pgrep -f ne respecte pas une ancre ^ en début de motif face à cette chaîne de retitrage : pgrep -f '^daemon: ...' ne correspond à rien. Supprimez le ^ ; appuyez-vous sur le préfixe daemon: pour la spécificité et échappez le point de .sh en [.] (et le crochet en [[]) afin qu’ils soient littéraux.

sh

launcher_pat=daemon: /usr/local/libexec/zeroclaw-run[.]sh[[]

zeroclaw_running()
{
    pgrep -f "${launcher_pat}" >/dev/null 2>&1
}

read depuis un pidfile de daemon -P signale un faux négatif. daemon -P écrit le pid sans saut de ligne final, donc IFS= read -r pid < "${pidfile}" retourne un statut non nul (EOF avant le saut de ligne) même si pid a bien été défini. Si vous le protégez avec read -r pid < "$pf" || return 1, chaque instance en cours d’exécution semble arrêtée et votre start idempotent lance allègrement un doublon. Ne basez pas le chemin de succès sur le statut de sortie de read : validez plutôt la valeur :

sh

pid=""
IFS= read -r pid < "${pidfile}"     # NE PAS ajouter `|| return 1` ici
case "${pid}" in
    ''|*[!0-9]*) return 1 ;;        # vide ou non numérique → considérer comme non en cours d'exécution
esac

Exécution d’un pool d’instances. Pour exécuter N démons (par ex. un pool de workers), attribuez à chacun son propre pidfile et logfile (worker.$i.pid, worker.$i.log) et faites une boucle de démarrage/arrêt sur $i. Comme le nouveau titre du superviseur est identique pour chaque instance et n’inclut pas les arguments propres à chaque instance, le pidfile est le seul identifiant par instance : pilotez l’arrêt/le statut depuis le pidfile, et lors d’un arrêt complet, balayez tout superviseur résiduel vers lequel aucun pidfile actif ne pointe (démarré à la main, ou dont le pidfile est devenu obsolète).

Exécution dans une jail

Les jails offrent à ZeroClaw une racine isolée avec ses propres paquets, son utilisateur de service et, éventuellement, sa propre adresse IP, ce qui est utile si l’hôte exécute d’autres services ou si vous souhaitez restreindre l’agent. La configuration du service est identique au cas de l’hôte ; vous l’exécutez simplement à l’intérieur de la jail. Ce guide décrit la mise en place d’une jail épaisse (thick jail) classique avec les outils du système de base (aucun gestionnaire de jail requis).

Option en une étape. dist/freebsd/zeroclaw-jail-setup.sh automatise les étapes 1 à 3 ci-dessous : il crée la jail, extrait une base correspondante, ajoute l’entrée dans /etc/jail.conf, démarre la jail et installe le lanceur ainsi que le script rc.d renforcé à l’intérieur (doas sh zeroclaw-jail-setup.sh, avec JAIL_NAME / JAIL_PATH / ZPOOL / ZEROCLAW_USER remplaçables via les variables d’environnement). La procédure manuelle ci-dessous explique son fonctionnement.

1. Créer la jail

sh

# Dataset ZFS pour la jail (utilisez un simple répertoire si vous êtes sur UFS).
doas zfs create -o mountpoint=/jails/zeroclaw zroot/jails/zeroclaw   # ajuster le pool

# Extraire une base correspondant à la version de l'HÔTE dans celui-ci.
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. Configurer et démarrer

Ajoutez une entrée de jail dans /etc/jail.conf (côté hôte). Cet exemple partage le réseau de l’hôte ; définissez plutôt ip4.addr si vous attribuez une adresse dédiée à la jail.

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+=zeroclaw
doas service jail start zeroclaw

3. Installer ZeroClaw dans la jail

Tout ce qui figure dans les sections ci-dessus s’exécute à l’intérieur de la jail : préfixez les commandes avec doas jexec zeroclaw …, ou ouvrez un shell avec doas jexec zeroclaw /bin/sh :

sh

doas jexec zeroclaw pkg install -y rust git     # ou copier un binaire compilé sur l'hôte
# build + install zeroclaw to /usr/local/bin/zeroclaw exactly as above, then:
doas jexec zeroclaw pw useradd zeroclaw -m -s /usr/sbin/nologin

Installez le lanceur et le script rc.d dans le système de fichiers de la jail (depuis l’hôte, la racine de la jail est préfixée : /jails/zeroclaw/usr/local/libexec/… et /jails/zeroclaw/usr/local/etc/rc.d/…). Ensuite, activez et démarrez le service à l’intérieur de la jail :

sh

doas jexec zeroclaw sysrc zeroclaw_enable=YES
doas jexec zeroclaw service zeroclaw start
doas jexec zeroclaw service zeroclaw status

Notes spécifiques aux jails

  • Modifiez les fichiers du jail depuis l’hôte avec tee, pas avec cp /dev/stdin. Faites passer la sortie par … | doas tee /jails/zeroclaw/usr/local/etc/rc.d/zeroclaw >/dev/null ; doas cp /dev/stdin … peut échouer en cours de copie avec cp: /dev/stdin: File changed.
  • La passerelle se lie à l’intérieur de la jail. Le démon écoute sur l’interface loopback par défaut : pour y accéder depuis l’hôte ou le réseau local, lancez zeroclaw avec --host 0.0.0.0 (modifiez zeroclaw-run.sh) et attribuez à la jail une adresse joignable, ou utilisez un proxy depuis l’hôte.
  • Privilégiez le script rc.d renforcé dans une jail. Vous piloterez généralement service de manière non interactive via jexec/ssh, ce qui est exactement le contexte où le blocage de start du script de base et l’accumulation de processus orphelins posent problème : voir Hardening. Cela maintient également /var/run/zeroclaw sous la propriété de root à l’intérieur de la jail, afin que l’utilisateur de service non privilégié ne puisse pas falsifier le pidfile du superviseur.
  • Exécuter plusieurs démons dans une même jail (p. ex. un pool de workers) suit la note sur les pools de la section sur le durcissement : un pidfile/logfile par instance et un pgrep lié au retitrage du lanceur, puisque la jail partage une seule table de processus.

Exécution de l’image Linux sous Podman + Linuxulator

La compilation native ci-dessus est la bonne approche pour ZeroClaw lui-même. Mais certains outils et skills basés sur Python dépendent de wheels exclusivement manylinux : polars, pyarrow et oracledb, par exemple, ne publient pas de wheels pour FreeBSD, donc un outil qui les importe ne peut pas s’exécuter sous le python3 natif de FreeBSD. Le Linuxulator de FreeBSD (couche de compatibilité binaire Linux) combiné à Podman vous permet d’exécuter l’image de conteneur Linux officielle sur un hôte FreeBSD, offrant à ces outils l’ABI Linux qu’ils attendent. Cela complète le démon rc.d natif : vous pouvez exécuter l’un ou l’autre, ou les deux côte à côte.

1. Prérequis

Activez l’ABI Linux et vérifiez qu’elle signale une version de Linux :

sh

doas sysrc linux_enable="YES"
doas service linux start              # charge les modules et monte /compat/linux
sysctl compat.linux.osrelease         # p. ex. compat.linux.osrelease: 5.15.0

linux_enable="YES" dans /etc/rc.conf charge également l’ABI au démarrage. Installez ensuite Podman :

sh

doas pkg install -y podman

2. Récupérez l’image : forcez la plateforme Linux

Sous FreeBSD, Podman utilise par défaut os=freebsd lors de la résolution d’une liste de manifestes. Les images de ZeroClaw sont publiées uniquement pour linux/amd64 et linux/arm64, donc un simple podman pull échoue avec no image found in manifest list for architecture ..., OS freebsd. Forcez explicitement la plateforme Linux :

sh

doas podman pull --os linux --arch amd64 ghcr.io/zeroclaw-labs/zeroclaw:debian

Utilisez le tag debian plutôt que latest : l’image distroless latest n’a pas de shell, ce qui rend le débogage sous émulation peu pratique. Consultez Docker & Containers pour la liste complète des images.

3. Exécutez le conteneur

L’image Linux se comporte exactement comme documenté dans Docker & Containers, elle attend un état persistant dans /zeroclaw-data et initialise une configuration au premier lancement :

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

Conservez les indicateurs --os linux --arch amd64 sur chaque run (pas seulement sur pull) afin que Podman ne résolve pas à nouveau vers la valeur par défaut FreeBSD.

Notes sur Linuxulator

  • Persistance au démarrage. L’option --restart=always de Podman ne redémarre le conteneur qu’au sein d’une instance Podman en cours d’exécution ; elle ne survit pas à elle seule à un redémarrage de l’hôte. Supervisez le podman start depuis un script rc.d (même modèle que le service natif) ou une entrée cron @reboot afin que le conteneur soit relancé après le redémarrage de l’hôte.
  • Mise en réseau. -p 42617:42617 publie la passerelle via le pont de Podman. Si la configuration bridge/CNI n’est pas en place sur votre hôte, --network host est l’alternative la plus simple : le conteneur partage alors directement la pile réseau de l’hôte.
  • Tout ne s’émule pas parfaitement. Linuxulator couvre la surface des appels système courants, mais les binaires exotiques peuvent rencontrer des appels non implémentés. Si un outil se comporte mal, vérifiez les avertissements linux: dans dmesg avant de supposer qu’il s’agit d’un bug de ZeroClaw.

Journaux

sh

tail -f /var/log/zeroclaw.log

Définissez le niveau de journalisation via la configuration standard / les variables d’environnement : voir Opérations → Journaux et observabilité.

Vérifier

sh

zeroclaw --version
service zeroclaw status
# si le démon expose la passerelle locale (par défaut 127.0.0.1:42617) :
fetch -qo - http://127.0.0.1:42617/health

Une charge utile de santé "status":"ok" signifie que la passerelle est opérationnelle ; le champ runtime de la réponse contient l’état de santé par composant (canaux, fournisseurs, etc.).

Désinstaller

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        # facultatif — supprime la configuration + l'historique

Suivant