Files
command-center/agent/managed-skills/compose-stack-bringup-groundtruth/SKILL.md
T
Frank 9bfa0be85d chore(skills): promote runbook skills to managed-skills; drop superseded SKILL.md
- 31 new managed skills (anubis/arr/authentik/hermes/freetoken/podman/llm-swap
  runbooks etc.) now tracked.
- Removed superseded skills: omp_harness_config, peon_ping_integration
  (replaced by user-authored peon-ping-* managed skills),
  rocmfp4-strix-benchmark-orchestration.
- New memory-root skills: niri_compositor_ops, omp_git_workflow,
  omp_model_config, quadlet-media-migration, homelab-service-triage,
  hermes-dankclaw-ops, frank-default-large-ops, caddy-auth-dns-playbook.
2026-09-09 16:20:28 -07:00

3.7 KiB

name, description
name description
compose-stack-bringup-groundtruth Bring up a compose-defined container stack on a rootless podman host by verifying reality first (mounts, images, in-image interfaces) instead of trusting compose env/flag guesses; includes the copyparty ac-edition argv-interface recipe and boot-persistence audit.

Compose-stack bring-up with ground truth (rootless podman hosts)

Use when standing up (or debugging) a compose-defined service stack on a rootless podman host where the stack has never run, or answers with surprise statuses (SIGSEGV at boot, HTTP 500 on /, "manifest unknown").

Procedure

  1. Audit reality before pressing buttons. podman ps -a runs per-user — check every namespace (sudo podman ps -a) and native units (systemctl list-units) before declaring a service absent; a service may run as a native systemd unit or snap, not a container. Compare compose mount source paths against the real filesystem (ls /mnt/...): compose files often name phantom paths that never existed (e.g. /mnt/media/* vs the real LUKS array at /mnt/entropy). Fix compose through git first, deploy second.

  2. Pre-create bind-mount sources. Rootless podman fails container creation with statfs /opt/<svc>/...: no such file or directory when a bind source is missing. sudo mkdir -p + chown 1000:1000 every compose volume source before the first podman-compose up -d.

  3. Staged bring-up. Infra first (up -d mariadb redis), poll healthchecks via podman inspect --format "{{.State.Health.Status}}", then up -d the rest.

  4. Never guess image tags — query ground truth. ghcr.io answers 403 on the bearer-token request for nonexistent/private repos ("manifest unknown" / token len 0 = repo or tag does not exist, not an auth problem). Query the registry API (ghcr.io/token?scope=repository:<ns>/<repo>:pull then /v2/<ns>/<repo>/tags/list) before pinning a tag.

  5. Read the interface from inside the image before guessing flags/envs: podman exec <ctr> cat /z/cpp.sh, cat /z/initcfg, podman exec <ctr> python3 -m copyparty --help-accounts. A service answering HTTP 500 with its own styled error page is running — it is misconfigured, not down. Copyparty ac edition ground truth: entrypoint /bin/ash /z/cpp.sh -c /z/initcfg then exec python3 -m copyparty "$@"; accounts/volumes are argv flags (-a USER:PASS, -v SRC:DST:PERMS), not COPAY_* envs (zero COPAY_ references in the package). With no accounts and no volumes configured it serves cwd read/write for everyone — an unauthenticated world-writable share of the whole mount.

  6. Beware remote-shell quoting traps. Remote zsh eats bare ===/? tokens (glob qualifiers/globs); grep patterns with nested quotes over ssh can be quote-eaten into silent zero-match. A zero-match from a mangled pattern is not absence — re-verify the target exists before concluding it.

  7. Boot-persistence audit last. On rootless podman hosts with podman-user-generator, containers started via podman-compose get generated container-<name>.service units at first boot (evidence: an existing unit for one container proves the generator works). Verify after first reboot: systemctl --user is-enabled <name>.service.

Gotchas

  • jellyfinetype SIGSEGV at boot with user: "1000:1000" = unmapped uid inside the rootless userns (host uid 1000 == container uid 0); drop the user line and let it run as container-root (= host deploy user).
  • up -d --force-recreate applies compose changes that change command/env; probe with a poll loop (for i in $(seq...)) because fresh containers answer 000/refused for the first seconds while indexing.