Files
homelabstack/.claude/skills/homelab-apply/SKILL.md
T
ginnoir f995014d48 docs+ops: rewrite CLAUDE.md, skills, runner for post-split topology
Post-monolith documentation and ops cleanup:

- CLAUDE.md rewritten end-to-end. Documents the 11 Portainer-managed stacks
  + raw-compose management plane, the single shared `edge` network, the
  SSD-vs-ZFS bind-mount tiering, the four deployment channels (git push
  for app stacks, runner for Caddyfile, apply-compose.ps1 for mgmt plane /
  Caddyfile / vault), and the fact that the repo is now canonical.
- homelab-apply skill rewritten for the new channels — no more `dc up -d`,
  no more monolith.
- homelab-ssh skill rewritten — no `dc` alias, plain `docker` against
  container names; per-stack compose ops via /data/compose/<id>/...
- homelab-sync skill + sync-prod.ps1 retired. The repo is canonical now;
  pulling from prod is the wrong direction.
- .github/workflows/deploy.yml: drop the dc up -d steps, gate on
  paths:[Caddyfile, .github/workflows/deploy.yml], reload caddy via
  `docker exec` (no longer through compose).
- apply-compose.ps1: drop -Compose and -DevStack flags; -Caddy now reloads
  via `docker exec caddy` (Caddy is in its own Portainer stack now).

No live container is touched by this commit. The runner workflow is
currently disabled at the repo level; re-enabling it makes Caddyfile pushes
auto-deploy again.
2026-06-04 18:17:16 -05:00

3.3 KiB

name, description
name description
homelab-apply Deploy changes to the valhalla homelab. For application stacks (foundry, media, owncloud, etc.), commit and push — Portainer git-polls every 5 min. For the management plane (portainer, vault, watchtower, runner), Caddyfile, or .env on the server, use the apply-compose.ps1 helper. Use after editing any homelab config to get it deployed.

homelab-apply

The repo is canonical. Different config layers deploy through different channels:

Edit Deployment channel Lag
stacks/<domain>/docker-compose.yml or stacks/<domain>/.env git push → Portainer polls every 5 min and redeploys that stack up to 5 min
Caddyfile git push triggers .github/workflows/deploy.yml → runner pushes file + docker exec caddy caddy reload seconds (if workflow is enabled)
portainer-compose.yml (mgmt plane: portainer, vault, watchtower, runner) apply-compose.ps1 -Portainer — Portainer can't manage itself seconds
vault.hcl apply-compose.ps1 -Portainer (bundled with mgmt plane push) seconds
.env at ~/valhalla-lab/.env (only used by mgmt plane + vault unseal) apply-compose.ps1 -EnvFile seconds

For application stack edits — just push

git add stacks/media/.env
git commit -m "..."
git push

Portainer's per-stack auto-update will pick up the new commit within 5 minutes and redeploy. Watch progress:

ssh -o BatchMode=yes ginnoir@valhalla "docker compose -f /data/compose/<id>/stacks/<domain>/docker-compose.yml ps"

Or just docker ps and filter by name. To force an immediate redeploy without waiting, trigger it from the Portainer UI ("Update the stack").

For Caddyfile edits — push and wait for the runner

Workflow is gated by paths: [Caddyfile, .github/workflows/deploy.yml] so only Caddyfile commits trigger it.

If you don't want to wait (or the workflow is disabled), the manual fallback is:

powershell -File apply-compose.ps1 -Caddy

This scps the local Caddyfile to /config/caddy/Caddyfile and runs docker exec caddy caddy reload --config /etc/caddy/Caddyfile. Invalid Caddyfile → reload fails, old config keeps running; read the output.

For management-plane edits

powershell -File apply-compose.ps1 -Portainer    # portainer-compose.yml + vault.hcl + up -d
powershell -File apply-compose.ps1 -EnvFile      # ~/valhalla-lab/.env only
powershell -File apply-compose.ps1 -VaultUnseal  # unseal vault after restart (keys from .env)

No flags = -EnvFile + -Caddy (the two ad-hoc pushes you'd want for a quick manual deploy).

Verify after applying

ssh -o BatchMode=yes ginnoir@valhalla "docker ps --format 'table {{.Names}}\t{{.Status}}'"
ssh -o BatchMode=yes ginnoir@valhalla "docker logs --tail 50 <container>"

Notes

  • Compose is v2 (docker compose, space).
  • There is no monolithic dc alias anymore — each stack has its own compose dir under /data/compose/<id>/stacks/<domain>/. Address services by container name with docker logs, docker exec, etc. — docker compose ... only makes sense when you explicitly point at a per-stack compose file.
  • A GateGuard hook blocks the first Bash and every Write/Edit until you state the user request + what the operation does/affects. State them, retry.