nixos/syncoid: Reformat file with nixpkgs-fmt
This commit is contained in:
parent
b9f98165ab
commit
fa58d89b24
@ -8,206 +8,213 @@ let
|
|||||||
# Extract local dasaset names (so no datasets containing "@")
|
# Extract local dasaset names (so no datasets containing "@")
|
||||||
localDatasetName = d: optionals (d != null) (
|
localDatasetName = d: optionals (d != null) (
|
||||||
let m = builtins.match "([^/@]+[^@]*)" d; in
|
let m = builtins.match "([^/@]+[^@]*)" d; in
|
||||||
optionals (m != null) m);
|
optionals (m != null) m
|
||||||
|
);
|
||||||
|
|
||||||
# Escape as required by: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
|
# Escape as required by: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
|
||||||
escapeUnitName = name:
|
escapeUnitName = name:
|
||||||
lib.concatMapStrings (s: if lib.isList s then "-" else s)
|
lib.concatMapStrings (s: if lib.isList s then "-" else s)
|
||||||
(builtins.split "[^a-zA-Z0-9_.\\-]+" name);
|
(builtins.split "[^a-zA-Z0-9_.\\-]+" name);
|
||||||
|
|
||||||
# Function to build "zfs allow" and "zfs unallow" commands for the
|
# Function to build "zfs allow" and "zfs unallow" commands for the
|
||||||
# filesystems we've delegated permissions to.
|
# filesystems we've delegated permissions to.
|
||||||
buildAllowCommand = zfsAction: permissions: dataset: lib.escapeShellArgs [
|
buildAllowCommand = zfsAction: permissions: dataset: lib.escapeShellArgs [
|
||||||
# Here we explicitly use the booted system to guarantee the stable API needed by ZFS
|
# Here we explicitly use the booted system to guarantee the stable API needed by ZFS
|
||||||
"-+/run/booted-system/sw/bin/zfs" zfsAction
|
"-+/run/booted-system/sw/bin/zfs"
|
||||||
cfg.user (concatStringsSep "," permissions) dataset
|
zfsAction
|
||||||
|
cfg.user
|
||||||
|
(concatStringsSep "," permissions)
|
||||||
|
dataset
|
||||||
];
|
];
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
|
||||||
# Interface
|
# Interface
|
||||||
|
|
||||||
options.services.syncoid = {
|
options.services.syncoid = {
|
||||||
enable = mkEnableOption "Syncoid ZFS synchronization service";
|
enable = mkEnableOption "Syncoid ZFS synchronization service";
|
||||||
|
|
||||||
interval = mkOption {
|
interval = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "hourly";
|
default = "hourly";
|
||||||
example = "*-*-* *:15:00";
|
example = "*-*-* *:15:00";
|
||||||
description = ''
|
description = ''
|
||||||
Run syncoid at this interval. The default is to run hourly.
|
Run syncoid at this interval. The default is to run hourly.
|
||||||
|
|
||||||
The format is described in
|
The format is described in
|
||||||
<citerefentry><refentrytitle>systemd.time</refentrytitle>
|
<citerefentry><refentrytitle>systemd.time</refentrytitle>
|
||||||
<manvolnum>7</manvolnum></citerefentry>.
|
<manvolnum>7</manvolnum></citerefentry>.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
user = mkOption {
|
user = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "syncoid";
|
default = "syncoid";
|
||||||
example = "backup";
|
example = "backup";
|
||||||
description = ''
|
description = ''
|
||||||
The user for the service. ZFS privilege delegation will be
|
The user for the service. ZFS privilege delegation will be
|
||||||
automatically configured for any local pools used by syncoid if this
|
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
|
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
|
"hold" and "send" privileges on any pool that has datasets being sent
|
||||||
and the "create", "mount", "receive", and "rollback" privileges on
|
and the "create", "mount", "receive", and "rollback" privileges on
|
||||||
any pool that has datasets being received.
|
any pool that has datasets being received.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = "syncoid";
|
default = "syncoid";
|
||||||
example = "backup";
|
example = "backup";
|
||||||
description = "The group for the service.";
|
description = "The group for the service.";
|
||||||
};
|
};
|
||||||
|
|
||||||
sshKey = mkOption {
|
sshKey = mkOption {
|
||||||
type = types.nullOr types.path;
|
type = types.nullOr types.path;
|
||||||
# Prevent key from being copied to store
|
# Prevent key from being copied to store
|
||||||
apply = mapNullable toString;
|
apply = mapNullable toString;
|
||||||
default = null;
|
default = null;
|
||||||
description = ''
|
description = ''
|
||||||
SSH private key file to use to login to the remote system. Can be
|
SSH private key file to use to login to the remote system. Can be
|
||||||
overridden in individual commands.
|
overridden in individual commands.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
commonArgs = mkOption {
|
commonArgs = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [];
|
default = [ ];
|
||||||
example = [ "--no-sync-snap" ];
|
example = [ "--no-sync-snap" ];
|
||||||
description = ''
|
description = ''
|
||||||
Arguments to add to every syncoid command, unless disabled for that
|
Arguments to add to every syncoid command, unless disabled for that
|
||||||
command. See
|
command. See
|
||||||
<link xlink:href="https://github.com/jimsalterjrs/sanoid/#syncoid-command-line-options"/>
|
<link xlink:href="https://github.com/jimsalterjrs/sanoid/#syncoid-command-line-options"/>
|
||||||
for available options.
|
for available options.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
service = mkOption {
|
service = mkOption {
|
||||||
type = types.attrs;
|
type = types.attrs;
|
||||||
default = {};
|
default = { };
|
||||||
description = ''
|
description = ''
|
||||||
Systemd configuration common to all syncoid services.
|
Systemd configuration common to all syncoid services.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
commands = mkOption {
|
commands = mkOption {
|
||||||
type = types.attrsOf (types.submodule ({ name, ... }: {
|
type = types.attrsOf (types.submodule ({ name, ... }: {
|
||||||
options = {
|
options = {
|
||||||
source = mkOption {
|
source = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
example = "pool/dataset";
|
example = "pool/dataset";
|
||||||
description = ''
|
description = ''
|
||||||
Source ZFS dataset. Can be either local or remote. Defaults to
|
Source ZFS dataset. Can be either local or remote. Defaults to
|
||||||
the attribute name.
|
the attribute name.
|
||||||
'';
|
'';
|
||||||
};
|
|
||||||
|
|
||||||
target = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
example = "user@server:pool/dataset";
|
|
||||||
description = ''
|
|
||||||
Target ZFS dataset. Can be either local
|
|
||||||
(<replaceable>pool/dataset</replaceable>) or remote
|
|
||||||
(<replaceable>user@server:pool/dataset</replaceable>).
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
recursive = mkEnableOption ''the transfer of child datasets'';
|
|
||||||
|
|
||||||
sshKey = mkOption {
|
|
||||||
type = types.nullOr types.path;
|
|
||||||
# Prevent key from being copied to store
|
|
||||||
apply = mapNullable toString;
|
|
||||||
description = ''
|
|
||||||
SSH private key file to use to login to the remote system.
|
|
||||||
Defaults to <option>services.syncoid.sshKey</option> option.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
sendOptions = mkOption {
|
|
||||||
type = types.separatedString " ";
|
|
||||||
default = "";
|
|
||||||
example = "Lc e";
|
|
||||||
description = ''
|
|
||||||
Advanced options to pass to zfs send. Options are specified
|
|
||||||
without their leading dashes and separated by spaces.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
recvOptions = mkOption {
|
|
||||||
type = types.separatedString " ";
|
|
||||||
default = "";
|
|
||||||
example = "ux recordsize o compression=lz4";
|
|
||||||
description = ''
|
|
||||||
Advanced options to pass to zfs recv. Options are specified
|
|
||||||
without their leading dashes and separated by spaces.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
useCommonArgs = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = true;
|
|
||||||
description = ''
|
|
||||||
Whether to add the configured common arguments to this command.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
service = mkOption {
|
|
||||||
type = types.attrs;
|
|
||||||
default = {};
|
|
||||||
description = ''
|
|
||||||
Systemd configuration specific to this syncoid service.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
extraArgs = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [];
|
|
||||||
example = [ "--sshport 2222" ];
|
|
||||||
description = "Extra syncoid arguments for this command.";
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
config = {
|
|
||||||
source = mkDefault name;
|
target = mkOption {
|
||||||
sshKey = mkDefault cfg.sshKey;
|
type = types.str;
|
||||||
|
example = "user@server:pool/dataset";
|
||||||
|
description = ''
|
||||||
|
Target ZFS dataset. Can be either local
|
||||||
|
(<replaceable>pool/dataset</replaceable>) or remote
|
||||||
|
(<replaceable>user@server:pool/dataset</replaceable>).
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
}));
|
|
||||||
default = {};
|
recursive = mkEnableOption ''the transfer of child datasets'';
|
||||||
example = literalExample ''
|
|
||||||
{
|
sshKey = mkOption {
|
||||||
"pool/test".target = "root@target:pool/test";
|
type = types.nullOr types.path;
|
||||||
}
|
# Prevent key from being copied to store
|
||||||
'';
|
apply = mapNullable toString;
|
||||||
description = "Syncoid commands to run.";
|
description = ''
|
||||||
|
SSH private key file to use to login to the remote system.
|
||||||
|
Defaults to <option>services.syncoid.sshKey</option> option.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
sendOptions = mkOption {
|
||||||
|
type = types.separatedString " ";
|
||||||
|
default = "";
|
||||||
|
example = "Lc e";
|
||||||
|
description = ''
|
||||||
|
Advanced options to pass to zfs send. Options are specified
|
||||||
|
without their leading dashes and separated by spaces.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
recvOptions = mkOption {
|
||||||
|
type = types.separatedString " ";
|
||||||
|
default = "";
|
||||||
|
example = "ux recordsize o compression=lz4";
|
||||||
|
description = ''
|
||||||
|
Advanced options to pass to zfs recv. Options are specified
|
||||||
|
without their leading dashes and separated by spaces.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
useCommonArgs = mkOption {
|
||||||
|
type = types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Whether to add the configured common arguments to this command.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
service = mkOption {
|
||||||
|
type = types.attrs;
|
||||||
|
default = { };
|
||||||
|
description = ''
|
||||||
|
Systemd configuration specific to this syncoid service.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraArgs = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [ ];
|
||||||
|
example = [ "--sshport 2222" ];
|
||||||
|
description = "Extra syncoid arguments for this command.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
source = mkDefault name;
|
||||||
|
sshKey = mkDefault cfg.sshKey;
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
default = { };
|
||||||
|
example = literalExample ''
|
||||||
|
{
|
||||||
|
"pool/test".target = "root@target:pool/test";
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
description = "Syncoid commands to run.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Implementation
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
users = {
|
||||||
|
users = mkIf (cfg.user == "syncoid") {
|
||||||
|
syncoid = {
|
||||||
|
group = cfg.group;
|
||||||
|
isSystemUser = true;
|
||||||
|
# For syncoid to be able to create /var/lib/syncoid/.ssh/
|
||||||
|
# and to use custom ssh_config or known_hosts.
|
||||||
|
home = "/var/lib/syncoid";
|
||||||
|
createHome = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
groups = mkIf (cfg.group == "syncoid") {
|
||||||
|
syncoid = { };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Implementation
|
systemd.services = mapAttrs'
|
||||||
|
(name: c:
|
||||||
config = mkIf cfg.enable {
|
|
||||||
users = {
|
|
||||||
users = mkIf (cfg.user == "syncoid") {
|
|
||||||
syncoid = {
|
|
||||||
group = cfg.group;
|
|
||||||
isSystemUser = true;
|
|
||||||
# For syncoid to be able to create /var/lib/syncoid/.ssh/
|
|
||||||
# and to use custom ssh_config or known_hosts.
|
|
||||||
home = "/var/lib/syncoid";
|
|
||||||
createHome = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
groups = mkIf (cfg.group == "syncoid") {
|
|
||||||
syncoid = {};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services = mapAttrs' (name: c:
|
|
||||||
nameValuePair "syncoid-${escapeUnitName name}" (mkMerge [
|
nameValuePair "syncoid-${escapeUnitName name}" (mkMerge [
|
||||||
{ description = "Syncoid ZFS synchronization from ${c.source} to ${c.target}";
|
{
|
||||||
|
description = "Syncoid ZFS synchronization from ${c.source} to ${c.target}";
|
||||||
after = [ "zfs.target" ];
|
after = [ "zfs.target" ];
|
||||||
startAt = cfg.interval;
|
startAt = cfg.interval;
|
||||||
# syncoid may need zpool to get feature@extensible_dataset
|
# syncoid may need zpool to get feature@extensible_dataset
|
||||||
@ -226,11 +233,15 @@ in {
|
|||||||
++ optional c.recursive "-r"
|
++ optional c.recursive "-r"
|
||||||
++ optionals (c.sshKey != null) [ "--sshkey" c.sshKey ]
|
++ optionals (c.sshKey != null) [ "--sshkey" c.sshKey ]
|
||||||
++ c.extraArgs
|
++ c.extraArgs
|
||||||
++ [ "--sendoptions" c.sendOptions
|
++ [
|
||||||
"--recvoptions" c.recvOptions
|
"--sendoptions"
|
||||||
"--no-privilege-elevation"
|
c.sendOptions
|
||||||
c.source c.target
|
"--recvoptions"
|
||||||
]);
|
c.recvOptions
|
||||||
|
"--no-privilege-elevation"
|
||||||
|
c.source
|
||||||
|
c.target
|
||||||
|
]);
|
||||||
User = cfg.user;
|
User = cfg.user;
|
||||||
Group = cfg.group;
|
Group = cfg.group;
|
||||||
StateDirectory = [ "syncoid" ];
|
StateDirectory = [ "syncoid" ];
|
||||||
@ -246,7 +257,7 @@ in {
|
|||||||
# systemd-analyze security | grep syncoid-'*'
|
# systemd-analyze security | grep syncoid-'*'
|
||||||
AmbientCapabilities = "";
|
AmbientCapabilities = "";
|
||||||
CapabilityBoundingSet = "";
|
CapabilityBoundingSet = "";
|
||||||
DeviceAllow = ["/dev/zfs"];
|
DeviceAllow = [ "/dev/zfs" ];
|
||||||
LockPersonality = true;
|
LockPersonality = true;
|
||||||
MemoryDenyWriteExecute = true;
|
MemoryDenyWriteExecute = true;
|
||||||
NoNewPrivileges = true;
|
NoNewPrivileges = true;
|
||||||
@ -272,7 +283,7 @@ in {
|
|||||||
BindPaths = [ "/dev/zfs" ];
|
BindPaths = [ "/dev/zfs" ];
|
||||||
BindReadOnlyPaths = [ builtins.storeDir "/etc" "/run" "/bin/sh" ];
|
BindReadOnlyPaths = [ builtins.storeDir "/etc" "/run" "/bin/sh" ];
|
||||||
# Avoid useless mounting of RootDirectory= in the own RootDirectory= of ExecStart='s mount namespace.
|
# Avoid useless mounting of RootDirectory= in the own RootDirectory= of ExecStart='s mount namespace.
|
||||||
InaccessiblePaths = ["-+/run/syncoid/${escapeUnitName name}"];
|
InaccessiblePaths = [ "-+/run/syncoid/${escapeUnitName name}" ];
|
||||||
MountAPIVFS = true;
|
MountAPIVFS = true;
|
||||||
# Create RootDirectory= in the host's mount namespace.
|
# Create RootDirectory= in the host's mount namespace.
|
||||||
RuntimeDirectory = [ "syncoid/${escapeUnitName name}" ];
|
RuntimeDirectory = [ "syncoid/${escapeUnitName name}" ];
|
||||||
@ -283,8 +294,15 @@ in {
|
|||||||
# perf stat -x, 2>perf.log -e 'syscalls:sys_enter_*' syncoid …
|
# perf stat -x, 2>perf.log -e 'syscalls:sys_enter_*' syncoid …
|
||||||
# awk >perf.syscalls -F "," '$1 > 0 {sub("syscalls:sys_enter_","",$3); print $3}' perf.log
|
# awk >perf.syscalls -F "," '$1 > 0 {sub("syscalls:sys_enter_","",$3); print $3}' perf.log
|
||||||
# systemd-analyze syscall-filter | grep -v -e '#' | sed -e ':loop; /^[^ ]/N; s/\n //; t loop' | grep $(printf ' -e \\<%s\\>' $(cat perf.syscalls)) | cut -f 1 -d ' '
|
# systemd-analyze syscall-filter | grep -v -e '#' | sed -e ':loop; /^[^ ]/N; s/\n //; t loop' | grep $(printf ' -e \\<%s\\>' $(cat perf.syscalls)) | cut -f 1 -d ' '
|
||||||
"~@aio" "~@chown" "~@keyring" "~@memlock" "~@privileged"
|
"~@aio"
|
||||||
"~@resources" "~@setuid" "~@sync" "~@timer"
|
"~@chown"
|
||||||
|
"~@keyring"
|
||||||
|
"~@memlock"
|
||||||
|
"~@privileged"
|
||||||
|
"~@resources"
|
||||||
|
"~@setuid"
|
||||||
|
"~@sync"
|
||||||
|
"~@timer"
|
||||||
];
|
];
|
||||||
SystemCallArchitectures = "native";
|
SystemCallArchitectures = "native";
|
||||||
# This is for BindPaths= and BindReadOnlyPaths=
|
# This is for BindPaths= and BindReadOnlyPaths=
|
||||||
@ -294,8 +312,9 @@ in {
|
|||||||
}
|
}
|
||||||
cfg.service
|
cfg.service
|
||||||
c.service
|
c.service
|
||||||
])) cfg.commands;
|
]))
|
||||||
};
|
cfg.commands;
|
||||||
|
};
|
||||||
|
|
||||||
meta.maintainers = with maintainers; [ julm lopsided98 ];
|
meta.maintainers = with maintainers; [ julm lopsided98 ];
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user