···
cfg = config.services.syncoid;
8
+
# Extract pool names of local datasets (ones that don't contain "@") that
9
+
# have the specified type (either "source" or "target")
10
+
getPools = type: unique (map (d: head (builtins.match "([^/]+).*" d)) (
11
+
# Filter local datasets
12
+
filter (d: !hasInfix "@" d)
13
+
# Get datasets of the specified type
14
+
(catAttrs type (attrValues cfg.commands))
···
38
+
default = "syncoid";
32
-
The user for the service. Sudo or ZFS privilege delegation must be
33
-
configured to use a user other than root.
41
+
The user for the service. ZFS privilege delegation will be
42
+
automatically configured for any local pools used by syncoid if this
43
+
option is set to a user other than root. The user will be given the
44
+
"hold" and "send" privileges on any pool that has datasets being sent
45
+
and the "create", "mount", "receive", and "rollback" privileges on
46
+
any pool that has datasets being received.
52
+
default = "syncoid";
54
+
description = "The group for the service.";
···
config = mkIf cfg.enable {
174
+
users = mkIf (cfg.user == "syncoid") {
177
+
isSystemUser = true;
180
+
groups = mkIf (cfg.group == "syncoid") {
systemd.services.syncoid = {
description = "Syncoid ZFS synchronization service";
script = concatMapStringsSep "\n" (c: lib.escapeShellArgs
···
++ [ "--sendoptions" c.sendOptions
"--recvoptions" c.recvOptions
195
+
"--no-privilege-elevation"
])) (attrValues cfg.commands);
after = [ "zfs.target" ];
166
-
serviceConfig.User = cfg.user;
200
+
ExecStartPre = (map (pool: lib.escapeShellArgs [
201
+
"+/run/booted-system/sw/bin/zfs" "allow"
202
+
cfg.user "hold,send" pool
203
+
]) (getPools "source")) ++
204
+
(map (pool: lib.escapeShellArgs [
205
+
"+/run/booted-system/sw/bin/zfs" "allow"
206
+
cfg.user "create,mount,receive,rollback" pool
207
+
]) (getPools "target"));