Watch
0
0
Fork
You've already forked hyperhive
0

add the agent option privateUsers, with the uid = gid assertion

This commit is contained in:
atlas 2026-11-01 16:05:36 +01:00 • committed by mara
commit 1fd591d28b

View file

@ -90,8 +90,47 @@ in
'';
};
options.services.hyperhive.agent.user.privateUsers = lib.mkOption {
type = lib.types.bool;
default = false;
example = true;
description = ''
Run this agent's container in its own user namespace. Off by default.
**Approving the config PR that sets this authorises a host-level
change.** The swarm builder reads the option from the evaluated config
into the agent's closure record, and the hive then starts the container
with `--private-users=pick`, every hive bind mounted `owneridmap`, and
its root idmapped. The first such start has `hive-priv`, as root, chown
the agent's `state`, `harness`, `work` and `claude` dirs once to the
host's data owner
(`services.hyperhive.deploy.hive-controller.userns.dataOwner`). Nothing is
deleted. Turning it off afterwards needs the dirs chowned back by hand.
Needs `user.uid` and `user.gid` set to the same number: nspawn maps a
bind's gids with its uid map, so a group of another number has no
mapping and writes fail. Start the agent once with the pin before
turning this on; `hive-priv` refuses to move a `state` dir whose gid
differs from its uid. An agent that holds `ManageRootAgent` should not
set it, since the other agents' dirs it mounts are not remapped.
'';
};
config = {
assertions = [
{
assertion =
!config.services.hyperhive.agent.user.privateUsers
|| (
config.services.hyperhive.agent.user.uid != null
&& config.services.hyperhive.agent.user.uid == config.services.hyperhive.agent.user.gid
);
message = ''
services.hyperhive.agent.user.privateUsers needs services.hyperhive.agent.user.uid
and services.hyperhive.agent.user.gid set to the same number: a user namespace
maps a bind's gids with its uid map, so a group of another number has no mapping.
'';
}
{
assertion =
config.services.hyperhive.agent.user.uid == null