External Systems' artifact flake: pinned, source-built packages and source materials (charts, images, rendered manifests) for downstream flakes — primarily external-systems/clanServices — to consume via a locked flake input. This repo contains packaging only: no inventory, no clan vars, no fleet policy.
The consuming contract is defined by clanServices SPEC.md (D26 two-layer
rendering, D34 version policy, D40 Cilium lifecycle, D41 Node IPAM, §8 phase
2). Scope after the round-13 narrowing: only the distro runtimes (last 3
Kubernetes minors per distro), the IfState package overlay, the Cilium chart +
committed inflated manifest + airgap image set, the CoreDNS image (D46 uniform
clan-rendered CoreDNS), and the go-httpbin test fixture. Everything day-2
(Envoy Gateway, cert-manager, Flux, external-dns, Multus, Sealed Secrets) is
GitOps-owned (SPEC §3.3) and no longer carried here.
Outside that contract, the repo also builds the workstation and agent tooling
the fleet flakes (external-systems/home) used to build themselves: the
overlays.tools packages and the code-agent sandbox image (see below).
# Name the input org-pkgs, never pkgs (pkgs is the nixpkgs package set).
inputs.org-pkgs.url = "github:external-systems/pkgs/<immutable-rev>";- Packages —
packages.<system>.<name>for direct builds onx86_64-linuxandaarch64-linux:nix build github:external-systems/pkgs#rke2 - Overlays —
overlays.defaultcomposes the Kubernetes, IfState and tools overlays;overlays.kubernetes,overlays.ifstateandoverlays.toolsare also exported separately. Applying the default overlay gives you the pinned artifacts aspkgs.rke2/pkgs.k3s_1_36/pkgs.ifstate. The builder expressions come from the consumer's nixpkgs: rke2 needs any nixpkgs shippingpkgs/applications/networking/cluster/rke2/builder.nix(all version data is pinned locally inpkgs/rke2/versions/); k3s rides the consumer'sk3s_1_35/k3s_1_36/k3s_1_37builders, so consumer nixpkgs must ship those minors at the pinned patches. Following this flake'snixpkgsinput is the supported way to keep that contract aligned. - Artifact metadata —
lib.versions.matrixexposes the full last-3-minors matrix per distro (kubernetes,k3s,rke2, commits per minor);lib.versions.kubernetes/.k3s/.rke2are latest-minor aliases.lib.cilium.manifestis the committed base manifest,lib.cilium.imagePackageNameslists its per-system tarball outputs, andlib.coredns.imageRefis the digest-pinned CoreDNS reference.
The last 3 Kubernetes minors per distro, latest patch each, with per-minor
parity enforced by checks.k8s-version-parity-<minor>:
| minor | rke2 | k3s |
|---|---|---|
| 1.35 | v1.35.9+rke2r1 (source-built, local table) | v1.35.9+k3s1 (nixpkgs) |
| 1.36 | v1.36.5+rke2r1 (source-built, local table) | v1.36.5+k3s1 (nixpkgs) |
| 1.37 | v1.37.1+rke2r1 (source-built, local table) | v1.37.1+k3s1 (nixpkgs) |
packages.rke2 / packages.k3s alias the latest minor; per-minor attrs are
rke2_1_35 / k3s_1_35 / …. Release-tag pins only. rke2 ldflag component
versions come from each tag's own scripts/version.sh.
Support-window gate (D34): lib.versions emits an eval warning (never a
failure) when Cilium's upstream support matrix does not list a pinned k8s
minor. Today: no warnings — Cilium 1.20 supports 1.33–1.37.
The Cilium chart is rendered at update time with the canonical
fleet-uniform profile and committed as source under manifests/.
Consumers read the committed file (builtins.readFile / kubenix
importYAML); nothing in this repo's outputs requires a build at consumer
eval time — zero IFD downstream. Per-cluster variation is layer 2 (kubenix
module merging in clanServices), never re-run helm values here.
| Component | Artifacts |
|---|---|
manifests/cilium/1.20.3.yaml |
Cilium 1.20.3, canonical profile (pkgs/cilium/values.nix): KPR, native routing, multi-pool IPAM, auto-direct-node-routes off, Cilium iptables rules off, BPF masquerade+tproxy, Maglev, pmtu, dual-stack, clustermesh-apiserver, Gateway/Ingress off (D1) |
The committed manifest is guarded by checks.manifest-cilium-freshness: the
committed file must be byte-identical to a fresh render of the pin. This is
the artifact-side publish-freshness gate (D26/D40).
Every container image the committed Cilium manifest references is exported as
a digest-pinned docker-archive tarball (dockerTools.pullImage):
image-cilium-agent, image-cilium-envoy, image-cilium-operator,
image-cilium-clustermesh-apiserver, plus the aggregate
cilium-airgap-images directory for VM tests to preload. Each supported
system selects its matching amd64 or arm64 image and output hash.
checks.cilium-airgap-completeness enforces that the pinned set in
pkgs/cilium/versions.nix matches the manifest's image references exactly.
CoreDNS (SPEC D46): image-coredns — the digest-pinned upstream
registry.k8s.io/coredns/coredns tarball for the clan-rendered
cluster.local DNS.
Test fixture (SPEC §6): go-httpbin (source-built v2.26.0) +
image-go-httpbin.
nix run .#update-rke2 -- 1.35 # bump one rke2 minor to its latest patch:
# tag, commit, tarball hash, ldflags from the
# tag's scripts/version.sh, vendor-hash dance,
# verifying build — one atomic table rewrite
nix run .#update-manifests # re-render the committed manifest from the
# current pins; review with git diffCilium chart bumps: edit pkgs/cilium/versions.nix (new version + hash via
nix store prefetch-file --json <url>, refresh images from a fresh
render's image references), then nix run .#update-manifests. k3s bumps ride
nix flake update nixpkgs — verify the minors' patches still match upstream
latest afterwards, then run sync-locks in the same commit so
dev/flake.lock and devenv.yaml/devenv.lock follow (checks.lock-sync
enforces it).
Needs Nix and devenv. The shell is the devenv CLI (devenv.yaml imports the
org shell from ./devenv); apps, checks, the formatter, docs and slides live
in the dev flake-parts partition, whose inputs are locked separately in
dev/flake.lock. Consumers of packages, overlays or lib never fetch
them.
devenv allow # auto-activation (after `devenv hook`)
fmt # treefmt: alejandra, deadnix, nixf-diagnose,
# shellcheck, sizelint, statix
check # nix flake check: treefmt, lock-sync, docs and
# slides, per-minor k8s parity, manifest
# freshness, cilium airgap completeness
docs-build # static docs to ./result-docs (nix build
# .#documentation); open index.html from disk
devenv up # live docs :8981 and slides :8982git add new files before evaluating — Nix reads the git tree. This repo is
the organization's nixpkgs authority: downstream flakes follow pkgs/nixpkgs
so routine artifact and nixpkgs updates remain independent of consumer update
lifecycles. Every fetch is a fixed-output derivation from a public URL with a
committed hash; airgap image sets cover the committed Cilium manifest.
pkgs also carries what every external-systems repo builds on:
flakeModules.treefmt, flakeModules.dev, the org devenv shell (devenv/)
and templates.default. Start a repo with
nix flake init -t github:external-systems/pkgs. The full description is in
the docs site (documentation/docs/flake-standard.md) and the nix-style
skill (external-systems/skills).
overlays.tools (also in overlays.default, and as packages.<system>.*
where the platform is supported) carries the repo-built CLIs and agent
tooling. Each source is pinned in its own pkgs/<name>/package.nix, so the
overlay adds no flake input to consumers' locks.
| Package | What |
|---|---|
headroom, headroom-slim |
Context compression proxy + MCP server for AI agents (x86_64 wheel) |
kimi-code |
Moonshot's Kimi Code CLI, from source (ported from numtide/llm-agents.nix) |
artifacthub-mcp |
MCP server for Artifact Hub (Helm charts) |
kubernetes-mcp-server |
MCP server for Kubernetes and OpenShift |
longhornctl |
Longhorn CLI (release binary, x86_64) |
hcloud-ip |
Hetzner Cloud floating IP CLI (release binary, x86_64) |
claude-code, pi-coding-agent, tfctl, devenv, mcp-nixos and
github-mcp-server come straight from nixpkgs.
The OpenShell code-agent sandbox image (agent CLIs, nix, the skills tree from
external-systems/skills, home-manager-generated dotfiles) lives in the dev
partition (images/code-agent/), so its inputs (external-systems/modules,
which brings home-manager and skills) are locked only in dev/flake.lock.
nix build .#code-agent-image # streamed docker-archive script
nix run .#load-code-agent-image # docker load
nix run .#push-code-agent-image -- docker://ghcr.io/<org>/code-agent:<tag>