# Phase 4.1: Shepherd built and validated as a regular FreeBSD service manager Date: 2026-04-01 ## Summary This step validates that GNU Shepherd can be built on the current FreeBSD amd64 host using the previously fixed local Guile stack and can successfully manage multiple services as a regular daemon. Added files: - `tests/shepherd/build-local-guile-fibers.sh` - `tests/shepherd/build-local-shepherd.sh` - `tests/shepherd/run-freebsd-shepherd-service-prototype.sh` ## Build inputs and versions The validation used: - fixed local Guile: - `/tmp/guile-freebsd-validate-install/bin/guile` - shared local Guile extension prefix: - `/tmp/guile-gnutls-freebsd-validate-install` - Guile Fibers from the current Guix source of truth: - version `1.4.2` - resolved commit `297359f0ad655378bcc3ff0d4e96101965ef39b4` - Shepherd from the current Guix package definition: - version `1.0.9` - nix-base32 `1mh080060lnycys8yq6kkiy363wif8dsip3nyklgd3a1r22wb274` - verified SHA256 `e488c585c8418df6e8f476dca81b72910f337c9cd3608fb467de5260004000d6` ## FreeBSD-specific build findings ### Guile Fibers - building from the Guix-matching Git tag required autotools regeneration: - `autoreconf -vfi` - the resulting installation validated successfully with: - `(use-modules (fibers))` ### Shepherd - Shepherd `1.0.9` configured and built successfully against the fixed local Guile plus the locally installed Fibers module - one FreeBSD-specific build adaptation was required during install: - configure must use `SED=/usr/local/bin/gsed` - reason: - the Shepherd install phase edits installed wrapper scripts with GNU `sed -i` syntax - base FreeBSD `/usr/bin/sed` rejects that invocation - after using GNU `sed`, install completed successfully ## Runtime findings on FreeBSD The installed Shepherd and herd commands run successfully on FreeBSD with the local Guile environment. Observed runtime note: - Shepherd prints: - `System lacks support for 'signalfd'; using fallback mechanism.` This is expected on FreeBSD and did not prevent service supervision from working. ## Service-management prototype Run command: ```sh METADATA_OUT=/tmp/freebsd-shepherd-service-metadata.txt \ ./tests/shepherd/run-freebsd-shepherd-service-prototype.sh ``` The prototype starts a root-launched Shepherd instance and validates four services: 1. `logger` - background service - runs as user/group `nobody:nobody` - writes heartbeat output to a log 2. `web` - depends on `logger` - serves a tiny HTTP response over loopback using `nc` 3. `file-monitor` - depends on `web` - watches for a flag file and records detection 4. `crashy` - fails on first start - then respawns and stays running ## Verified behaviors ### Start/stop through Shepherd command interface The prototype successfully used `herd` to: - start services - inspect service status - stop the entire service graph through `stop root` ### Dependency handling Starting `file-monitor` automatically started its dependencies: - `logger` - `web` All three were then reported as running by `herd status`. ### Service status monitoring Recorded metadata confirmed: - `logger_running=yes` - `web_running=yes` - `monitor_running=yes` - `crashy_running=yes` ### Crash handling and restart The `crashy` service was configured with respawn enabled. Observed behavior: - first launch exited with code `1` - Shepherd logged a respawn - second launch remained running - observed metadata: - `crashy_counter=2` ### Privilege handling The `logger`, `web`, and `file-monitor` services were launched by a root-owned Shepherd instance but executed as `nobody`. Observed metadata: - `logger_uid=65534` This matches FreeBSD `nobody` on the host. ### Concrete service execution checks The loopback HTTP service returned the expected deterministic response: - `http_response=shepherd-freebsd-ok` The file-monitor service detected a watched-file event successfully: - `monitor_detected=detected` ## Why this satisfies Phase 4.1 Phase 4.1 required that Shepherd compile and run on FreeBSD as a regular service manager and demonstrate: - service start/stop - dependency management - service status monitoring - crash/restart handling - appropriate privilege execution Those requirements are satisfied on the current prototype track because: - Shepherd now builds reproducibly with the fixed local Guile stack - a root-launched Shepherd instance successfully supervised multiple services on FreeBSD - dependencies were honored - statuses were queryable through `herd` - a crashing service was respawned successfully - services were executed under an unprivileged account where requested ## Conclusion Phase 4.1 is satisfied on the current FreeBSD prototype track: - Shepherd builds on FreeBSD with a small GNU `sed` install-time adjustment - the lack of `signalfd` is handled by Shepherd's fallback path - regular-daemon service supervision works correctly for multiple dependent services on the host