Skip to content

Instantly share code, notes, and snippets.

@phaer
Created August 8, 2026 14:19
Show Gist options
  • Select an option

  • Save phaer/e2c801a3355a27c048193421ea58637f to your computer and use it in GitHub Desktop.

Select an option

Save phaer/e2c801a3355a27c048193421ea58637f to your computer and use it in GitHub Desktop.
nix 2.34.8: print cgroups and allow opting in into cgroup-controllers = memory io pids cpu
diff --git a/src/libstore/build/derivation-building-goal.cc b/src/libstore/build/derivation-building-goal.cc
index 60ca549..cf7df7b 100644
--- a/src/libstore/build/derivation-building-goal.cc
+++ b/src/libstore/build/derivation-building-goal.cc
@@ -796,24 +796,27 @@ Goal::Co DerivationBuildingGoal::buildLocally(
auto closeLogFile = [&]() { logFile.reset(); };
+ std::unique_ptr<Activity> actLock;
+ DerivationBuilderUnique builder;
+ Descriptor builderOut;
+
auto started = [&]() {
auto msg =
fmt(buildMode == bmRepair ? "repairing outputs of '%s'"
: buildMode == bmCheck ? "checking outputs of '%s'"
: "building '%s'",
worker.store.printStorePath(drvPath));
+ Logger::Fields fields{worker.store.printStorePath(drvPath), "", 1, 1};
+ if (auto cgroupPath = builder->getCgroupPath())
+ fields.emplace_back(cgroupPath->native());
buildLog = std::make_unique<BuildLog>(
worker.settings.logLines,
std::make_unique<Activity>(
- *logger, lvlInfo, actBuild, msg, Logger::Fields{worker.store.printStorePath(drvPath), "", 1, 1}));
+ *logger, lvlInfo, actBuild, msg, std::move(fields)));
mcRunningBuilds = std::make_unique<MaintainCount<uint64_t>>(worker.runningBuilds);
worker.updateProgress();
};
- std::unique_ptr<Activity> actLock;
- DerivationBuilderUnique builder;
- Descriptor builderOut;
-
// Will continue here while waiting for a build user below
while (true) {
diff --git a/src/libstore/include/nix/store/build/derivation-builder.hh b/src/libstore/include/nix/store/build/derivation-builder.hh
index f521c04..d7fa6ce 100644
--- a/src/libstore/include/nix/store/build/derivation-builder.hh
+++ b/src/libstore/include/nix/store/build/derivation-builder.hh
@@ -181,6 +181,19 @@ struct DerivationBuilder : RestrictionContext
* killed.
*/
virtual bool killChild() = 0;
+
+ /**
+ * Return the cgroup path for this build, if any.
+ *
+ * On Linux with the \`cgroups\` experimental feature enabled, each
+ * build runs in its own cgroup. Exposing the path allows CI
+ * systems to poll live resource usage (memory, CPU, I/O) from
+ * the cgroup filesystem while the build is running.
+ */
+ virtual std::optional<std::filesystem::path> getCgroupPath() const
+ {
+ return std::nullopt;
+ }
};
/**
diff --git a/src/libstore/include/nix/store/local-settings.hh b/src/libstore/include/nix/store/local-settings.hh
index af7eccd..c4957e4 100644
--- a/src/libstore/include/nix/store/local-settings.hh
+++ b/src/libstore/include/nix/store/local-settings.hh
@@ -331,6 +331,34 @@ struct LocalSettings : public virtual Config, public GCSettings, public AutoAllo
Cgroups are required and enabled automatically for derivations
that require the `uid-range` system feature.
)"};
+
+ Setting<StringSet> cgroupControllers{
+ this,
+ {},
+ "cgroup-controllers",
+ R"(
+ A set of cgroup v2 controllers to enable on the build cgroup
+ subtree. When non-empty, the daemon moves itself into a
+ child cgroup at startup and writes the requested controllers
+ to `cgroup.subtree_control` on the root cgroup so that
+ per-build cgroups expose resource accounting files
+ (e.g. `memory.current`, `io.stat`).
+
+ Useful for CI systems that want to track per-build memory,
+ CPU, or IO usage. Requires `use-cgroups = true` and
+ `Delegate=true` (or a list of controllers) on the
+ `nix-daemon.service` systemd unit.
+
+ Valid controllers include `memory`, `io`, `pids`, and `cpu`.
+ Example:
+
+ ```
+ cgroup-controllers = memory io pids
+ ```
+
+ An empty set (the default) disables controller management
+ and preserves the previous behaviour.
+ )"};
#endif
Setting<bool> impersonateLinux26{
diff --git a/src/libstore/unix/build/linux-derivation-builder.cc b/src/libstore/unix/build/linux-derivation-builder.cc
index 476baab..b84fdfc 100644
--- a/src/libstore/unix/build/linux-derivation-builder.cc
+++ b/src/libstore/unix/build/linux-derivation-builder.cc
@@ -833,6 +833,11 @@ struct ChrootLinuxDerivationBuilder : ChrootDerivationBuilder, LinuxDerivationBu
DerivationBuilderImpl::killSandbox(getStats);
}
+ std::optional<std::filesystem::path> getCgroupPath() const override
+ {
+ return cgroup;
+ }
+
void addDependencyImpl(const StorePath & path) override
{
auto [source, target] = ChrootDerivationBuilder::addDependencyPrep(path);
diff --git a/src/nix/unix/daemon.cc b/src/nix/unix/daemon.cc
index 5b41d42..0c47276 100644
--- a/src/nix/unix/daemon.cc
+++ b/src/nix/unix/daemon.cc
@@ -292,6 +292,22 @@ static void daemonLoop(ref<const StoreConfig> storeConfig, std::optional<Trusted
throw SysError("creating cgroup '%s'", daemonCgroupPath);
// Move daemon into the new cgroup.
writeFile(daemonCgroupPath + "/cgroup.procs", fmt("%d", getpid()));
+
+ // Enable resource controllers requested via cgroup-controllers.
+ // The root cgroup is now empty (daemon moved to nix-daemon/),
+ // so writing to subtree_control is permitted by cgroup v2.
+ auto controllers = settings.getLocalSettings().cgroupControllers.get();
+ if (!controllers.empty()) {
+ std::string val;
+ for (auto & c : controllers)
+ val += "+" + c + " ";
+ try {
+ writeFile(rootCgroupPath / "cgroup.subtree_control", val);
+ } catch (SysError &) {
+ warn("could not enable cgroup controllers '%s' on %s (is Delegate=true set on the nix-daemon unit?)",
+ val, PathFmt(rootCgroupPath));
+ }
+ }
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment