Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,25 @@ on fixable CRITICALs if you ever want a gate.
Renovate already keeps the digest pins moving, so the usual fix for a finding
is to let it bump the image, not to hand-edit a tag.

## Agent tooling

`.claude/` is checked in, so every agent working here starts from the same
setup:

- **`agents/stack-consistency-reviewer.md`** — reviews a diff for convention
drift across the stacks. With this many near-identical Compose files, drift is
the failure mode, not bugs.
- **`skills/new-stack/`** — scaffolds a stack and its central backup wiring from
`templates/`. It carries `disable-model-invocation: true`, so it runs only
when a person asks for it by name.
- **`skills/backup-preflight/`** — the bind-mount path preflight, before
deploying a backup change.
- **Hooks** (`settings.json`): a PreToolUse hook refuses to edit a real `.env` —
those are gitignored, so the edit would be invisible and unshippable; edit the
`.env.example` instead. A PostToolUse hook runs
`hooks/validate-compose.sh` on whatever was just written, so a broken Compose
file surfaces at the edit rather than at `make check`.

## Compose stack conventions

- Each application stack lives in its own directory under `eggenberg-services/<stack>/`.
Expand Down
58 changes: 57 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
# docker-stack

Services live in separate Compose stacks under `eggenberg-services/`.
Services live in separate Compose stacks under `eggenberg-services/`, deployed
to TrueNAS through Dockhand. Central backups live in `infrastructure/`.

There is no build step and no application code here — the whole repository is
Compose files, `.env.example` files and the scripts that check them.

## Getting started

```bash
make tools # install the pinned toolchain from mise.toml
make hooks # install the git pre-commit hooks, once
make check # what a PR needs: hooks + compose config + conventions
```

`make help` lists every target. Day to day: `make stacks` lists them,
`make config STACK=jellyfin` prints a stack's fully resolved Compose config,
and `make up|down|restart|pull|logs STACK=<name>` operate on one.

**Tool versions live in `mise.toml` and nowhere else**, and CI installs from the
same file — so a hook that passes locally passes in CI.

## Services

Expand Down Expand Up @@ -50,3 +69,40 @@ Before deploying backup changes, run `infrastructure/volume-backup/check-backup-
- Add a dedicated `<stack>_backup` service to `infrastructure/volume-backup/docker-compose.yaml` that mounts the stack directory read-only under `/backup/<stack>_stack` and writes archives to `${BACKUP_ROOT}/<stack>/`
- Add `<STACK>_STACK_HOST_PATH` to `infrastructure/volume-backup/backup.env.example`
- Define an explicit default network named `<stack>_network`, replacing hyphens with underscores

## Checks

`make check` is the whole local gate, and it is what a pull request runs:

| Step | What it catches |
| --- | --- |
| `make lint` | yamlfmt, shellcheck/shfmt, gitleaks, and `actionlint` + `zizmor` over the workflows |
| `make validate` | `docker compose config` per stack — an interpolation or schema error before it reaches the host |
| `make conventions` | `scripts/check-stack-conventions.sh`: the `<stack>_network` naming rule and `.env.example` coverage for every variable a Compose file reads |

`.env.example` coverage is the one worth calling out: a variable referenced in a
Compose file but missing from `.env.example` deploys fine on the host that
already has it set and fails for everyone else. The check exists because that
happened.

One required check gates a merge: **`pre-commit`**. The image CVE sweep
(`scan.yml`) is deliberately not required — it is path-filtered and advisory,
and a required check that does not run on every pull request blocks the merge
for good. It runs weekly and answers "which of my services is currently
exposed"; a new upstream CVE in somebody else's image is not something a commit
here can fix. `make scan` runs the same sweep locally, `make scan-strict` fails
on fixable criticals.

## Agent tooling

`.claude/` is checked in: a `stack-consistency-reviewer` agent for diffs, a
`new-stack` skill that scaffolds all five pieces listed above from templates, a
`backup-preflight` skill, and two hooks — one refuses to edit a real `.env`
(they are gitignored, so the edit would be invisible), the other validates a
Compose file as soon as it is written. [`AGENTS.md`](AGENTS.md) is the detailed
guide.

## License and security

MIT ([`LICENSE`](LICENSE)). To report a vulnerability, see
[`SECURITY.md`](SECURITY.md) — please do not open a public issue for one.