diff --git a/nix/agent-modules/default.nix b/nix/agent-modules/default.nix index 3bdbcc56..e84e51cc 100644 --- a/nix/agent-modules/default.nix +++ b/nix/agent-modules/default.nix @@ -131,6 +131,22 @@ # that bypasses the daemon (e.g. direct nix-store invocations). nix.settings.sandbox-fallback = lib.mkForce true; + # Fall back to a local build when a remote builder can't be reached, + # instead of hard-failing the whole invocation. + # + # This is NOT redundant with the host daemon's own setting, and that + # is the subtle part: `fallback` (protocol `tryFallback`) is a *client* + # option. Every nix client transmits it to the daemon on connect, so + # the client — i.e. this container — decides whether a failed remote + # dispatch may degrade to a local build, even though the build itself + # executes on the host daemon under NIX_REMOTE=daemon below. Contrast + # `builders`, which is genuinely daemon-side and which an untrusted + # client cannot override. Without this, a container inherits nix's + # default `false`, so a momentarily unreachable remote builder kills + # the invocation while the exact same build started on the host + # succeeds. + nix.settings.fallback = true; + # Route ALL nix invocations in this container through the host # nix-daemon socket, regardless of whether the caller is root or # non-root. Without this, root contexts (PID 1, systemd services diff --git a/nix/host-modules/hive-ci.nix b/nix/host-modules/hive-ci.nix index dcce7244..cd8e3a34 100644 --- a/nix/host-modules/hive-ci.nix +++ b/nix/host-modules/hive-ci.nix @@ -205,8 +205,9 @@ in # Route the container's nix through the HOST nix-daemon (as the agent # containers do) instead of an in-container daemon: with # NIX_REMOTE=daemon below, builds run on the host daemon and inherit - # its buildMachines + max-jobs + fallback, so a remote builder that's - # down degrades to a local build instead of hard-failing the check. + # its buildMachines + max-jobs. Note that `fallback` is NOT inherited + # that way — it's a client-side option transmitted per connection, so + # the container sets it itself (see nix.settings.fallback below). # Bind the *directory* (not the socket file) so the mount stays live # across a host nix-daemon restart, which recreates the socket inode. "/nix/var/nix/daemon-socket" = { @@ -252,6 +253,13 @@ in # through the host daemon (the daemon governs sandboxing). # See docs/gotchas.md and harness-base.nix. nix.settings.sandbox-fallback = lib.mkForce true; + # Degrade to a local build when a remote builder is unreachable + # rather than failing the check. `fallback` is a client-side + # option (transmitted per daemon connection), so routing through + # the host daemon does NOT inherit the host's value — the + # container has to set it. Same reasoning as the agent + # containers; see nix/agent-modules/default.nix. + nix.settings.fallback = true; nix.settings.experimental-features = [ "nix-command" "flakes"