18 KiB
Clawdie Shell Module Manifest
Purpose: Explicit dependency graph for 12-module pipeline (Phase 1) Used by: firstboot.sh wizard (Phase 2.1) for sequencing and recovery
Module Dependencies Map
[0.0 setup-import] (optional) → setup.txt + system.env import
↓
[0.1 zfs] (baremetal only) → CLAWDIE_BOOT_MODE
↓
[User Input]
↓
[1.1 env] → ASSISTANT_NAME, AGENT_DOMAIN, TZ, LLM_PROVIDER
↓
├→ [1.2 pkg] (optional: can run any time)
├→ [1.3 gpu] (optional: hardware detection)
├→ [1.3b nvidia] ← REQUIRES: DETECTED_GPU from [1.3]
├→ [1.3c ssh] ← REQUIRES: ASSISTANT_NAME from [1.1]
├→ [1.4 system] ← REQUIRES: TZ, AGENT_DOMAIN from [1.1]
├→ [1.4.1 pf] ← REQUIRES: ASSISTANT_NAME from [1.1]
├→ [1.4.2 desktop] ← PREFERS: GPU config from [1.3]
├→ [1.5 tailscale] (optional) ← PREFERS: repos from [1.2]
← PREFERS: pf from [1.4.1]
├→ [1.5.1 npm-globals] ← PREFERS: repos from [1.2]
└→ [1.6 deploy] ← REQUIRES: .env from [1.1]
← REQUIRES: repos from [1.2]
← PREFERS: gpu config from [1.3]
Module Specifications
0.0: setup-import.sh
Purpose: Read setup.txt and system.env from the writable USB config partition before the wizard.
Wizard Inputs: None
Outputs (Exports):
- identity/substrate values:
ASSISTANT_NAME,HOSTNAME,AGENT_DOMAIN,TZ - optional pre-baked provider/channel values, if present for backward compatibility
ZFS_POOL,ZFS_LAYOUT,ZFS_DATA_DISKS,ZFS_HOT_SPARES,ZFS_PREFIX- optional hardware hints from
system.env
Checkpoint Name: setup-import
Skip Condition:
- no
CLAWDIEFAT32 partition found - or
setup.txtmissing - or identity/substrate values are incomplete for the non-interactive path
Error Handling:
- safe-fail back to wizard
- never blocks interactive install on a missing or partial config partition
0.1: shell-zfs.sh
Purpose: Detect existing ZFS pools and select boot mode (install | upgrade | maintenance)
Wizard Inputs: None (automatic detection)
Outputs (Exports):
CLAWDIE_BOOT_MODE—install,upgrade, ormaintenancePOOL_NAME— detected pool name (when present)
Checkpoint Name: [ZFS]
Skip Condition:
- If
TARGET=vps(ZFS not used)
Error Handling:
- Safe-fail: if no pools found, defaults to
install - If maintenance mode selected, execs
maintenance-mode.shand exits
1.1: shell-env.sh
Purpose: Generate a minimal .env seed (identity + feature flags)
Wizard Inputs (Tier 1 - Required):
ASSISTANT_NAME— Human name (e.g., "Clawdie Smith")AGENT_DOMAIN— public or local domain zone (default:${agentname}.home.arpa)TZ— Timezone (e.g., "Europe/Ljubljana")
Wizard Inputs (Tier 2 - Optional):
- Provider/model values — normally configured after first boot in
/setup - Provider API keys — optional backward-compatible pre-bake only
- Telegram credentials — optional backward-compatible pre-bake only
Outputs (Created):
$ENV_FILE—/home/clawdie/.env(chmod 600)- Contains: identity + feature flags from the live installer handoff or fallback wizard
- Copied into:
/home/clawdie/clawdie-ai/.envby shell-deploy (1.6)- Completed by: Clawdie-AI onboarding (secrets + derived defaults)
Exports (for downstream modules):
AGENT_NAME— derived from ASSISTANT_NAME (e.g., "clawdie-smith")DETECTED_ABI— optional (frompkg config abi)
Checkpoint Name: [ENV]
Skip Condition:
- If
.envexists AND contains AGENT_DOMAIN: skip (idempotent)
Error Handling:
- Fails if ASSISTANT_NAME, AGENT_DOMAIN, or TZ missing
- Validates
.envhas the minimal required variables before marking complete
Recovery Note:
- If 1.1 fails, user runs
clawdie-firstboot --resume - Skips 1.1 if
[ENV] COMPLETEin progress file - Can re-run to update .env (idempotent via sysrc pattern)
1.2: shell-pkg.sh
Purpose: Configure package repositories (online FreeBSD + offline USB)
Wizard Inputs: None (automatic from [1.1])
Inputs from [1.1]:
DETECTED_ABI— optional (auto-detected if missing)- Used for FreeBSD repo URL:
pkg+https://pkg.FreeBSD.org/${ABI}/latest
- Used for FreeBSD repo URL:
Outputs (Created):
-
/etc/pkg/repos/FreeBSD.conf- Online repo, priority 10 (fallback)
- URL:
pkg+https://pkg.FreeBSD.org/FreeBSD:15:amd64/latest - Enable: yes
-
/etc/pkg/repos/Clawdie-USB.conf- Offline USB repo, priority 100 (preferred)
- URL:
file:///mnt/media/packages - Enable: yes
-
/var/cache/pkg/bastille/- Seeded with .pkg files from USB (for offline jail provisioning)
Exports: None
Checkpoint Name: [PKG]
Skip Condition:
- If both FreeBSD.conf AND Clawdie-USB.conf exist: skip
Error Handling:
- Safe to fail: If USB packages missing, continues (online only)
- pkg update may fail in chroot (expected, logged as warning)
- Cache seeding errors are non-fatal (safe-fail with
|| true)
Recovery Note:
- Can re-run to update repo configs
- If jails fail to provision, user may re-run 1.2 to refresh cache
- Dependency-free: can run before or after 1.1 (but run 1.1 first for ABI)
1.3: shell-gpu.sh
Purpose: Detect GPU hardware, select driver kernel module
Wizard Inputs: None (automatic detection)
Inputs from [1.1]:
- None (hardware detection is autonomous)
Hardware Detection (via pciconf -lv):
- Intel → i915kms
- AMD → amdgpu
- NVIDIA → nvidia (sets DETECTED_GPU="nvidia")
- VMware → vmwgfx
- Unknown → vesa (fallback)
Outputs (Created):
/etc/rc.conf(append/update):kld_list="i915kms"(or amdgpu, vesa, etc.)- Idempotent: updates if already exists
Exports (for downstream):
DETECTED_GPU— "intel", "amd", "nvidia", "vmware", or "vesa"- Used by [1.3b nvidia] to decide: run or skip
Checkpoint Name: [GPU]
Skip Condition:
- If
kld_list=already in rc.conf: skip
Error Handling:
- pciconf may fail outside chroot (expected)
- Silently falls back to "vesa" if detection fails
- kldload live fails gracefully (expected in chroot)
Recovery Note:
- Can re-run to re-detect GPU
- No dependencies on [1.1], [1.2]
- MUST run before [1.4 system] (which reads rc.conf)
- REQUIRED before [1.3b nvidia]
1.3b: shell-nvidia.sh ⭐ (NEW in Option B)
Purpose: NVIDIA driver version selection (PC-BSD heritage)
Wizard Inputs (optional, Tier 2):
NVIDIA_DRIVER_VERSION— "590", "470", or "390" (env var for unattended)- OR: interactive bsddialog menu if not set
Inputs from [1.3 gpu]:
- ✅ REQUIRED:
DETECTED_GPUvariable- If DETECTED_GPU ≠ "nvidia": skip gracefully
- If DETECTED_GPU = "nvidia": show driver selection
Outputs (Created):
-
/etc/rc.conf(append/update):nvidia_driver_version="590"(or "470", "390")- Idempotent: updates if exists
-
/var/run/nvidia_driver_version.txt(optional, safe-fail):- Marker file for build system
- Non-critical; failure is ignored
Exports (for downstream):
NVIDIA_DRIVER_VERSION— "590", "470", or "390"- Used during package selection in 1.6
Checkpoint Name: [NVIDIA]
Skip Condition:
- If DETECTED_GPU ≠ "nvidia": skip (returns 0 without error)
- If
nvidia_driver_version=already in rc.conf: skip
Driver Mapping:
- 590 → nvidia-driver-590 (Maxwell & newer: GTX 750 Ti+, RTX 20/30/40)
- 470 → nvidia-driver-470 (Kepler: GTX 600/700, Titan Black)
- 390 → nvidia-driver-390 (Fermi: GTX 400/500)
Error Handling:
- Invalid version: logs warning, uses default "590"
- bsddialog not available: silently uses default
- /var/run write fails: non-fatal, continues
Recovery Note:
- DEPENDS ON [1.3 gpu]: WILL FAIL if DETECTED_GPU not set
- Can run after [1.3], before [1.4], [1.6]
- Unattended mode: set
NVIDIA_DRIVER_VERSIONenv var before wizard
1.3c: shell-ssh.sh
Purpose: Configure SSH access and system passwords
Wizard Inputs (Tier 1 - Required):
ASSISTANT_NAME— used for default user namingASSISTANT_PASSWORD— operator passwordROOT_PASSWORD— root password (optional if disabled)
Outputs (Created):
/etc/master.passwdupdates viapw(user + password hashes)/home/clawdie/.ssh/authorized_keys(if SSH key provided)/etc/ssh/sshd_config(hardened defaults)
Checkpoint Name: [SSH]
Skip Condition:
- If
[SSH] COMPLETEin progress file
Error Handling:
- Password prompts must succeed; failure exits the step
- Missing SSH key is non-fatal (password login allowed)
1.4: shell-system.sh
Purpose: System configuration (hostname, timezone, rc.conf, services)
Wizard Inputs (from [1.1]):
TZ— Timezone (e.g., "Europe/Ljubljana")AGENT_DOMAIN— public or local domain zone (e.g., "home.arpa")
Inputs from [1.3 gpu]:
- rc.conf already updated by [1.3] (this module appends to it)
Outputs (Created/Modified):
-
/etc/rc.conf(append/update):timezone="Europe/Ljubljana"dbus_enable="YES"hald_enable="YES"seatd_enable="YES"display_manager="lightdm"lightdm_enable="YES"- Idempotent: uses sysrc pattern
-
/etc/hostname:- Contains single line:
home.arpa
- Contains single line:
-
/etc/profile.d/clawdie.sh:- npm environment (PATH, npm_config_prefix)
Exports: None
Checkpoint Name: [SYSTEM]
Skip Condition:
- If
timezone=ANDdbus_enable=already in rc.conf: skip
Error Handling:
- hostname command may fail in chroot (safe-fail)
- service onestart fails gracefully (expected in chroot)
- Missing /etc/profile.d: creates directory
Recovery Note:
- DEPENDS ON [1.1]: requires TZ, AGENT_DOMAIN
- Can run after [1.3], before [1.4.2], [1.5]
- Idempotent: safe to re-run
1.4.2: shell-desktop.sh
Purpose: Detect display hardware and enable desktop stack when appropriate
Wizard Inputs: None (automatic detection)
Inputs from [1.3 gpu]:
DETECTED_GPU— used to decide which desktop packages to enable
Outputs (Created/Modified):
/etc/rc.confupdates for desktop services (when enabled)- Desktop flag file for firstboot progress tracking
Checkpoint Name: [DESKTOP]
Skip Condition:
- If headless/VPS scenario detected
- If desktop already enabled
Error Handling:
- Detection failures fall back to headless mode
1.4.1: shell-pf.sh ⭐ (NEW in v0.5.0)
Purpose: Configure PF firewall with block-all default, SSH protection, jail NAT, glasspane VNC
Wizard Inputs: None (automatic)
Inputs from [1.1]:
ASSISTANT_NAME— used for assistant identity, not bridge namingAGENT_NET— optional, default: 192.168.100.0/24
Outputs (Created):
-
/etc/pf.conf- Block-all default
- SSH brute-force protection (max-src-conn-rate 3/60)
- NAT for agent jails (192.168.0.0/16 supernet)
- Pass rules for HTTP/HTTPS
- Commented block for Tailscale + glasspane VNC (agent enables later)
-
/etc/rc.conf(append):cloned_interfaces="bridge0"ifconfig_bridge0_name="warden0"ifconfig_${BRIDGE}="inet 192.168.100.1/24 up"gateway_enable="YES"pf_enable="YES"pf_reload_enable="YES"
-
/usr/local/etc/rc.d/pf_reload- rc.d service:
REQUIRE: tailscaled - Fixes PF/Tailscale cold boot race (resolves tailscale0 interface index)
- rc.d service:
Exports: None
Checkpoint Name: [PF]
Skip Condition:
- If
pf_enable="YES"already in rc.conf: skip
Error Handling:
- Fails if external interface cannot be detected (no default route)
- Bridge creation may fail in chroot (expected, non-fatal)
- PF load fails in chroot (expected, will load on reboot)
Recovery Note:
- DEPENDS ON [1.1]: requires ASSISTANT_NAME
- Should run AFTER [1.4 system] (both write rc.conf, different vars)
- MUST run BEFORE [1.5 tailscale] (tailscale modifies PF rules)
- pf_reload pre-installed even without Tailscale — harmless now, essential later
Glasspane VNC:
- Port 5900 (wayvnc → cage → Chromium)
- Blocked on ext_if, passed on tailscale0
- Uncommented by agent when Tailscale is enabled
1.5: shell-tailscale.sh
Purpose: Optional Tailscale install + enablement for secure remote access.
Wizard Inputs (Tier 2 - Optional):
FEATURE_TAILSCALE— YES/NO toggle (default NO)TAILSCALE_AUTHKEY— optional device auth key (tskey-...) for unattended login; recommended reusable for host + jails
Inputs from [1.1]:
ASSISTANT_NAME— used to derive a safe hostname if neededAGENT_DOMAIN— used to derive a hostname label if set to a public domain
Outputs (Created):
/etc/rc.confentry:tailscaled_enable="YES"- Tailscale device login (if no auth key), logged to
/var/log/clawdie-firstboot.log
Checkpoint Name: [TAILSCALE]
Skip Condition:
- If
FEATURE_TAILSCALE != YES
Error Handling:
- Safe to fail: network or daemon start issues are logged and do not abort install
- If
pkg install tailscalefails, logs a warning and continues
Recovery Note:
- Can be re-run manually:
service tailscaled start && tailscale up
1.5.1: shell-npm-globals.sh
Purpose: Install bundled npm CLI tools (claude, gemini, pi) from ISO cache
Wizard Inputs: None (automatic)
Inputs from [1.2] — PREFERRED:
- Offline repo cache (ensures fully offline install)
Outputs (Created):
/opt/clawdie/npm-global/bin/*— bundled CLI binaries/etc/profile.d/clawdie.shupdates (PATH) if missing
Checkpoint Name: [NPM-GLOBALS]
Skip Condition:
- If npm globals already installed in
/opt/clawdie/npm-global
Error Handling:
- Missing cache logs warning and skips (non-fatal)
1.6: shell-deploy.sh
Purpose: Extract Clawdie-AI (offline tarball incl. node_modules), run installer, start services
Wizard Inputs: None (automatic)
Inputs from [1.1] — REQUIRED:
.envfile must exist (path:$ENV_FILE)- Sourced to get: ASSISTANT_NAME, AGENT_DOMAIN, jail IPs, DB config
- Failure if missing: hard exit
Inputs from [1.2] — PREFERRED (not required):
- Repos configured (speeds up offline provisioning)
- Pkg cache seeded (enables offline jail setup)
- But: can run without [1.2] (falls back to online)
Inputs from [1.3], [1.3b] — OPTIONAL:**
- rc.conf kld_list (already applied to system)
- nvidia_driver_version (used for jail package selection)
Outputs (Created):
/home/clawdie/clawdie-ai/.env— seeded from [1.1]- Clawdie-AI directory structure extracted
node_modules/present (bundled into ISO tarball at build time)- Jails created (worker, db, cms, optional mgmt)
- Services provisioned (just install)
Exports: None
Checkpoint Name: [DEPLOY]
Skip Condition:
- If Clawdie-AI/package.json AND node_modules/ exist: skip extraction
- But: always runs just install (jails may need provisioning)
Error Handling:
- Missing .env: hard exit (module exits with error)
- Missing tarball: logs warning, assumes already extracted
- If node_modules are missing: attempts
npm ci(requires network) and fails if it cannot install deps - Jail creation failures: logs warning, continues
- DB connectivity failures: deferred to runtime
Recovery Note:
- HARD DEPENDENCY ON [1.1]: will fail if .env missing
- Should run AFTER [1.1], [1.2], [1.3], [1.3c], [1.4], [1.4.2], [1.5.1]
- Can be re-run for idempotency (skips if already deployed)
- Failures here block full system setup
Execution Order (from firstboot.sh)
User Input (wizard Tier 1 + optional Tier 2)
↓
1. zfs ✓ CONDITIONAL (baremetal only, sets boot mode)
↓
2. gpu ✓ RECOMMENDED (hardware detection)
↓
3. nvidia ✓ CONDITIONAL (only if GPU=nvidia)
↓
4. pkg ✓ OPTIONAL (run early for offline support)
↓
5. ssh ✓ REQUIRED (user + password provisioning)
↓
6. env ✓ REQUIRED (creates .env with identity)
↓
7. system ✓ REQUIRED (system-level config)
↓
8. desktop ✓ CONDITIONAL (display detection + enablement)
↓
9. pf ✓ REQUIRED (PF firewall + jail NAT)
↓
10. tailscale ✓ OPTIONAL (remote access, modifies PF rules)
↓
11. npm-globals ✓ OPTIONAL (offline npm CLIs)
↓
12. deploy ✓ REQUIRED (depends on .env from env)
↓
SUCCESS: Clawdie-AI ready for first boot
Resume/Recovery Rules (for Phase 2.1)
Rule 1: Hard Dependencies
- 1.1 must complete before 1.6 (deploy sources .env)
- 1.3 must complete before 1.3b (1.3b checks DETECTED_GPU)
- 1.4 should run before 1.4.2 and 1.4.1 (system config affects desktop + PF)
- 1.4.1 should run before 1.5 (PF rules updated by tailscale)
Rule 2: Skip Logic on Resume
# Pseudo-code for firstboot.sh --resume logic:
if grep -q "[ENV] COMPLETE" $PROGRESS_FILE; then
skip_module env
fi
if grep -q "[PKG] COMPLETE" $PROGRESS_FILE; then
skip_module pkg
fi
if grep -q "[GPU] COMPLETE" $PROGRESS_FILE; then
skip_module gpu
fi
if grep -q "[NVIDIA] COMPLETE" OR DETECTED_GPU != "nvidia"; then
skip_module nvidia
fi
# ... etc
Rule 3: Error Recovery
-
Soft failure (warning): Module logs error but continues
- Examples: gpu live-load fails, pkg update fails
- Action on resume: re-run module (idempotent)
-
Hard failure (exit 1): Module exits shell
- Examples: .env missing in 1.6, AGENT_DOMAIN not set
- Action on resume: fix input, re-run from beginning
For Phase 2.1 Implementation
Use this manifest to:
-
Sequence modules in firstboot.sh:
. shell-zfs.sh clawdie_shell_zfs_detect # [ZFS] COMPLETE (baremetal) . shell-gpu.sh clawdie_shell_gpu_detect # [GPU] COMPLETE . shell-nvidia.sh clawdie_shell_nvidia_detect # [NVIDIA] COMPLETE # ... etc -
Implement resume logic:
# If --resume, skip completed modules grep -q "[ENV] COMPLETE" $PROGRESS && skip_env=1 -
Handle wizard tiers:
- Tier 1 (required): ASSISTANT_NAME, AGENT_DOMAIN, TZ
- Tier 2 (optional): provider/model and Telegram values for backward-compatible pre-bake
-
Define checkpoint names for progress tracking
Version History
- current dev ISO: live QML installer, post-install setup token, 12 shell modules, ZFS/desktop/npm-globals, bundled npm CLIs
- v0.9.0: 8 modules, runtime GPU detection, no ZFS/desktop/npm-globals
- v0.5.0: 6 modules, PF firewall, glasspane VNC support
- v1.1 (planned): Add shell-gpu-passthrough.sh, add shell-upgrade.sh