diff --git a/PLAN-UNIFY.md b/PLAN-UNIFY.md new file mode 100644 index 00000000..673ce1e2 --- /dev/null +++ b/PLAN-UNIFY.md @@ -0,0 +1,175 @@ +# Plan: Unify clawdie-iso + clawdie-shell → single repo with --target flag + +**Author:** Sam & Claude +**Date:** 06.apr.2026 +**Status:** Ready to implement +**Branch:** implementation + +--- + +## Context + +Two repos existed: `clawdie-iso` (VPS/headless) and `clawdie-shell` (baremetal/Lumina desktop). +Decision: **clawdie-shell is being archived**. Everything merges into clawdie-iso with `--target vps|baremetal`. + +Both targets need a display stack (cage + wayvnc) for browser automation and the "glasspane" operator +feature. The difference is baremetal adds Lumina for local human use. + +**Glasspane concept:** operator connects via Tailscale → SSH into tmux panes (terminal view) or +wayvnc → cage → Chromium (visual browser automation view). Both secured behind Tailscale — PF +blocks ext_if for SSH and VNC, passes only on tailscale0. + +--- + +## Decision: Tailscale is mandatory + +Tailscale is no longer optional. It is the security perimeter. All deployments must authenticate +before install completes. Free up to 100 devices: https://tailscale.com/pricing + +- Pre-install requirement: operator generates an auth key at Tailscale admin console before booting ISO +- Baremetal wizard: Tailscale auth key is screen 1 (before disk selection, identity, timezone) +- VPS/cloud build: `TAILSCALE_AUTHKEY` must be set in env or build fails +- Escape hatch: `--insecure-no-tailscale` flag exists but is named deliberately to signal risk +- Headscale (self-hosted) supported via `--tailscale-login-server` flag (same auth flow) + +After Tailscale connects, PF is updated to: +- Block SSH (22) and VNC (5900) on ext_if +- Pass SSH (22) and VNC (5900) on tailscale0 only +- pf_reload rc.d service (REQUIRE: tailscaled) handles cold boot race — already built + +--- + +## Step 1: Port PF module from clawdie-shell + +**Source:** `https://codeberg.org/Clawdie/clawdie-shell` (being archived — pull before it goes) + +Files to port: +- `firstboot/clawdie-shell-pf.sh` → `firstboot/shell-pf.sh` (rename to match iso naming convention) +- `NETWORKING.md` → `NETWORKING.md` (copy to iso root) + +The PF module: +- Detects ext_if via `route -n get default` (no hardcoded interface names) +- Creates agent bridge `${ASSISTANT_NAME}0` at 192.168.100.1/24 +- Writes /etc/pf.conf with block-all default, SSH rate limiting, jail NAT +- Installs pf_reload rc.d service with `REQUIRE: tailscaled` + +After porting, add VNC to the PF rule set in shell-pf.sh: +```sh +# In the Tailscale activation block: +pass in quick on $tailscale_if proto tcp to port 5900 keep state # wayvnc glasspane +block in quick on $ext_if proto tcp to port 5900 # block public VNC +``` + +--- + +## Step 2: Make Tailscale mandatory + +**File: `build.cfg`** +- Change `FEATURE_TAILSCALE="${FEATURE_TAILSCALE:-NO}"` → `FEATURE_TAILSCALE="YES"` +- `TAILSCALE_AUTHKEY` stays as-is (empty default, must be supplied) + +**File: `build.sh`** +- Add early validation: if `TAILSCALE_AUTHKEY` is empty and `--insecure-no-tailscale` not set → print error and exit 1 +- Add `--insecure-no-tailscale` flag parsing (sets `FEATURE_TAILSCALE=NO`, prints warning) +- Add `--tailscale-login-server ` flag (Headscale support, passed through to shell-tailscale.sh) + +**File: `firstboot/shell-tailscale.sh`** +- Remove the `FEATURE_TAILSCALE != YES` early return — Tailscale always runs +- Add `TAILSCALE_LOGIN_SERVER` support: if set, append `--login-server "$TAILSCALE_LOGIN_SERVER"` to `tailscale up` + +**File: `firstboot/firstboot.sh`** +- Move Tailscale setup to first wizard screen (currently it's optional/last) +- Baremetal wizard order becomes: Welcome → Tailscale key → Identity → Timezone → [LLM] → [Telegram] → Summary +- VPS/cloud: key already in build.cfg, no wizard needed + +**File: `firstboot/cloud-path-test.sh`** +- Add `TAILSCALE_AUTHKEY` to required vars check (must be non-empty) +- Add `FEATURE_TAILSCALE` check (must be YES) + +--- + +## Step 3: Add --target flag to build.sh + +**Current state:** `TARGET="baremetal"` in build.cfg, but build.sh doesn't branch on it yet for packages. + +**Change:** build.sh package assembly should conditionally include desktop packages: + +```sh +# Always included: +pkg-list-host.txt # includes cage, wayvnc, waypipe already +pkg-list-jails.txt + +# Only for baremetal: +if [ "$TARGET" = "baremetal" ]; then + pkg-list-desktop-base.txt + pkg-list-lumina.txt + # + NVIDIA packages if GPU_DRIVER is set +fi +``` + +The Wayland stack (cage, wayvnc, waypipe, seatd, weston, xwayland) stays in pkg-list-host.txt +for both targets — VPS needs it for glasspane, baremetal needs it for both glasspane and desktop. + +--- + +## Step 4: Create REQUIREMENTS.md + +New file at repo root. Pre-install checklist for operators. Must include: + +- Tailscale account (free): https://tailscale.com +- Generate a reusable auth key: Tailscale admin console → Settings → Keys → Generate auth key + - Check "Reusable" if deploying multiple Clawdie instances + - Check "Ephemeral" only if you want the device removed when offline +- Headscale alternative for air-gapped/enterprise: https://headscale.net +- Minimum hardware: 4 cores, 8 GB RAM, 50 GB disk +- USB size: 64 GB minimum, 128 GB recommended + +--- + +## Step 5: Cleanup + +- Remove `pkg-list-kde.txt`, `pkg-list-mate.txt`, `pkg-list-xfce.txt` if present (already removed in iso, confirm) +- Update AGENTS.md to note clawdie-shell is archived +- Codeberg: archive clawdie-shell repo (Settings → Danger Zone → Archive — Sam does this manually) + +--- + +## Package list canonical state (clawdie-iso wins) + +| List | iso state | shell state | Action | +|------|-----------|-------------|--------| +| pkg-list-host.txt | Full (tailscale, rust, codex, full wayland) | Subset | Keep iso version | +| pkg-list-lumina.txt | Granular (lumina-core + lightdm + openbox) | lumina-desktop meta + sddm | Keep iso version | +| pkg-list-desktop-base.txt | xorg-minimal + drm-kmod | + desktop-installer | Keep iso version | +| pkg-list-nvidia*.txt | Versioned (390/470/590) | Single list | Keep iso version | +| pkg-list-jails.txt | Present | Present | Diff and merge if needed | + +--- + +## Files summary + +| File | Repo | Action | +|------|------|--------| +| `firstboot/shell-pf.sh` | iso | NEW — ported from clawdie-shell | +| `NETWORKING.md` | iso | NEW — ported from clawdie-shell | +| `REQUIREMENTS.md` | iso | NEW — Tailscale pre-install guide | +| `build.cfg` | iso | FEATURE_TAILSCALE=YES, validation note | +| `build.sh` | iso | --target branching, mandatory Tailscale validation | +| `firstboot/shell-tailscale.sh` | iso | Remove optional skip, add login-server support | +| `firstboot/firstboot.sh` | iso | Tailscale to wizard screen 1 | +| `firstboot/cloud-path-test.sh` | iso | Add TAILSCALE_AUTHKEY required check | + +--- + +## Verification + +After implementation: +1. `sh firstboot/cloud-path-test.sh` — all checks pass including TAILSCALE_AUTHKEY +2. `sh firstboot/integration-test.sh` — all modules pass +3. `./build.sh --target vps` without TAILSCALE_AUTHKEY → fails with clear error +4. `./build.sh --target vps --insecure-no-tailscale` → builds with warning +5. `./build.sh --target baremetal` → includes Lumina packages, skips for vps + +## Attribution + +Commit as: `(Sam & Claude)` or `(Sam & Codex)` per AGENTS.md convention.