Files
serverAppConfigs/serverAppConfigs-docs/Architecture/Service Inventory.md
T
Frank 65bd5ccea7 feat(rank6): node-exporter renders from a template; guard chain is one snippet
- service-map render node-exporter-unit --host H: the MIRROR pair comment
  ('keep this file in step') becomes a template. Per-host title, LAN
  address from the hosts map, port from the node-<host> scrape job. Both
  tracked quadlets are now rendered artifacts; check_drift gates them.
- dankclaw/Caddyfile: the nine verbatim Anubis pre-auth chains
  (reverse_proxy anubis:8923 + X-Real-Ip) collapse into the (guarded)
  named snippet; guarded vhosts are 'import guarded'. Validated with real
  caddy 2.11.7 (import resolution clean; the stock image stops at the
  porkbun module and the git basicauth placeholder, as designed).
- vhost-scoped guard greps (authentik, homepage_caddy, marreta_quadlet)
  now pin 'import guarded' in the vhost block.
- Service Inventory + Authentik docs carry the new laws.
2026-10-13 22:40:50 -07:00

5.5 KiB
Raw Blame History

type, title, description, tags, timestamp
type title description tags timestamp
reference Service Inventory shared/services.yml is the one inventory of deployable services; scripts/service-map.py is its only reader. The planner, both deploy allow-lists, the changed-test seam mapper, the Pi-hole hosts render, the Prometheus scrape facts, and the homepage probes all derive from it.
deployment
inventory
planner
quadlet
prometheus
pihole
homepage
2026-10-13T00:00:00-07:00

Service Inventory

Before 2026-10-13 the same facts lived in four hand-maintained lists — the planner's path rules (deploy-plan.py), the --service allow-list in deploy.sh, the near-copy in deploy-remote.sh, and the changed-test mapper (test-changed.sh) — plus per-fact copies in prometheus.yml, addn-hosts, and services.json. They drifted on every swap (the planner still mapped the retired qwen-sharp template to frank-dragoon; the allow-list still listed the *arr stack under Dankserver after it moved to FrankBook-Pro). Now there is one inventory and one reader:

  • shared/services.yml — the data: every deployable service, its hosts, unit dir(s), unit files, path claims, tests, scrape/DNS/probe facts, aliases.
  • scripts/service-map.py — the only reader. CLI subcommands: hosts, services, allows, plan, seams, owner, units, stack, get, render, check.

1. Consumers

Consumer Call
scripts/deploy-plan.py thin wrapper → plan --host TARGET [paths...] (keeps the --repo/--base/--head and --paths CLIs)
scripts/deploy.sh (--service gate) allows --host T --service S
scripts/deploy-remote.sh (service_is_allowed) same
scripts/test-changed.sh seams [paths...] — a service's declared tests are its seams
dankclaw/pihole/addn-hosts render pihole-hosts — the tracked file is a rendered artifact
*/observability/quadlet/node-exporter.container render node-exporter-unit --host H — the MIRROR pair became one template; per-host title, LAN address (hosts map), and port (scrape job) fill it
Prometheus scrape jobs, LAN DNS, homepage probes check compares the tracked configs against the inventory's scrape/dns/probe fields (drift gate)

Selection rules the engine encodes (see tests/fixtures/service-plan-golden.tsv, the pinned characterization of every tracked path × every target):

  • Host scoping — a host's top-level directory can only select that host's services. frankbook-pro/** plans nothing on Dankserver (the old planner had a stale Dankserver *arr list).
  • Quadlet coupling graph — Network=x.container rides x's netns; Network=y.network joins a shared network. Changing the parent (or the network file) selects every rider transitively, in their own directories (dankclaw/searxng/quadlet/gluetun.container → gluetun + searxng + marreta; frankbook-pro/gluetun/quadlet/gluetun.container → the whole arr stack).
  • Stacks — a service's stack members deploy and restart as one handler (romm trio, hermes trio).
  • Retirement — removing a service from services.yml removes it from the planner, both allow-lists, and the seam mapper in one data edit; a pending deploy-state entry for it is auto-triaged (see Deploy State Triage).

2. Integrity gates (check)

python3 scripts/service-map.py check runs, and tests/service_inventory.bats pins:

  • schema — required fields per entry, known keys only;
  • units — every unit file named by an entry exists under its unit_dir on the right host; each unit name is claimed by exactly one service per host;
  • ownership — every tracked quadlet .container/.network file is claimed by exactly one service (trash excluded);
  • paths — every claimed files/dirs/retires glob matches ≥1 tracked file;
  • compose — the container names in each host's compose.yaml have exactly one quadlet owner (the Quadlet Lifecycle two-owners trap);
  • drift — addn-hosts equals its render, each tracked node-exporter unit equals its per-host render; the Prometheus job set, the DNS names, and the homepage probe ports equal the inventory's fields.

3. Adding, moving, retiring a service

  • Add: append an entry (name, hosts, kind, unit_dir, units, paths, tests, …), add the quadlet file, run check — plan/allows/seams pick it up with zero script edits.
  • Move between hosts: edit hosts (and per-host unit_dir/probe maps).
  • Retire: delete the entry, move files to .AGENTTRASH/ (see Testing Policy for the seam the mapper applies to trash paths).

Field notes: alias carries deployable names that differ from the service name (calibre-web deploys the unit calibre-server); probe for multi-host services is a {host: port} map; dependents names services whose config embeds a reference to this one (config-only coupling — a .env edit selects both, a unit edit selects the graph closure).

4. Known cutover deltas (2026-10-13)

The 17 deltas against the old planner are all in these classes: anubis paths now select anubis (the old planner had no rule at all); cross-host paths select nothing; scripts/qwen-sharp-v22.4.0.jinja (retired template) plans nothing while scripts/qwen38-froggeric-v22.5.jinja (the live frank-archon template, previously unmapped) plans frank-archon; dankserver/romm/romm.container (top-level quadlet dir the old unit-file rule missed) now plans the romm trio.


Related: Deployment Flow, Testing Policy, Quadlet Lifecycle, Container Network Namespaces, Deploy State Triage