colibri/docs/ISO-SERVICE-LAYOUT.md
Sam & Claude 4517e13935
Some checks failed
CI / rust (pull_request) Has been cancelled
CI / markdown (pull_request) Has been cancelled
fix(daemon): fail closed when socket ownership is unsafe (Sam & Codex)
Return an error from the socket server when another daemon owns the Unix socket or bind setup fails, and broadcast shutdown so the daemon does not stay alive without a control socket. Also format the PR docs.\n\nChecks: cargo fmt --check; ./scripts/check-format.sh; git diff --check; cargo test -p colibri-daemon clear_stale_socket -- --nocapture; cargo test -p colibri-daemon --test sigterm_shutdown -- --nocapture.
2026-06-15 09:08:56 +02:00

101 lines
4.3 KiB
Markdown

# Colibri ISO Service Layout
## Service identity
| Field | Value |
| ------------ | ---------------------------------------------- |
| Service name | `colibri_daemon` |
| Binary | `/usr/local/bin/colibri-daemon` |
| User | `colibri` (unprivileged, `/usr/sbin/nologin`) |
| Group | `colibri` |
| Supervisor | `daemon(8)` — restart on crash, privilege drop |
## Filesystem layout
```
/usr/local/bin/colibri-daemon ← daemon binary (foreground, no self-daemonize)
/usr/local/bin/colibri ← CLI client (status, create-task, etc.)
/usr/local/bin/colibri-test-agent ← test agent (fake Pi JSONL)
/usr/local/etc/rc.d/colibri_daemon ← rc.d service script
/usr/local/etc/colibri/
rc.conf.sample ← service config template
provider.env ← optional API keys (mode 0600, root-owned)
/usr/local/etc/newsyslog.conf.d/
colibri.conf ← log rotation (1MB, 7 archives)
/var/db/colibri/ ← persistent data (750 colibri:colibri)
colibri.sqlite ← coordination store
sessions/ ← JSONL session files
/var/run/colibri/ ← tmpfs (recreated each boot)
colibri.sock ← Unix socket (770 colibri:colibri, set by daemon)
colibri-daemon.pid ← child pidfile (daemon(8) -p)
colibri-daemon-supervisor.pid ← supervisor pidfile (daemon(8) -P)
/var/log/colibri/ ← persistent logs
daemon.log ← stdout/stderr from colibri-daemon
```
## Boot-time behavior
1. `rc.d` starts `colibri_daemon` after LOGIN + cleanvar
2. `prestart`: creates `/var/run/colibri/`, `/var/db/colibri/`, `/var/log/colibri/`
3. `daemon(8)` forks `colibri-daemon` as user `colibri`, redirects logs
4. `poststart`: waits up to 10s for `/var/run/colibri/colibri.sock` to appear
5. Daemon binds socket, opens SQLite, starts scheduler loop
6. CLI clients connect via `colibri` binary → Unix socket
## Shutdown behavior
1. `rc.d` sends SIGTERM to daemon(8) supervisor (via custom `stop_cmd`)
2. Supervisor forwards signal to colibri-daemon child and exits (no restart)
3. Colibri closes socket, flushes SQLite, stops scheduler
4. `poststop`: removes stale socket from tmpfs
## Startup validation
```sh
# Check service status
service colibri_daemon status
# Socket health (nc must be available)
service colibri_daemon health
# CLI check
colibri status
colibri create-task --title "iso-check"
colibri list-tasks --status queued
```
## Config knobs (set in /etc/rc.conf or /etc/rc.conf.d/colibri_daemon)
| Variable | Default | Purpose |
| -------------------------- | --------------------------- | ----------------------- |
| `colibri_daemon_enable` | NO | Enable at boot (YES/NO) |
| `colibri_daemon_user` | colibri | Runtime user |
| `colibri_daemon_group` | colibri | Runtime group |
| `colibri_daemon_cost_mode` | smart | fast/smart/max |
| `colibri_daemon_data_dir` | /var/db/colibri | Persistent data |
| `colibri_daemon_run_dir` | /var/run/colibri | tmpfs runtime |
| `colibri_daemon_socket` | $run_dir/colibri.sock | Unix socket path |
| `colibri_daemon_db_path` | $data_dir/colibri.sqlite | SQLite path |
| `colibri_daemon_logfile` | /var/log/colibri/daemon.log | Log output |
## Log rotation
`/usr/local/etc/newsyslog.conf.d/colibri.conf`:
```
/var/log/colibri/daemon.log colibri:colibri 640 7 1024 * JC
```
Rotates at 1MB, keeps 7 compressed archives, bzip2 compression.
## Secrets policy
- No API keys in rc.conf or service environment files.
- `DEEPSEEK_API_KEY` and other provider keys are set via a separate,
mode-0600 env file sourced by the daemon (e.g. `/usr/local/etc/colibri/provider.env`).
- The rc.d script does NOT read or expose secrets.
- Logs go to `/var/log/colibri/` which is mode 0750 colibri:colibri —
only the colibri user and root can read them.