Skip to content

Support garbage collection in external daemon#15143

Merged
Ericson2314 merged 1 commit intoNixOS:masterfrom
obsidiansystems:rootless-daemon-minimal
Feb 17, 2026
Merged

Support garbage collection in external daemon#15143
Ericson2314 merged 1 commit intoNixOS:masterfrom
obsidiansystems:rootless-daemon-minimal

Conversation

@artemist
Copy link
Member

@artemist artemist commented Feb 4, 2026

Motivation

Some users may want to run the nix daemon as an unprivileged user, reducing the risk of compromise to their system if the nix daemon is exploited. While there are workarounds for many of the issues faced while running an unprivileged nix daemon, programs need root (or the equivalent CAP_SYS_PTRACE) to find the list of runtime garbage collector roots.

With this PR, users can run the minimal garbage-collector roots daemon as root, then the rest of the nix daemon as an unprivileged user, in order to not sacrifice functionality.

Note from @Ericson2314: The key result from this PR is that fewer GC functional tets are failing within the hydraJobs.tests.functional_unprivileged-daemon NixOS VM test than before.

Context

This replaces the more invasive #15026. The protocol and implementation in this PR were made as simple and non-invasive as possible: roots are sent from the daemon on connection, separated by null bytes. Existing code was reused wherever possible.


Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

@github-actions github-actions bot added documentation new-cli Relating to the "nix" command labels Feb 4, 2026
@artemist artemist force-pushed the rootless-daemon-minimal branch from e764a10 to 5fe89d4 Compare February 4, 2026 16:57
@artemist artemist force-pushed the rootless-daemon-minimal branch 2 times, most recently from 888a478 to b3efe29 Compare February 4, 2026 19:35
@artemist artemist force-pushed the rootless-daemon-minimal branch from b3efe29 to ab555f2 Compare February 4, 2026 20:26
@artemist artemist force-pushed the rootless-daemon-minimal branch 2 times, most recently from 53e8836 to 44ad62e Compare February 4, 2026 21:45
@github-actions github-actions bot added the store Issues and pull requests concerning the Nix store label Feb 4, 2026
@artemist artemist force-pushed the rootless-daemon-minimal branch 2 times, most recently from 5dfc791 to f3ac1b3 Compare February 6, 2026 18:08
@Ericson2314 Ericson2314 force-pushed the rootless-daemon-minimal branch from f3ac1b3 to 8df59e4 Compare February 6, 2026 20:23

std::filesystem::path LocalStoreConfig::getRootsSocketPath() const
{
return std::filesystem::path(stateDir.get()) / "gc-roots-socket" / "socket";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it to match daemon-socket/socket for the original daemon, but frankly, it's a weird path and I don't know if we rather do something else instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree it's a weird path and would not be against changing it. I'm not sure what 's good though.

@Ericson2314 Ericson2314 force-pushed the rootless-daemon-minimal branch from 8df59e4 to c2bef2d Compare February 9, 2026 20:33
@amaanq amaanq force-pushed the rootless-daemon-minimal branch 4 times, most recently from e570237 to c44f623 Compare February 10, 2026 17:07
@artemist artemist force-pushed the rootless-daemon-minimal branch from c44f623 to d47ef14 Compare February 12, 2026 14:18
Copy link
Contributor

@xokdvium xokdvium left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably document the "protocol" somewhere. Not sure it's a blocker though.

@Ericson2314 Ericson2314 force-pushed the rootless-daemon-minimal branch from d47ef14 to f7aee9a Compare February 16, 2026 20:31
@Ericson2314 Ericson2314 force-pushed the rootless-daemon-minimal branch from f7aee9a to 77fafa8 Compare February 16, 2026 20:50
@Ericson2314 Ericson2314 force-pushed the rootless-daemon-minimal branch from db84efb to 6c02f9d Compare February 16, 2026 20:54
Copy link
Contributor

@xokdvium xokdvium left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM, modulo the release note.

@artemist artemist force-pushed the rootless-daemon-minimal branch from 6c02f9d to 0249c0b Compare February 17, 2026 15:13
This comes in two parts: a `nix store roots-daemon` command that
can run as root and list runtime roots,
and client logic to find runtime roots for a `LocalStore` by connecting
to that daemon.

This may be useful with an unprivileged nix daemon, as it would
otherwise be unable to find runtime roots from process open files
and maps.
@artemist artemist force-pushed the rootless-daemon-minimal branch from 0249c0b to 96fef69 Compare February 17, 2026 15:42
@artemist
Copy link
Member Author

The actual integration test for this, in the hydraJobs.tests.functional_unprivileged-daemon VM test, does not in CI. However, it does function locally in my testing.

Copy link
Contributor

@xokdvium xokdvium left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, threading solution seems much better to me.

@Ericson2314 Ericson2314 added this pull request to the merge queue Feb 17, 2026
Merged via the queue into NixOS:master with commit 6e72509 Feb 17, 2026
14 checks passed
@Ericson2314 Ericson2314 deleted the rootless-daemon-minimal branch February 17, 2026 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation new-cli Relating to the "nix" command store Issues and pull requests concerning the Nix store

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants