summary refs log tree commit diff
path: root/nixos/modules/services/backup/syncoid.nix
diff options
context:
space:
mode:
authorBenjamin Hipple <bhipple@protonmail.com>2020-10-25 10:40:33 -0400
committerGitHub <noreply@github.com>2020-10-25 10:40:33 -0400
commitf98312fcb5882e67b7c92d636e0ce7182255dc63 (patch)
tree7600aef9ece7a3088b7eedab66ff372656a7ece7 /nixos/modules/services/backup/syncoid.nix
parent7426e53f95169881d1696bf7c631561ed9a75465 (diff)
parent733acfa140d5b73bc69c53c4ebd90ccc5f281f0e (diff)
downloadnixpkgs-f98312fcb5882e67b7c92d636e0ce7182255dc63.tar
nixpkgs-f98312fcb5882e67b7c92d636e0ce7182255dc63.tar.gz
nixpkgs-f98312fcb5882e67b7c92d636e0ce7182255dc63.tar.bz2
nixpkgs-f98312fcb5882e67b7c92d636e0ce7182255dc63.tar.lz
nixpkgs-f98312fcb5882e67b7c92d636e0ce7182255dc63.tar.xz
nixpkgs-f98312fcb5882e67b7c92d636e0ce7182255dc63.tar.zst
nixpkgs-f98312fcb5882e67b7c92d636e0ce7182255dc63.zip
Merge pull request #79759 from lopsided98/syncoid-no-root
nixos/syncoid: automatically setup privilege delegation
Diffstat (limited to 'nixos/modules/services/backup/syncoid.nix')
-rw-r--r--nixos/modules/services/backup/syncoid.nix52
1 files changed, 48 insertions, 4 deletions
diff --git a/nixos/modules/services/backup/syncoid.nix b/nixos/modules/services/backup/syncoid.nix
index fff119c2cf0..e72e3fa59cf 100644
--- a/nixos/modules/services/backup/syncoid.nix
+++ b/nixos/modules/services/backup/syncoid.nix
@@ -4,6 +4,15 @@ with lib;
 
 let
   cfg = config.services.syncoid;
+
+  # Extract pool names of local datasets (ones that don't contain "@") that
+  # have the specified type (either "source" or "target")
+  getPools = type: unique (map (d: head (builtins.match "([^/]+).*" d)) (
+    # Filter local datasets
+    filter (d: !hasInfix "@" d)
+    # Get datasets of the specified type
+    (catAttrs type (attrValues cfg.commands))
+  ));
 in {
 
     # Interface
@@ -26,14 +35,25 @@ in {
 
       user = mkOption {
         type = types.str;
-        default = "root";
+        default = "syncoid";
         example = "backup";
         description = ''
-          The user for the service. Sudo or ZFS privilege delegation must be
-          configured to use a user other than root.
+          The user for the service. ZFS privilege delegation will be
+          automatically configured for any local pools used by syncoid if this
+          option is set to a user other than root. The user will be given the
+          "hold" and "send" privileges on any pool that has datasets being sent
+          and the "create", "mount", "receive", and "rollback" privileges on
+          any pool that has datasets being received.
         '';
       };
 
+      group = mkOption {
+        type = types.str;
+        default = "syncoid";
+        example = "backup";
+        description = "The group for the service.";
+      };
+
       sshKey = mkOption {
         type = types.nullOr types.path;
         # Prevent key from being copied to store
@@ -150,6 +170,18 @@ in {
     # Implementation
 
     config = mkIf cfg.enable {
+      users =  {
+        users = mkIf (cfg.user == "syncoid") {
+          syncoid = {
+            group = cfg.group;
+            isSystemUser = true;
+          };
+        };
+        groups = mkIf (cfg.group == "syncoid") {
+          syncoid = {};
+        };
+      };
+
       systemd.services.syncoid = {
         description = "Syncoid ZFS synchronization service";
         script = concatMapStringsSep "\n" (c: lib.escapeShellArgs
@@ -160,10 +192,22 @@ in {
             ++ c.extraArgs
             ++ [ "--sendoptions" c.sendOptions
                  "--recvoptions" c.recvOptions
+                 "--no-privilege-elevation"
                  c.source c.target
                ])) (attrValues cfg.commands);
         after = [ "zfs.target" ];
-        serviceConfig.User = cfg.user;
+        serviceConfig = {
+          ExecStartPre = (map (pool: lib.escapeShellArgs [
+            "+/run/booted-system/sw/bin/zfs" "allow"
+            cfg.user "hold,send" pool
+          ]) (getPools "source")) ++
+          (map (pool: lib.escapeShellArgs [
+            "+/run/booted-system/sw/bin/zfs" "allow"
+            cfg.user "create,mount,receive,rollback" pool
+          ]) (getPools "target"));
+          User = cfg.user;
+          Group = cfg.group;
+        };
         startAt = cfg.interval;
       };
     };