Goal: run famstack on a Mac safely. Install, lifecycle, troubleshoot, back up. No code changes from this role - that is the engineer role (see dev.md).
For full prose, see ../admin-guide.md. This file is the compact decision layer; the admin guide is the manual.
stack.toml(per-host config) + each stacklet'sstacklet.toml→ render.envon everystack up..envis derived, never edit it.- Every stacklet lives under
stacklets/<id>/. All persistent data lives under~/famstack-data/<id>/. No exceptions. - State is derived, not stored. Container existence == "running"; container absence + data dir absence == "available". There is no enabled-list.
- macOS on Apple Silicon (M1+).
- 16 GB RAM minimum; 32 GB recommended (AI quality, especially non-English).
- Homebrew installed. It is the only manual dep - it pulls everything else.
- OrbStack (preferred) or Docker Desktop running.
If a precondition is missing, ./stack prints exactly what to do. Don't improvise.
| Command | Idempotent | Destructive | Touches |
|---|---|---|---|
./stack |
yes | no | interactive installer (first-run path) |
./stack up <id> |
yes | no | starts containers, renders .env, runs hooks |
./stack down <id> |
yes | no | stops containers; data preserved |
./stack down all |
yes | no | stops every running stacklet in reverse dep order |
./stack restart <id> |
yes | no | down + up |
./stack destroy <id> |
yes | YES | removes containers + ~/famstack-data/<id>/ + secrets |
./stack uninstall |
yes | YES, EVERYTHING | destroys every stacklet, network, all data, config |
./stack list |
yes | no | reports state |
./stack status |
yes | no | runs health checks |
./stack logs <id> |
yes | no | tail container logs |
./stack errors |
yes | no | recent error logs (24h) |
./stack host |
yes | no | disk / memory / uptime |
./stack updates |
yes | no | checks for newer Docker images |
./stack config [--secrets] |
yes | no | prints resolved config |
./stack ai models |
yes | no | lists installed AI models |
./stack setup ai |
yes | no | re-runs AI install (model swap path) |
Output contract: every command returns JSON when piped or when --json is passed. Force human output with --pretty. Exit code 0 == success.
Applying config/compose changes to a running stacklet: stack up <id> is the apply command — it re-renders .env and compose up creates new services and recreates changed ones, leaving the rest running. restart (= down + up) also works but takes the whole stacklet down first. Plain docker compose restart does neither: it won't re-render env or create new services.
stack upis always safe to re-run. Failures leave the system in a valid intermediate state; re-running picks up where it failed..envis a derived artifact. Never edit by hand. Overwritten on everystack up..stack/secrets.tomlis gitignored and contains generated passwords + tokens. Treat as a password export.- Data lives outside the repo at
~/famstack-data/<id>/. That's the only mandatory backup. ~/.omlx/models/holds LLM model files. Re-downloadable; not indata_dir.- Two famstack instances cannot run on the same Mac at the same time - container names collide (
stack-<id>).stack downthe active one first.
Refuse without explicit, scoped human approval:
| Action | Why |
|---|---|
./stack destroy <id> |
Deletes ~/famstack-data/<id>/ permanently. No undo. |
./stack uninstall |
Wipes every stacklet's data, secrets, runtime state, and config. |
rm -rf ~/famstack-data/... |
Bypasses the CLI's safety prompts. |
Editing .env directly |
Will be silently overwritten next stack up. |
Editing .stack/secrets.toml |
Breaks every stacklet that depends on the changed secret. |
Moving data_dir while stacklets are running |
Bind mounts break. stack down all first, then move, then stack up. |
Changing stack.toml [core] language |
Re-seeds Paperless taxonomy. Orphan tags require manual cleanup. |
Switching [core] domain empty ↔ non-empty |
Switches port mode ↔ domain mode. Requires wildcard DNS + Caddy understanding. |
| Port | Stacklet | Service |
|---|---|---|
| 42010 | photos | Immich web + API |
| 42020 | docs | Paperless-ngx |
| 42030 | messages | Element web |
| 42031 | messages | Synapse (Matrix homeserver - phones connect here) |
| 42040 | code | Forgejo web |
| 222 | code | Forgejo SSH (macOS uses 22 itself) |
| 42050 | chatai | Open WebUI |
| 42060 | ai | oMLX |
| 42062 | ai | Whisper |
| 42070 | memory | Family wiki (Quartz) |
Port collisions: do not silently rebind. Surface them. The user's fix is "stop the offender" or switch to domain mode.
| Symptom | First check | Likely cause |
|---|---|---|
| "Docker is not running" | OrbStack/Docker Desktop icon present? | App not started. |
| "Port 42xxx already in use" | lsof -nP -iTCP:<port> -sTCP:LISTEN |
Another service grabbed it. |
| Phone can't reach server | Same Wi-Fi? Guest network isolating clients? | Network isolation. |
| "Server not Matrix" on phone | ./stack status → messages |
Synapse down. ./stack restart messages. |
| Mac IP keeps changing | Router DHCP behaviour | Set DHCP reservation on the router. |
| AI install fails at whisper.cpp build | xcode-select -p |
Xcode CLT missing. xcode-select --install. |
brew: command not found after install |
PATH on Apple Silicon | Add eval "$(/opt/homebrew/bin/brew shellenv)" to ~/.zshrc. |
| LLM OOM / very slow | RAM tier | Edit [ai] default to smaller model, then ./stack setup ai. |
| Disk full | ./stack host |
Likely the photo library. Move data_dir to external SSD. |
| Element warns "browser not supported" | n/a | Click Continue. The check is outdated; Element works in every modern browser. |
| Wiki pages stale after filings | docker logs stack-memory-curator |
Curator debounces (~3 min quiet) before rebuilding; topic pages wait for the nightly sweep. Manual override: ./stack memory wiki. |
| Wiki shows old content entirely | docker logs stack-memory-curator |
The curator owns the vault git pull (the wiki container is a read-only view). Curator down/stuck → vault and wiki go stale together. |
| Curator logs "waiting for vault" | ./stack status → memory, code |
Vault not cloned yet — the memory install hooks own the initial clone. |
For symptoms not on this table: ./stack logs <id> + ./stack errors, paste output to the user. Do not invent fixes.
~/famstack-data/- mandatory. Time Machine, restic, or rsync. Pick one.stack.toml,users.toml,.stack/secrets.toml- small, irreplaceable, gitignored. One-liner:tar czf famstack-config-$(date +%F).tgz stack.toml users.toml .stack/~/.omlx/models/- re-downloadable; skip.
This role describes operating an existing famstack install. Do NOT, from the operator role:
- Edit code in
stacklets/,lib/, ortests/. That's the engineer role; see dev.md. - Create or merge PRs.
- Run
./stack uninstallto "start fresh" without explicit user approval. - Suggest exact config strings (URLs, ports, IPs, field names) from memory. Verify against
stack.toml, the user guide, or./stack config.
When in doubt: ./stack status and ask.