Skip to content

Commit 6b216c2

Browse files
committed
Initial darwin-multi agent
1 parent 9a031b7 commit 6b216c2

2 files changed

Lines changed: 176 additions & 0 deletions

File tree

flake.nix

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,31 @@
194194
};
195195
};
196196

197+
darwinModules.multi-agent-service =
198+
{ lib, pkgs, ...}:
199+
{
200+
_file = "${toString ./flake.nix}#darwinModules.multi-agent-service";
201+
imports = [
202+
agentFromFlakeModule_multi
203+
./internal/nix/nix-darwin/multi.nix
204+
];
205+
206+
# This module replaces what's provided by nix-darwin
207+
disabledModules = [ "services/hercules-ci-agent" ];
208+
209+
options = let inherit (lib) types mkOption; in
210+
{
211+
services.hercules-ci-agents =
212+
mkOption {
213+
type = types.attrsOf (
214+
types.submoduleWith {
215+
modules = [{ config.settings.labels.module = "darwin-multi-service"; }];
216+
}
217+
);
218+
};
219+
};
220+
};
221+
197222
# A nix-darwin module with more defaults set for machines that serve as agents
198223
darwinModules.agent-profile =
199224
{ lib, pkgs, ... }:

internal/nix/nix-darwin/multi.nix

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# Module similar to (flake).agent-service or the NixOS-bundled module, but
2+
# supports running multiple instance of the agent, each with their own files,
3+
# user, etc.
4+
5+
systemArgs@{ pkgs, config, lib, ... }:
6+
let
7+
inherit (lib) mkIf mkDefault types mkOption;
8+
inherit (lib.strings) match;
9+
literalDocBook = lib.literalDocBook or lib.literalExample;
10+
literalExpression = lib.literalExpression or lib.literalExample;
11+
12+
submodule = { config, options, name, ... }:
13+
let
14+
inherit (import ../settings.nix { inherit pkgs lib; }) format makeSettingsOptions;
15+
configFile = format.generate "hercules-ci-agent${suffix}.json" config.settings;
16+
command = "${config.package}/bin/hercules-ci-agent --config ${configFile}";
17+
testCommand = "${command} --test-configuration";
18+
suffix = if name == "" then "" else "-${name}";
19+
user = if name == "" then "hercules-ci-agent" else "hci-${name}";
20+
in
21+
{
22+
options = {
23+
systemConfig = lib.mkOption {
24+
internal = true;
25+
type = types.unspecified; # A function from module arguments to config.
26+
};
27+
package = mkOption {
28+
description = ''
29+
Package containing the bin/hercules-ci-agent executable.
30+
'';
31+
type = types.package;
32+
default = pkgs.hercules-ci-agent;
33+
defaultText = literalExpression "pkgs.hercules-ci-agent";
34+
};
35+
user = mkOption {
36+
type = types.str;
37+
default = "_hercules-ci-agent";
38+
};
39+
} // makeSettingsOptions { cfg = config; opt = options; };
40+
config = let cfg = config; in
41+
{
42+
settings = {
43+
_module.args = {
44+
packageOption = options.package;
45+
inherit pkgs;
46+
};
47+
baseDirectory = "/var/lib/hercules-ci-agent${if name == "" then "" else "/${name}"}"; # Almost a `suffix` logic, but yield subdir
48+
nixUserIsTrusted = true;
49+
labels =
50+
let
51+
mkIfNotNull = x: mkIf (x != null) x;
52+
in
53+
{
54+
darwin.label = config.system.darwinLabel;
55+
darwin.revision = config.system.darwinRevision;
56+
darwin.version = config.system.darwinVersion;
57+
darwin.nix.daemon = config.nix.useDaemon;
58+
darwin.nix.sandbox = config.nix.settings.sandbox;
59+
};
60+
};
61+
systemConfig = { config, ... }: {
62+
launchd.daemons.hercules-ci-agent = {
63+
script = "exec ${cfg.package}/bin/hercules-ci-agent --config ${cfg.jsonFile}";
64+
65+
path = [ config.nix.package ];
66+
environment = {
67+
NIX_SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
68+
};
69+
70+
serviceConfig.KeepAlive = true;
71+
serviceConfig.RunAtLoad = true;
72+
serviceConfig.StandardErrorPath = cfg.logFile;
73+
serviceConfig.StandardOutPath = cfg.logFile;
74+
serviceConfig.GroupName = "_hercules-ci-agent";
75+
serviceConfig.UserName = "_hercules-ci-agent";
76+
serviceConfig.WorkingDirectory = user.home;
77+
serviceConfig.WatchPaths = [
78+
cfg.settings.staticSecretsDirectory
79+
];
80+
};
81+
82+
system.activationScripts.preActivation.text = ''
83+
touch '${cfg.logFile}'
84+
chown ${toString user.uid}:${toString user.gid} '${cfg.logFile}'
85+
'';
86+
# Trusted user allows simplified configuration and better performance
87+
# when operating in a cluster.
88+
nix.settings.trusted-users = [ config.systemd.services."hercules-ci-agent${suffix}".serviceConfig.User ];
89+
};
90+
};
91+
};
92+
93+
mergeSub =
94+
f: lib.mkMerge (map (sub: f (sub.systemConfig systemArgs)) (lib.attrValues config.services.hercules-ci-agents));
95+
in {
96+
options = {
97+
services.hercules-ci-agents = lib.mkOption {
98+
type = types.attrsOf (types.submoduleWith {
99+
modules = [ submodule ];
100+
});
101+
default = { };
102+
description = ''
103+
Multiple instances of hercules-ci-agent can be specified.
104+
105+
If you specify an instance named `""`, it will behave just as the `services.hercules-ci-agent` options did.
106+
- User: `hercules-ci-agent`
107+
- Default base directory: `/var/lib/hercules-ci-agent`
108+
109+
Otherwise:
110+
- User: `hci-''${name}`
111+
- Default base directory: `/var/lib/hercules-ci-agent-''${name}`
112+
'';
113+
};
114+
};
115+
116+
config = lib.mkMerge [
117+
{
118+
nix = mergeSub (c: c.nix);
119+
launchd = mergeSub (c: c.launchd);
120+
# FIXME: no per-agent user support
121+
# users = mergeSub (c: c.users);
122+
}
123+
{
124+
nix.extraOptions = lib.mkIf (config.services.hercules-ci-agents != { }) ''
125+
# A store path that was missing at first may well have finished building,
126+
# even shortly after the previous lookup. This *also* applies to the daemon.
127+
narinfo-cache-negative-ttl = 0
128+
'';
129+
130+
users.knownGroups = [ "hercules-ci-agent" "_hercules-ci-agent" ];
131+
users.knownUsers = [ "hercules-ci-agent" "_hercules-ci-agent" ];
132+
133+
users.users._hercules-ci-agent = {
134+
uid = mkDefault 399;
135+
gid = mkDefault config.users.groups._hercules-ci-agent.gid;
136+
home = mkDefault "/var/lib/hercules-ci-agent";
137+
name = "_hercules-ci-agent";
138+
createHome = true;
139+
shell = "/bin/bash";
140+
description = "System user for the Hercules CI Agent";
141+
};
142+
users.groups._hercules-ci-agent = {
143+
gid = mkDefault 32001;
144+
name = "_hercules-ci-agent";
145+
description = "System group for the Hercules CI Agent";
146+
};
147+
}
148+
];
149+
150+
meta.maintainers = [ ];
151+
}

0 commit comments

Comments
 (0)