1 { config, lib, pkgs, ... }:
6 cfg = config.services.syncoid;
7 # Escape as required by: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
9 lib.concatMapStrings (s: if lib.isList s then "-" else s)
10 (builtins.split "[^a-zA-Z0-9_.\\-]+" name);
15 options.services.syncoid = {
16 enable = mkEnableOption "Syncoid ZFS synchronization service";
21 example = "*-*-* *:15:00";
23 Run syncoid at this interval. The default is to run hourly.
25 The format is described in
26 <citerefentry><refentrytitle>systemd.time</refentrytitle>
27 <manvolnum>7</manvolnum></citerefentry>.
36 The user for the service. Sudo or ZFS privilege delegation must be
37 configured to use a user other than root.
42 type = types.nullOr types.path;
43 # Prevent key from being copied to store
44 apply = mapNullable toString;
47 SSH private key file to use to login to the remote system. Can be
48 overridden in individual commands.
52 commonArgs = mkOption {
53 type = types.listOf types.str;
55 example = [ "--no-sync-snap" ];
57 Arguments to add to every syncoid command, unless disabled for that
59 <link xlink:href="https://github.com/jimsalterjrs/sanoid/#syncoid-command-line-options"/>
60 for available options.
68 Systemd configuration common to all syncoid services.
73 type = types.attrsOf (types.submodule ({ name, ... }: {
77 example = "pool/dataset";
79 Source ZFS dataset. Can be either local or remote. Defaults to
86 example = "user@server:pool/dataset";
88 Target ZFS dataset. Can be either local
89 (<replaceable>pool/dataset</replaceable>) or remote
90 (<replaceable>user@server:pool/dataset</replaceable>).
94 recursive = mkEnableOption ''the transfer of child datasets'';
97 type = types.nullOr types.path;
98 # Prevent key from being copied to store
99 apply = mapNullable toString;
101 SSH private key file to use to login to the remote system.
102 Defaults to <option>services.syncoid.sshKey</option> option.
106 sendOptions = mkOption {
107 type = types.separatedString " ";
111 Advanced options to pass to zfs send. Options are specified
112 without their leading dashes and separated by spaces.
116 recvOptions = mkOption {
117 type = types.separatedString " ";
119 example = "ux recordsize o compression=lz4";
121 Advanced options to pass to zfs recv. Options are specified
122 without their leading dashes and separated by spaces.
126 useCommonArgs = mkOption {
130 Whether to add the configured common arguments to this command.
138 Systemd configuration specific to this syncoid service.
142 extraArgs = mkOption {
143 type = types.listOf types.str;
145 example = [ "--sshport 2222" ];
146 description = "Extra syncoid arguments for this command.";
150 source = mkDefault name;
151 sshKey = mkDefault cfg.sshKey;
155 example."pool/test".target = "root@target:pool/test";
156 description = "Syncoid commands to run.";
162 config = mkIf cfg.enable {
163 systemd.services = mapAttrs' (name: c:
164 nameValuePair "syncoid-${escapeUnitName name}" (recursiveUpdate (recursiveUpdate {
165 description = "Syncoid ZFS synchronization from ${c.source} to ${c.target}";
166 script = lib.escapeShellArgs ([ "${pkgs.sanoid}/bin/syncoid" ]
167 ++ (optionals c.useCommonArgs cfg.commonArgs)
168 ++ (optional c.recursive "-r")
169 ++ (optionals (c.sshKey != null) [ "--sshkey" c.sshKey ])
171 ++ [ "--sendoptions" c.sendOptions
172 "--recvoptions" c.recvOptions
175 after = [ "zfs.target" ];
176 serviceConfig.User = cfg.user;
177 startAt = cfg.interval;
178 } cfg.serviceConfig) c.serviceConfig) cfg.commands;
181 meta.maintainers = with maintainers; [ lopsided98 ];