blumeops/docs/reference/infrastructure/indri.md
Erich Blume a2f1e06224 Add hephaestus sync hub to indri (launchagent, PWA, device-code OIDC) (#369)
Makes indri the canonical **heph** hub for the hub-and-spoke task/context system, deployed as a self-updating LaunchAgent managed by Ansible. Other devices (gilbert) attach as offline-capable spokes.

## What's here
- **`ansible/roles/heph`** (tag `heph`) — bootstrap `cargo install hephd` (only if absent; `--self-update` keeps it current after), version-pinned `heph-pwa` checkout served via `--web-root`, launchagent `mcquack.eblume.heph`:
  ```
  hephd --mode server --http-addr 0.0.0.0:8787 --db … --web-root …
        --oidc-issuer …/o/heph/ --oidc-audience heph
        --self-update --self-update-interval-secs 600
  ```
  `~/.cargo/bin` is on the agent `PATH` so self-update's `cargo install` works.
- **Caddy** — `heph.ops.eblu.me → localhost:8787` (TLS for the PWA secure context).
- **Authentik** — new `heph` **public device-code** OIDC app + `default-device-code-flow` bound to the default brand's `flow_device_code` (verified live: brand `authentik-default`, field currently unset → additive).
- **Docs** — `services/hephaestus.md` (Path-A seeding runbook + spoke caveat), `indri.md`, changelog fragment.

## Three features requested
- **Autoupdate** — 10-min interval (`--self-update-interval-secs 600`).
- **PWA** — `--web-root` (confirmed shipped in v1.2.0).
- **Spoke** — gilbert reconfig documented (post-merge step).

## Deploy plan (not done yet — awaiting review)
1. Seed from gilbert (Path A): `heph daemon stop` → copy `heph.db` → `DELETE FROM meta WHERE key='origin'`.
2. Sync Authentik `apps`/blueprint; verify blueprint status via API (not just logs).
3. `provision-indri --tags heph,caddy` from this branch.
4. Point gilbert at the hub + `heph auth login`.

## Known follow-ups (heph-side, tracked in the Hephaestus project)
- `heph daemon` can't bake hub/spoke config or pass `--self-update-interval-secs` → worked around by the ansible plist.
- Path-A seeding lacks a clean `hephd --owner-id`/seed command → manual `meta.origin` reset for now.
- Self-update moves hephd ahead of the ansible-pinned PWA shell over time (drift; tolerated by the SW cache, revisit on next release).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: #369
2026-06-05 06:46:58 -07:00

1.9 KiB

title modified last-reviewed tags
Indri 2026-05-27 2026-05-27
infrastructure
host

Indri

Primary BlumeOps server. Mac Mini M1 (2020).

Specifications

Property Value
Model Mac mini M1, 2020 (Macmini9,1)
CPU / RAM 8 cores / 16 GB
Storage 2TB internal SSD
macOS 15.7.3 (Sequoia)
Tailscale hostname indri.tail8d86e.ts.net
Tailscale Tag tag:homelab
Power [[power

Services Hosted

Native (via Ansible):

  • forgejo - Git forge
  • zot - Container registry
  • jellyfin - Media server
  • borgmatic - Backup system
  • alloy - Metrics/logs collector
  • caddy - Reverse proxy for *.ops.eblu.me
  • devpi - PyPI mirror (LaunchAgent)
  • hephaestus - heph task/context sync hub (LaunchAgent, self-updating)
  • cv - Static CV site, served by Caddy
  • docs - Quartz-built docs site, served by Caddy

Kubernetes (via minikube):

  • apps. A growing set of apps (Authentik, Frigate, ntfy, Immich, Homepage, Shower, Kingfisher, alloy-ringtail) now run on ringtail's k3s instead. Long-term plan is to decommission indri's minikube entirely.

GUI Applications (manual start required):

  • Docker Desktop - Container runtime for minikube
  • Amphetamine - Prevents sleep
  • automounter - Mounts sifaka SMB shares

Maintenance Notes

Sleep prevention: Uses Amphetamine (App Store) to prevent sleep. If Amphetamine crashes after extended uptime, consider switching to pmset or caffeinate via ansible.

Passwordless sudo: Configured for erichblume user (/etc/sudoers.d/erichblume) to allow ansible become: true without prompts. Acceptable given Tailscale is the trust boundary.