Skip to content

Host-scoped Config

config.toml is fleet-wide by default: every key applies to every host. The reserved [hosts.<name>] table scopes keys to one host — for that host’s runs, its entries override the top level in preflight validation and in the variables passed to Ansible.

domain = "example.com"
headscale_subdomain = "hs"
blocky_subdomain = "dns"
[hosts.agent-box]
headscale_subdomain = "" # this host does not serve headscale
blocky_subdomain = "" # nor blocky
ssh_port = "2244" # nor the fleet's SSH port

<name> matches the host’s hosts.toml entry. Tables for names no host carries are inert.

infrastructure.yml gates headscale and blocky on their *_subdomain keys. A blank override makes the gate read unset for that host:

Run against agent-box Result
untagged infrastructure headscale and blocky skipped, everything else runs
-t headscale / -t blocky preflight fails naming the blanked key

Naming a gated role’s tag asserts it runs, so asking for it on a host that withdrew the key is an error, not a silent no-op.

An <app>_subdomain is the app’s record name in the fleet’s DNS zone — fleet identity, read by DNS discovery from the top level. Scope it per host only to withdraw the role (blank); give divergent values per host only for keys that are genuinely per-host (ports, <app>_tailscale_ip).

<app>_zone is the exception: it must be host-scoped, and preflight refuses it at the top level. A host’s zones decide which ACME tokens land on its Caddy. See Forgejo’s own DNS zone.

auberge headscale commands default to the one host whose config answers headscale_subdomain. While several hosts answer (a fleet-wide key and no blanks), you get the interactive picker — blank the gate on non-serving hosts to regain the non-interactive default.

  • A [hosts.<name>] table naming no known host fails preflight — a typo would otherwise silently hand the host every fleet-wide answer.
  • An override whose !command reference fails aborts the run instead of falling back to the fleet-wide value.
  • restic_* keys are read fleet-wide by backup push/verify/prune; scoping them per host is not supported.
  • auberge host rename moves the host’s table with it.

auberge config set hosts.<name>.<key> <value> writes one key into [hosts.<name>], creating the table if absent. auberge config remove hosts.<name>.<key> removes it, and drops the table once empty. auberge config get hosts.<name>.<key> reads the override alone, never the fleet-wide value behind it. Every other dotted name is refused, as is the bare hosts name. auberge config list shows host-scoped entries as hosts.<name>.<key> rows, secrets redacted.

Terminal window
auberge config set hosts.agent-box.headscale_subdomain ""

set and remove rewrite the whole file, dropping comments and key order. To keep them, edit the file instead: auberge config edit.