feat: remaining phases — actuator provisioning, transition checks, cleanup
Phase 2: Actuator provisioning - ProvisionLXC: pct create, start, package install, mounts, health check - ProvisionVM: qm create, status check via SSH - sshExecSimple helper for lightweight SSH command execution - resolveHost helper for entity attribute lookups Phase 5: Transition check enforcement - TransitionChecks map with 8 named checks: age-key-enrolled, mesh-joined, health-check-answering, no-inbound-edges, secrets-revoked, backups-verified, ingress-dns-removed, doc-page-complete - All checks accept pool + entity attrs for validation at transition time Phase 6: Cleanup - tools/setup-caveman.sh — npm install + wrapper + templates - tools/setup-hermes-soul.sh — SOUL.md provisioning - CLIENTS.md updated for thin client model (no git clone, API-based) - Old git-sync references replaced with context poller All tests pass, go vet clean.
This commit is contained in:
86
CLIENTS.md
86
CLIENTS.md
@@ -30,33 +30,52 @@ approval.
|
||||
|
||||
## Enrollment
|
||||
|
||||
Enrolled clients have a checkout at `/opt/homelab-context/`. If this
|
||||
directory does not exist, the client is not enrolled.
|
||||
Thin client model — no git clone, no sync timer. `bootstrap.sh` fetches only
|
||||
the agent orientation files and tooling from the raw Gitea URL, then enrolls
|
||||
via the Oikos API.
|
||||
|
||||
To enroll:
|
||||
```bash
|
||||
# Run from an existing enrolled client
|
||||
homelab client add <hostname>
|
||||
# Run from any machine with mesh connectivity
|
||||
curl -fsSL https://git.hubris.network/dtoro/Homelab-Docs/raw/main/bootstrap.sh | sudo bash
|
||||
|
||||
# Or with optional tooling:
|
||||
curl ... | sudo bash -s -- --with-mcp # wire Claude's MCP config
|
||||
curl ... | sudo bash -s -- --with-hermes # install Goose + Hermes
|
||||
```
|
||||
|
||||
This runs `bootstrap.sh` on the target, which:
|
||||
1. Clones the repo to `/opt/homelab-context/`
|
||||
2. Configures the auto-sync timer
|
||||
3. Provisions agent persona from `hermes/SOUL.md` (on Hermes agents)
|
||||
4. Installs Caveman tooling for terse communication
|
||||
This calls `POST /api/v1/clients/enroll` on the Oikos API, which:
|
||||
1. Validates the entity exists in DB (planned or provisioning state)
|
||||
2. Validates mesh IP against expected subnets
|
||||
3. Generates an age keypair and delivers it to the client
|
||||
4. Creates an Infisical machine identity
|
||||
5. Transitions the entity to provisioning state
|
||||
|
||||
## After enrollment
|
||||
|
||||
### What changes on your machine
|
||||
|
||||
- `/opt/homelab-context/` — the repo checkout, your source of truth
|
||||
- `/opt/homelab-context/inventory.yaml` — read this first: your hostname, role,
|
||||
peers, mounts, services
|
||||
- `/opt/homelab-context/seeds/policy.yaml` — rules for what actions you can
|
||||
take autonomously vs. what requires operator approval
|
||||
- Auto-sync timer — pulls the repo every 5 minutes
|
||||
- `~/.hermes/SOUL.md` — agent persona (on Hermes agents)
|
||||
- `~/bin/caveman_wrapper.sh` — terse communication tooling
|
||||
- `/opt/homelab/` — agent orientation files (CLIENTS.md, AGENTS.md, OIKOS.md)
|
||||
- `/opt/homelab/tools/` — tooling scripts (caveman, hermes-soul)
|
||||
- `/etc/age/key.txt` — age private key for SOPS decryption (fallback)
|
||||
- `/etc/infisical/identity` — Infisical machine identity (primary secrets)
|
||||
- Context poller — launchd/systemd timer hits `GET /api/v1/clients/{slug}/context` every 5 minutes for agent file updates
|
||||
|
||||
### What's NOT on your machine
|
||||
|
||||
- No git clone of the full repo
|
||||
- No `git pull` sync timer
|
||||
- No `bin/homelab` CLI (replaced by MCP tools + API)
|
||||
- No `.sops.yaml` or SOPS-encrypted backups (served via API context endpoint on demand)
|
||||
|
||||
### Thin client vs control plane
|
||||
|
||||
| | Thin client (workstation) | Control plane (mac-mini) |
|
||||
|---|---|---|
|
||||
| Disk footprint | ~100KB (orientation files + tools) | Full repo clone (~50MB) |
|
||||
| Update mechanism | `GET /context?since=` poll | Git pull + post-pull.sh |
|
||||
| Source of truth | DB via MCP | DB + local seeds + archive |
|
||||
| Secrets access | Infisical (primary), age/SOPS served via API (fallback) | Infisical + local SOPS files |
|
||||
|
||||
### Your identity
|
||||
|
||||
@@ -69,33 +88,36 @@ mesh address.
|
||||
|
||||
1. **Postgres database** (runtime) — authoritative for entities, knowledge,
|
||||
signals, ledger. Query via MCP or REST API.
|
||||
2. **Repo at `/opt/homelab-context/`** — bootstrap seeds + documentation.
|
||||
On disk, available offline.
|
||||
2. **Context poller** — agent files and tooling fetched via API deltas every
|
||||
5 minutes.
|
||||
3. **Never guess.** If data is missing, query MCP. If MCP is down, grep the
|
||||
clone.
|
||||
local `/opt/homelab/` files.
|
||||
|
||||
## The sync timer
|
||||
## The context poller
|
||||
|
||||
Every 5 minutes, `systemd` (Linux) or `launchd` (macOS) runs:
|
||||
Every 5 minutes, launchd (macOS) or systemd (Linux) hits:
|
||||
|
||||
1. `git pull` via `tools/post-pull.sh`
|
||||
2. Any `tools/*.setup.sh` scripts that need to run
|
||||
```
|
||||
GET /api/v1/clients/ws:{hostname}/context?since={last_timestamp}
|
||||
```
|
||||
|
||||
This keeps your checkout current and applies tooling updates automatically.
|
||||
To trigger sync manually: `sudo homelab sync`.
|
||||
The API returns which agent files, tools, and SOPS config changed since the
|
||||
last poll. Only changed files are downloaded. This replaces the old
|
||||
`git pull` with a lightweight HTTP delta.
|
||||
|
||||
To trigger manually: run `/opt/homelab/tools/context-poller.sh`.
|
||||
|
||||
## Making changes
|
||||
|
||||
- **Read state**: use MCP tools or the repo checkout
|
||||
- **Read state**: use MCP tools or the API
|
||||
- **Mutate state** (restart, edit config, deploy): classify the action against
|
||||
`seeds/policy.yaml`:
|
||||
policy (query `preflight` MCP tool):
|
||||
- `read_only` / `reversible_low` — execute directly
|
||||
- `config_mutation` / `destructive` — request operator approval via the
|
||||
`homelab` CLI
|
||||
- `config_mutation` / `destructive` — request operator approval via
|
||||
`POST /api/v1/entities/{slug}/activate` (or equivalent lifecycle endpoint)
|
||||
- **Secrets**: use Infisical (primary) or SOPS (fallback). Never hardcode.
|
||||
- **Knowledge**: if you observe a discrepancy between docs and live state,
|
||||
update the DB via the API in the same session. Run `oikos export` to
|
||||
regenerate seeds.
|
||||
update the DB via the API in the same session.
|
||||
|
||||
## MCP endpoint
|
||||
|
||||
|
||||
Reference in New Issue
Block a user