Watch
0
0
Fork
You've already forked hyperhive
0

ci-runner: warn when the host has no nix store gc

This commit is contained in:
atlas 2026-11-11 18:16:54 +01:00 • committed by mara
commit 493d2e6c37
4 changed files with 47 additions and 3 deletions

View file

@ -314,8 +314,10 @@ CI day can fill the disk until every job fails fast with `ENOSPC`.
Store GC is a **host-level** concern, so it belongs in the host's own NixOS
configuration, not in the hyperhive service modules — a single service should
not reach out and change the host's global nix-daemon options. Add the
following to your host config:
not reach out and change the host's global nix-daemon options. The module
only warns at `nixos-rebuild` time when the host sets neither
`nix.gc.automatic` nor `nix.settings.min-free`. Add the following to your
host config:
```nix
{

View file

@ -32,6 +32,18 @@ in
];
};
# CI builds land in this host's store; the runner module warns without a
# collector. See docs/4-implementation/scheduler/ci.md, "Host store
# maintenance", for the daily timer and the disk-pressure settings.
nix.gc = {
automatic = true;
dates = "daily";
randomizedDelaySec = "45min";
options = "--delete-older-than 1d";
};
nix.settings.min-free = 20 * 1024 * 1024 * 1024;
nix.settings.max-free = 50 * 1024 * 1024 * 1024;
# The cache is served through the gateway, over the VPN only.
networking.firewall.interfaces.wg0.allowedTCPPorts = [ hyperhive.gateway.httpsPort ];
}

View file

@ -236,6 +236,17 @@ in
}
];
# The runner builds through the host's nix daemon, so its outputs fill the
# host's /nix/store. The host's nix settings are not this module's to set;
# it only tells the operator when neither collector is configured.
warnings = lib.optional (!config.nix.gc.automatic && (config.nix.settings.min-free or 0) == 0) ''
services.hyperhive.deploy.ci-runner.enable is on, but this host sets
neither nix.gc.automatic nor nix.settings.min-free. CI builds fill
/nix/store until the disk is full and every job fails with ENOSPC.
Add the GC settings from "Host store maintenance" in
docs/4-implementation/scheduler/ci.md to the host's NixOS config.
'';
# The container hangs off the bridge, takes its address from the
# gateway's DHCP and resolves through its dnsmasq. The gateway also runs
# `hive-tls-ca`, which writes the trust bundle bound in below.

View file

@ -24,6 +24,7 @@ let
;
})
hive
hiveWith
runGroup
selfScrapes
;
@ -56,7 +57,7 @@ let
# The runner alone: no hive, no forge, no store, its store identity placed
# by hand. `nix` is a label without a scheme.
ciAlone = hive {
ciAloneOpts = {
deploy.hive-controller.enable = false;
deploy.ci-runner.enable = true;
deploy.ci-runner.labels = [
@ -66,6 +67,13 @@ let
deploy.bao.ciRunnerClientCertFile = "/etc/pki/bao-ci-runner.pem";
deploy.bao.ciRunnerClientKeyFile = "/etc/pki/bao-ci-runner-key.pem";
};
ciAlone = hive ciAloneOpts;
# `ciAlone` with the host's store collection set, one way each.
ciGcTimer = hiveWith [ { nix.gc.automatic = true; } ] ciAloneOpts;
ciMinFree = hiveWith [ { nix.settings.min-free = 20 * 1024 * 1024 * 1024; } ] ciAloneOpts;
ciOffNoGc = hive { deploy.hive-controller.enable = false; };
ciGcWarned =
m: lib.any (lib.hasInfix "neither nix.gc.automatic nor nix.settings.min-free") m.warnings;
ciNoIdentity = hive {
deploy.hive-controller.enable = false;
deploy.ci-runner.enable = true;
@ -211,6 +219,17 @@ let
in
!(lib.any (n: lib.elem n (u.after ++ u.wants ++ u.requires)) storeUnits);
}
{
# The module only warns: the host's nix settings stay the host's. Each
# collector alone, and the runner being off, silence the warning.
name = "the CI runner warns when the host has neither nix.gc.automatic nor nix.settings.min-free";
ok =
ciGcWarned ciAlone
&& !(ciGcWarned ciGcTimer)
&& !(ciGcWarned ciMinFree)
&& !(ciGcWarned ciOffNoGc)
&& !ciAlone.nix.gc.automatic;
}
{
# Without the identity the token never arrives; the control is the
# placed pair above.