|

Zygaena Init System

Clone
hg clone ssh://hg@leafscale.isurus.dev:2222/zygaena/zyginit hg clone https://leafscale.isurus.dev/zygaena/zyginit
deaa4c646836 bugs: close 004 (fixed in 0.2.7) — archive
Chris Tusa <chris.tusa@leafscale.com> 4 days ago

zyginit

Init daemon and service supervisor for Zygaena/Hammerhead.

zyginit replaces SMF (Service Management Facility) with a single-process
service manager written in Reef. It uses
TOML service definitions, symlink-based enable/disable, and Hammerhead
process contracts for kernel-level service tracking.

Components

Binary Path Description
zyginit /sbin/init (kernel exec target on Hammerhead) PID 1 init daemon and service supervisor
zygctl /sbin/zygctl Administrative CLI tool
sysv-wrapper /sbin/sysv-wrapper (+ symlinks halt, reboot, poweroff, telinit) Translates legacy commands to zygctl calls

Requirements

  • Reef 0.4.0+ compiler (reefc)
  • Clang or GCC (C compiler — for helpers.c and contract stubs on Linux)
  • Hammerhead OS (for process contract support; Linux for development only)

Building

On Hammerhead (production)

gcc -c src/helpers.c -o build/helpers.o
reefc build -l contract --obj build/helpers.o
cd tools/zygctl && gcc -c src/symlink_wrapper.c -o build/symlink_wrapper.o && reefc build --obj build/symlink_wrapper.o
cd tools/sysv-wrapper && make

helpers.o is REQUIRED — it provides zyginit_* C wrappers (uadmin,
sync, fsync, utmpx writes, STREAMS push, system()) that the Reef code
calls via extern "C". Without it the link fails on undefined refs.

On Linux (development, contracts stubbed)

clang -c src/helpers.c -o build/helpers.o
clang -c src/contract_linux_stubs.c -o build/contract_linux_stubs.o
reefc build --obj build/helpers.o --obj build/contract_linux_stubs.o
cd tools/zygctl && clang -c src/symlink_wrapper.c -o build/symlink_wrapper.o && reefc build --obj build/symlink_wrapper.o

Build output

build/zyginit                            # The init daemon
tools/zygctl/build/zygctl                # The admin CLI
tools/sysv-wrapper/sysv-wrapper          # The legacy-command shim

Install on Hammerhead

cp build/zyginit /sbin/init
cp tools/zygctl/build/zygctl /sbin/zygctl
cd tools/sysv-wrapper && make install     # creates /sbin/halt, /sbin/reboot, /sbin/poweroff, /sbin/telinit

Configuration

Service definitions are TOML files in /etc/zyginit/:

/etc/zyginit/
├── sshd.toml
├── cron.toml
├── syslog.toml
├── network.toml
├── network/
│   └── start.sh
├── filesystem.toml
├── filesystem/
│   └── start.sh
└── enabled.d/
    ├── sshd -> ../sshd.toml
    ├── cron -> ../cron.toml
    └── ...

Services are enabled by symlinks in enabled.d/. See the
Administration Guide for details.

Example service definition

# /etc/zyginit/sshd.toml
[service]
name = "sshd"
description = "Secure Shell Daemon"
type = "daemon"

[exec]
start = "/usr/lib/ssh/sshd -D"

[runlevel]
mode = "multi"             # default — runs in multi-user only

[dependencies]
requires = ["network", "filesystem"]

[restart]
on = "failure"
delay = 5
max_retries = 3

The [runlevel] mode field accepts "always", "single", or "multi"
(default "multi"). Essential services that need to run in single-user
recovery mode (root-fs, devfs, filesystem, etc.) use "always". The
recovery shell itself uses "single".

Usage

Managing services

zygctl status              # Show all service states
zygctl status sshd         # Show one service
zygctl start sshd          # Start a service
zygctl stop sshd           # Stop a service
zygctl restart sshd        # Restart a service
zygctl enable sshd         # Enable at boot
zygctl disable sshd        # Disable at boot
zygctl reload              # Re-scan enabled.d for changes
zygctl log sshd            # Show service output log
zygctl list                # List all definitions

Runlevel transitions and shutdown

zygctl single              # Transition to single-user (recovery) mode
zygctl multi               # Transition back to multi-user
zygctl halt                # Cleanly stop services + halt
zygctl reboot              # Cleanly stop services + reboot
zygctl poweroff            # Cleanly stop services + poweroff

The legacy commands work too via /sbin/sysv-wrapper symlinks:

init 0      → zygctl halt
init 5      → zygctl poweroff
init 6      → zygctl reboot
init s/S/1  → zygctl single
init 2/3/4  → zygctl multi
init q/Q    → zygctl reload
halt        → zygctl halt
reboot      → zygctl reboot
poweroff    → zygctl poweroff
telinit <N> → like init <N>

Boot args

The kernel passes boot-args from the loader to /sbin/init. zyginit
honors -s for single-user boot:

# In /boot/loader.conf:
boot-args="-v -s"

Testing without replacing PID 1

Run zyginit as a regular process with a custom config directory:

export ZYGINIT_CONFIG_DIR=/path/to/test/zyginit
export ZYGINIT_SOCKET=/tmp/zyginit.sock
./build/zyginit

Then use zygctl with the same socket:

ZYGINIT_SOCKET=/tmp/zyginit.sock ./tools/zygctl/build/zygctl status

Documentation

  • Administration Guide — Writing services, boot sequence, troubleshooting
  • Architecture and Design — Design decisions and rationale
  • Roadmap — Forward-looking plan with task checklists
  • Implementation Plan — Module-by-module technical details
  • Man pages in docs/man/:
    • zyginit(8) — Init daemon
    • zygctl(8) — Admin CLI
    • zyginit(5) — Service definition format
  • Example services in services/examples/

Architecture

zyginit is a single-threaded process using poll(2) to monitor:

  • Process contracts — Kernel-level service tracking (Hammerhead)
  • Signal pipe — SIGCHLD, SIGTERM, SIGHUP handling
  • Unix socketzygctl command interface

At boot, service dependencies are resolved via topological sort into
parallel tiers. Services within a tier start concurrently.

What zyginit does NOT do

  • No XML parsing (that's the point of replacing SMF)
  • No SQLite database
  • No door-based IPC
  • No multi-daemon architecture
  • No 32-bit support (Hammerhead is 64-bit only)

Project Layout

zyginit/
├── reef.toml                   # Reef project manifest
├── README.md                   # This file
├── ROADMAP.md                  # Forward-looking roadmap
├── CLAUDE.md                   # AI assistant context
├── src/
│   ├── main.reef               # Event loop, runlevel, shutdown
│   ├── config.reef             # TOML config parser (incl. [runlevel])
│   ├── depgraph.reef           # Dependency graph and topological sort
│   ├── contract.reef           # Hammerhead process contract FFI
│   ├── supervisor.reef         # Service lifecycle, restart, transitions
│   ├── socket.reef             # Unix domain socket server
│   ├── shutdown.reef           # uadmin / sync wrappers
│   ├── helpers.c               # C glue (uadmin, fsync, utmpx, ...)
│   └── contract_linux_stubs.c  # Linux dev stubs for libcontract
├── tools/
│   ├── zygctl/                 # Admin CLI (separate Reef project)
│   └── sysv-wrapper/           # Tiny C binary for /sbin/halt etc.
├── services/
│   ├── examples/               # Example TOML service definitions
│   └── hammerhead/             # Production boot chain for hh-prototest
├── docs/
│   ├── guide.md                # Administration guide
│   ├── DESIGN.md               # Architecture and design
│   ├── IMPLEMENTATION_PLAN.md
│   ├── superpowers/plans/      # Per-iter implementation plans
│   └── man/                    # Man pages (mdoc format)
├── tests/
│   └── integration/            # Integration test suite (run_tests.sh)
└── stub/                       # Original design stubs (reference)

License

CDDL-1.0

Author

Chris Tusa chris.tusa@leafscale.com
Leafscale, LLC

Languages
Markdown 62%
Reef 27%
Shell 5%
C 2%
Groff 2%
plaintext 1%
TOML 1%
Makefile 0%
Activity
230 changesets
Updated 4 days ago