This is the central architectural concept of the attic-iac system: infrastructure that deploys and updates itself using itself.
Recursive dogfooding means that the tools, services, and pipelines produced by this project are consumed by the same project to build, test, and deploy subsequent versions of themselves. Each component participates in a feedback loop where it is both producer and consumer.
GitLab runners are deployed via tofu apply, which updates their
Kubernetes manifests (resource limits, runner tokens, image versions).
The tofu apply command runs inside a CI pipeline, which itself
executes on those same runners. When a runner configuration change
merges to main, the runners execute a pipeline that reconfigures
themselves.
The Attic binary cache server is built as a Nix derivation. That derivation is stored in the Attic cache. On subsequent builds, Nix fetches the cached closure from Attic rather than rebuilding from source. The cache accelerates the build of the very artifact that provides the cache.
The runner dashboard is a SvelteKit application deployed by the CI pipeline. Once running, it monitors the health and activity of the runners that deployed it. If a runner degrades, the dashboard surfaces that information, prompting a fix that the runners will then deploy.
The system converges over time. Each successful cycle improves the next:
main.The steady state is a system where builds are fast (high cache hit rate), runners are correctly configured (no drift), and operators have clear visibility into system health.
graph LR
R[Runners] -->|"tofu apply"| R
R -->|deploy| AC[Attic Cache]
AC -->|accelerates| NB[Nix Builds]
NB -->|"executed by"| R
R -->|deploy| D[Dashboard]
D -->|monitors| R
AC -->|"caches its own derivations"| AC
The self-referential nature creates a chicken-and-egg problem on first deployment. The system cannot deploy itself if it does not yet exist. The bootstrap sequence breaks the cycle:
tofu apply runs from a
developer workstation (or a temporary CI runner outside the cluster).
This creates the Kubernetes namespace, deploys the Attic cache with
an empty store, and registers the initial set of runners.main triggers a pipeline that runs on the newly created runners.
This pipeline redeploys the same infrastructure, but now through the
self-referential path.After bootstrap, the system is self-sustaining. No external CI infrastructure is needed.
The loops are loosely coupled through Kubernetes. If one component fails, the others continue:
tofu apply to recreate the runners.The system is designed so that total failure of all components simultaneously is unlikely. Partial failures are self-healing as long as at least one runner type remains operational.