treewide: Format all Nix files

Format all Nix files using the officially approved formatter,
making the CI check introduced in the previous commit succeed:

  nix-build ci -A fmt.check

This is the next step of the of the [implementation](https://github.com/NixOS/nixfmt/issues/153)
of the accepted [RFC 166](https://github.com/NixOS/rfcs/pull/166).

This commit will lead to merge conflicts for a number of PRs,
up to an estimated ~1100 (~33%) among the PRs with activity in the past 2
months, but that should be lower than what it would be without the previous
[partial treewide format](https://github.com/NixOS/nixpkgs/pull/322537).

Merge conflicts caused by this commit can now automatically be resolved while rebasing using the
[auto-rebase script](8616af08d9/maintainers/scripts/auto-rebase).

If you run into any problems regarding any of this, please reach out to the
[formatting team](https://nixos.org/community/teams/formatting/) by
pinging @NixOS/nix-formatting.
This commit is contained in:
Silvan Mosberger 2025-04-01 20:10:43 +02:00
parent 2140bf39e4
commit 374e6bcc40
1523 changed files with 986047 additions and 513621 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,23 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.sanoid;
datasetSettingsType = with lib.types;
(attrsOf (nullOr (oneOf [ str int bool (listOf str) ]))) // {
datasetSettingsType =
with lib.types;
(attrsOf (
nullOr (oneOf [
str
int
bool
(listOf str)
])
))
// {
description = "dataset/template options";
};
@ -48,10 +62,13 @@ let
datasetOptions = rec {
use_template = lib.mkOption {
description = "Names of the templates to use for this dataset.";
type = lib.types.listOf (lib.types.str // {
check = (lib.types.enum (lib.attrNames cfg.templates)).check;
description = "configured template name";
});
type = lib.types.listOf (
lib.types.str
// {
check = (lib.types.enum (lib.attrNames cfg.templates)).check;
description = "configured template name";
}
);
default = [ ];
};
useTemplate = use_template;
@ -63,7 +80,12 @@ let
recursively in an atomic way without the possibility to
override settings for child datasets.
'';
type = with lib.types; oneOf [ bool (enum [ "zfs" ]) ];
type =
with lib.types;
oneOf [
bool
(enum [ "zfs" ])
];
default = false;
};
@ -80,26 +102,32 @@ let
# Function to build "zfs allow" and "zfs unallow" commands for the
# filesystems we've delegated permissions to.
buildAllowCommand = zfsAction: permissions: dataset: lib.escapeShellArgs [
# Here we explicitly use the booted system to guarantee the stable API needed by ZFS
"-+/run/booted-system/sw/bin/zfs"
zfsAction
"sanoid"
(lib.concatStringsSep "," permissions)
dataset
];
buildAllowCommand =
zfsAction: permissions: dataset:
lib.escapeShellArgs [
# Here we explicitly use the booted system to guarantee the stable API needed by ZFS
"-+/run/booted-system/sw/bin/zfs"
zfsAction
"sanoid"
(lib.concatStringsSep "," permissions)
dataset
];
configFile =
let
mkValueString = v:
if lib.isList v then lib.concatStringsSep "," v
else lib.generators.mkValueStringDefault { } v;
mkValueString =
v: if lib.isList v then lib.concatStringsSep "," v else lib.generators.mkValueStringDefault { } v;
mkKeyValue = k: v:
if v == null then ""
else if k == "processChildrenOnly" then ""
else if k == "useTemplate" then ""
else lib.generators.mkKeyValueDefault { inherit mkValueString; } "=" k v;
mkKeyValue =
k: v:
if v == null then
""
else if k == "processChildrenOnly" then
""
else if k == "useTemplate" then
""
else
lib.generators.mkKeyValueDefault { inherit mkValueString; } "=" k v;
in
lib.generators.toINI { inherit mkKeyValue; } cfg.settings;
@ -111,7 +139,7 @@ in
options.services.sanoid = {
enable = lib.mkEnableOption "Sanoid ZFS snapshotting service";
package = lib.mkPackageOption pkgs "sanoid" {};
package = lib.mkPackageOption pkgs "sanoid" { };
interval = lib.mkOption {
type = lib.types.str;
@ -126,21 +154,32 @@ in
};
datasets = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ config, options, ... }: {
freeformType = datasetSettingsType;
options = commonOptions // datasetOptions;
config.use_template = lib.modules.mkAliasAndWrapDefsWithPriority lib.id (options.useTemplate or { });
config.process_children_only = lib.modules.mkAliasAndWrapDefsWithPriority lib.id (options.processChildrenOnly or { });
}));
type = lib.types.attrsOf (
lib.types.submodule (
{ config, options, ... }:
{
freeformType = datasetSettingsType;
options = commonOptions // datasetOptions;
config.use_template = lib.modules.mkAliasAndWrapDefsWithPriority lib.id (
options.useTemplate or { }
);
config.process_children_only = lib.modules.mkAliasAndWrapDefsWithPriority lib.id (
options.processChildrenOnly or { }
);
}
)
);
default = { };
description = "Datasets to snapshot.";
};
templates = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule {
freeformType = datasetSettingsType;
options = commonOptions;
});
type = lib.types.attrsOf (
lib.types.submodule {
freeformType = datasetSettingsType;
options = commonOptions;
}
);
default = { };
description = "Templates for datasets.";
};
@ -157,7 +196,11 @@ in
extraArgs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "--verbose" "--readonly" "--debug" ];
example = [
"--verbose"
"--readonly"
"--debug"
];
description = ''
Extra arguments to pass to sanoid. See
<https://github.com/jimsalterjrs/sanoid/#sanoid-command-line-options>
@ -177,14 +220,29 @@ in
systemd.services.sanoid = {
description = "Sanoid snapshot service";
serviceConfig = {
ExecStartPre = (map (buildAllowCommand "allow" [ "snapshot" "mount" "destroy" ]) datasets);
ExecStopPost = (map (buildAllowCommand "unallow" [ "snapshot" "mount" "destroy" ]) datasets);
ExecStart = lib.escapeShellArgs ([
"${cfg.package}/bin/sanoid"
"--cron"
"--configdir"
(pkgs.writeTextDir "sanoid.conf" configFile)
] ++ cfg.extraArgs);
ExecStartPre = (
map (buildAllowCommand "allow" [
"snapshot"
"mount"
"destroy"
]) datasets
);
ExecStopPost = (
map (buildAllowCommand "unallow" [
"snapshot"
"mount"
"destroy"
]) datasets
);
ExecStart = lib.escapeShellArgs (
[
"${cfg.package}/bin/sanoid"
"--cron"
"--configdir"
(pkgs.writeTextDir "sanoid.conf" configFile)
]
++ cfg.extraArgs
);
User = "sanoid";
Group = "sanoid";
DynamicUser = true;

View file

@ -1,54 +1,69 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.syncoid;
# Extract local dasaset names (so no datasets containing "@")
localDatasetName = d: lib.optionals (d != null) (
let m = builtins.match "([^/@]+[^@]*)" d; in
lib.optionals (m != null) m
);
localDatasetName =
d:
lib.optionals (d != null) (
let
m = builtins.match "([^/@]+[^@]*)" d;
in
lib.optionals (m != null) m
);
# Escape as required by: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
escapeUnitName = name:
lib.concatMapStrings (s: if lib.isList s then "-" else s)
(builtins.split "[^a-zA-Z0-9_.\\-]+" name);
escapeUnitName =
name:
lib.concatMapStrings (s: if lib.isList s then "-" else s) (
builtins.split "[^a-zA-Z0-9_.\\-]+" name
);
# Function to build "zfs allow" commands for the filesystems we've delegated
# permissions to. It also checks if the target dataset exists before
# delegating permissions, if it doesn't exist we delegate it to the parent
# dataset (if it exists). This should solve the case of provisoning new
# datasets.
buildAllowCommand = permissions: dataset: (
"-+${pkgs.writeShellScript "zfs-allow-${dataset}" ''
# Here we explicitly use the booted system to guarantee the stable API needed by ZFS
buildAllowCommand =
permissions: dataset:
(
"-+${pkgs.writeShellScript "zfs-allow-${dataset}" ''
# Here we explicitly use the booted system to guarantee the stable API needed by ZFS
# Run a ZFS list on the dataset to check if it exists
if ${lib.escapeShellArgs [
"/run/booted-system/sw/bin/zfs"
"list"
dataset
]} 2> /dev/null; then
${lib.escapeShellArgs [
"/run/booted-system/sw/bin/zfs"
"allow"
cfg.user
(lib.concatStringsSep "," permissions)
dataset
]}
${lib.optionalString ((builtins.dirOf dataset) != ".") ''
else
# Run a ZFS list on the dataset to check if it exists
if ${
lib.escapeShellArgs [
"/run/booted-system/sw/bin/zfs"
"list"
dataset
]
} 2> /dev/null; then
${lib.escapeShellArgs [
"/run/booted-system/sw/bin/zfs"
"allow"
cfg.user
(lib.concatStringsSep "," permissions)
# Remove the last part of the path
(builtins.dirOf dataset)
dataset
]}
''}
fi
''}"
);
${lib.optionalString ((builtins.dirOf dataset) != ".") ''
else
${lib.escapeShellArgs [
"/run/booted-system/sw/bin/zfs"
"allow"
cfg.user
(lib.concatStringsSep "," permissions)
# Remove the last part of the path
(builtins.dirOf dataset)
]}
''}
fi
''}"
);
# Function to build "zfs unallow" commands for the filesystems we've
# delegated permissions to. Here we unallow both the target but also
@ -56,26 +71,30 @@ let
# knowing if the allow command did execute on the parent dataset or
# not in the pre-hook. We can't run the same if in the post hook
# since the dataset should have been created at this point.
buildUnallowCommand = permissions: dataset: (
"-+${pkgs.writeShellScript "zfs-unallow-${dataset}" ''
# Here we explicitly use the booted system to guarantee the stable API needed by ZFS
${lib.escapeShellArgs [
"/run/booted-system/sw/bin/zfs"
"unallow"
cfg.user
(lib.concatStringsSep "," permissions)
dataset
]}
${lib.optionalString ((builtins.dirOf dataset) != ".") (lib.escapeShellArgs [
"/run/booted-system/sw/bin/zfs"
"unallow"
cfg.user
(lib.concatStringsSep "," permissions)
# Remove the last part of the path
(builtins.dirOf dataset)
])}
''}"
);
buildUnallowCommand =
permissions: dataset:
(
"-+${pkgs.writeShellScript "zfs-unallow-${dataset}" ''
# Here we explicitly use the booted system to guarantee the stable API needed by ZFS
${lib.escapeShellArgs [
"/run/booted-system/sw/bin/zfs"
"unallow"
cfg.user
(lib.concatStringsSep "," permissions)
dataset
]}
${lib.optionalString ((builtins.dirOf dataset) != ".") (
lib.escapeShellArgs [
"/run/booted-system/sw/bin/zfs"
"unallow"
cfg.user
(lib.concatStringsSep "," permissions)
# Remove the last part of the path
(builtins.dirOf dataset)
]
)}
''}"
);
in
{
@ -84,7 +103,7 @@ in
options.services.syncoid = {
enable = lib.mkEnableOption "Syncoid ZFS synchronization service";
package = lib.mkPackageOption pkgs "sanoid" {};
package = lib.mkPackageOption pkgs "sanoid" { };
interval = lib.mkOption {
type = lib.types.str;
@ -131,7 +150,14 @@ in
localSourceAllow = lib.mkOption {
type = lib.types.listOf lib.types.str;
# Permissions snapshot and destroy are in case --no-sync-snap is not used
default = [ "bookmark" "hold" "send" "snapshot" "destroy" "mount" ];
default = [
"bookmark"
"hold"
"send"
"snapshot"
"destroy"
"mount"
];
description = ''
Permissions granted for the {option}`services.syncoid.user` user
for local source datasets. See
@ -142,8 +168,21 @@ in
localTargetAllow = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ "change-key" "compression" "create" "mount" "mountpoint" "receive" "rollback" ];
example = [ "create" "mount" "receive" "rollback" ];
default = [
"change-key"
"compression"
"create"
"mount"
"mountpoint"
"receive"
"rollback"
];
example = [
"create"
"mount"
"receive"
"rollback"
];
description = ''
Permissions granted for the {option}`services.syncoid.user` user
for local target datasets. See
@ -176,111 +215,116 @@ in
};
commands = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
options = {
source = lib.mkOption {
type = lib.types.str;
example = "pool/dataset";
description = ''
Source ZFS dataset. Can be either local or remote. Defaults to
the attribute name.
'';
};
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
source = lib.mkOption {
type = lib.types.str;
example = "pool/dataset";
description = ''
Source ZFS dataset. Can be either local or remote. Defaults to
the attribute name.
'';
};
target = lib.mkOption {
type = lib.types.str;
example = "user@server:pool/dataset";
description = ''
Target ZFS dataset. Can be either local
(«pool/dataset») or remote
(«user@server:pool/dataset»).
'';
};
target = lib.mkOption {
type = lib.types.str;
example = "user@server:pool/dataset";
description = ''
Target ZFS dataset. Can be either local
(«pool/dataset») or remote
(«user@server:pool/dataset»).
'';
};
recursive = lib.mkEnableOption ''the transfer of child datasets'';
recursive = lib.mkEnableOption ''the transfer of child datasets'';
sshKey = lib.mkOption {
type = with lib.types; nullOr (coercedTo path toString str);
description = ''
SSH private key file to use to login to the remote system.
Defaults to {option}`services.syncoid.sshKey` option.
'';
};
sshKey = lib.mkOption {
type = with lib.types; nullOr (coercedTo path toString str);
description = ''
SSH private key file to use to login to the remote system.
Defaults to {option}`services.syncoid.sshKey` option.
'';
};
localSourceAllow = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = ''
Permissions granted for the {option}`services.syncoid.user` user
for local source datasets. See
<https://openzfs.github.io/openzfs-docs/man/8/zfs-allow.8.html>
for available permissions.
Defaults to {option}`services.syncoid.localSourceAllow` option.
'';
};
localSourceAllow = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = ''
Permissions granted for the {option}`services.syncoid.user` user
for local source datasets. See
<https://openzfs.github.io/openzfs-docs/man/8/zfs-allow.8.html>
for available permissions.
Defaults to {option}`services.syncoid.localSourceAllow` option.
'';
};
localTargetAllow = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = ''
Permissions granted for the {option}`services.syncoid.user` user
for local target datasets. See
<https://openzfs.github.io/openzfs-docs/man/8/zfs-allow.8.html>
for available permissions.
Make sure to include the `change-key` permission if you send raw encrypted datasets,
the `compression` permission if you send raw compressed datasets, and so on.
For remote target datasets you'll have to set your remote user permissions by yourself.
'';
};
localTargetAllow = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = ''
Permissions granted for the {option}`services.syncoid.user` user
for local target datasets. See
<https://openzfs.github.io/openzfs-docs/man/8/zfs-allow.8.html>
for available permissions.
Make sure to include the `change-key` permission if you send raw encrypted datasets,
the `compression` permission if you send raw compressed datasets, and so on.
For remote target datasets you'll have to set your remote user permissions by yourself.
'';
};
sendOptions = lib.mkOption {
type = lib.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.
'';
};
sendOptions = lib.mkOption {
type = lib.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 = lib.mkOption {
type = lib.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.
'';
};
recvOptions = lib.mkOption {
type = lib.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 = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Whether to add the configured common arguments to this command.
'';
};
useCommonArgs = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Whether to add the configured common arguments to this command.
'';
};
service = lib.mkOption {
type = lib.types.attrs;
default = { };
description = ''
Systemd configuration specific to this syncoid service.
'';
};
service = lib.mkOption {
type = lib.types.attrs;
default = { };
description = ''
Systemd configuration specific to this syncoid service.
'';
};
extraArgs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "--sshport 2222" ];
description = "Extra syncoid arguments for this command.";
};
};
config = {
source = lib.mkDefault name;
sshKey = lib.mkDefault cfg.sshKey;
localSourceAllow = lib.mkDefault cfg.localSourceAllow;
localTargetAllow = lib.mkDefault cfg.localTargetAllow;
};
}));
extraArgs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "--sshport 2222" ];
description = "Extra syncoid arguments for this command.";
};
};
config = {
source = lib.mkDefault name;
sshKey = lib.mkDefault cfg.sshKey;
localSourceAllow = lib.mkDefault cfg.localSourceAllow;
localTargetAllow = lib.mkDefault cfg.localTargetAllow;
};
}
)
);
default = { };
example = lib.literalExpression ''
{
@ -310,9 +354,10 @@ in
};
};
systemd.services = lib.mapAttrs'
(name: c:
lib.nameValuePair "syncoid-${escapeUnitName name}" (lib.mkMerge [
systemd.services = lib.mapAttrs' (
name: c:
lib.nameValuePair "syncoid-${escapeUnitName name}" (
lib.mkMerge [
{
description = "Syncoid ZFS synchronization from ${c.source} to ${c.target}";
after = [ "zfs.target" ];
@ -321,25 +366,30 @@ in
path = [ "/run/booted-system/sw/bin/" ];
serviceConfig = {
ExecStartPre =
(map (buildAllowCommand c.localSourceAllow) (localDatasetName c.source)) ++
(map (buildAllowCommand c.localTargetAllow) (localDatasetName c.target));
(map (buildAllowCommand c.localSourceAllow) (localDatasetName c.source))
++ (map (buildAllowCommand c.localTargetAllow) (localDatasetName c.target));
ExecStopPost =
(map (buildUnallowCommand c.localSourceAllow) (localDatasetName c.source)) ++
(map (buildUnallowCommand c.localTargetAllow) (localDatasetName c.target));
ExecStart = lib.escapeShellArgs ([ "${cfg.package}/bin/syncoid" ]
(map (buildUnallowCommand c.localSourceAllow) (localDatasetName c.source))
++ (map (buildUnallowCommand c.localTargetAllow) (localDatasetName c.target));
ExecStart = lib.escapeShellArgs (
[ "${cfg.package}/bin/syncoid" ]
++ lib.optionals c.useCommonArgs cfg.commonArgs
++ lib.optional c.recursive "-r"
++ lib.optionals (c.sshKey != null) [ "--sshkey" c.sshKey ]
++ lib.optionals (c.sshKey != null) [
"--sshkey"
c.sshKey
]
++ c.extraArgs
++ [
"--sendoptions"
c.sendOptions
"--recvoptions"
c.recvOptions
"--no-privilege-elevation"
c.source
c.target
]);
"--sendoptions"
c.sendOptions
"--recvoptions"
c.recvOptions
"--no-privilege-elevation"
c.source
c.target
]
);
User = cfg.user;
Group = cfg.group;
StateDirectory = [ "syncoid" ];
@ -372,14 +422,23 @@ in
ProtectKernelTunables = true;
ProtectSystem = "strict";
RemoveIPC = true;
RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ];
RestrictAddressFamilies = [
"AF_UNIX"
"AF_INET"
"AF_INET6"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
RootDirectory = "/run/syncoid/${escapeUnitName name}";
RootDirectoryStartOnly = true;
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.
InaccessiblePaths = [ "-+/run/syncoid/${escapeUnitName name}" ];
MountAPIVFS = true;
@ -409,9 +468,13 @@ in
}
cfg.service
c.service
]))
cfg.commands;
]
)
) cfg.commands;
};
meta.maintainers = with lib.maintainers; [ julm lopsided98 ];
meta.maintainers = with lib.maintainers; [
julm
lopsided98
];
}