nixos/snapraid: init

lunik1 145a3d08 0b9a7ed2

Changed files
+242
nixos
doc
manual
from_md
release-notes
release-notes
modules
+7
nixos/doc/manual/from_md/release-notes/rl-2111.section.xml
···
<link linkend="opt-services.vikunja.enable">services.vikunja</link>.
</para>
</listitem>
</itemizedlist>
</section>
<section xml:id="sec-release-21.11-incompatibilities">
···
<link linkend="opt-services.vikunja.enable">services.vikunja</link>.
</para>
</listitem>
+
<listitem>
+
<para>
+
<link xlink:href="https://www.snapraid.it/">snapraid</link>, a
+
backup program for disk arrays. Available as
+
<link linkend="opt-snapraid.enable">snapraid</link>.
+
</para>
+
</listitem>
</itemizedlist>
</section>
<section xml:id="sec-release-21.11-incompatibilities">
+4
nixos/doc/manual/release-notes/rl-2111.section.md
···
- [vikunja](https://vikunja.io), a to-do list app. Available as [services.vikunja](#opt-services.vikunja.enable).
## Backward Incompatibilities {#sec-release-21.11-incompatibilities}
- The `staticjinja` package has been upgraded from 1.0.4 to 3.0.1
···
- [vikunja](https://vikunja.io), a to-do list app. Available as [services.vikunja](#opt-services.vikunja.enable).
+
- [snapraid](https://www.snapraid.it/), a backup program for disk arrays.
+
Available as [snapraid](#opt-snapraid.enable).
+
+
## Backward Incompatibilities {#sec-release-21.11-incompatibilities}
- The `staticjinja` package has been upgraded from 1.0.4 to 3.0.1
+1
nixos/modules/module-list.nix
···
./tasks/network-interfaces-systemd.nix
./tasks/network-interfaces-scripted.nix
./tasks/scsi-link-power-management.nix
./tasks/swraid.nix
./tasks/trackpoint.nix
./tasks/powertop.nix
···
./tasks/network-interfaces-systemd.nix
./tasks/network-interfaces-scripted.nix
./tasks/scsi-link-power-management.nix
+
./tasks/snapraid.nix
./tasks/swraid.nix
./tasks/trackpoint.nix
./tasks/powertop.nix
+230
nixos/modules/tasks/snapraid.nix
···
···
+
{ config, lib, pkgs, ... }:
+
+
with lib;
+
+
let cfg = config.snapraid;
+
in
+
{
+
options.snapraid = with types; {
+
enable = mkEnableOption "SnapRAID";
+
dataDisks = mkOption {
+
default = { };
+
example = {
+
d1 = "/mnt/disk1/";
+
d2 = "/mnt/disk2/";
+
d3 = "/mnt/disk3/";
+
};
+
description = "SnapRAID data disks.";
+
type = attrsOf str;
+
};
+
parityFiles = mkOption {
+
default = [ ];
+
example = [
+
"/mnt/diskp/snapraid.parity"
+
"/mnt/diskq/snapraid.2-parity"
+
"/mnt/diskr/snapraid.3-parity"
+
"/mnt/disks/snapraid.4-parity"
+
"/mnt/diskt/snapraid.5-parity"
+
"/mnt/disku/snapraid.6-parity"
+
];
+
description = "SnapRAID parity files.";
+
type = listOf str;
+
};
+
contentFiles = mkOption {
+
default = [ ];
+
example = [
+
"/var/snapraid.content"
+
"/mnt/disk1/snapraid.content"
+
"/mnt/disk2/snapraid.content"
+
];
+
description = "SnapRAID content list files.";
+
type = listOf str;
+
};
+
exclude = mkOption {
+
default = [ ];
+
example = [ "*.unrecoverable" "/tmp/" "/lost+found/" ];
+
description = "SnapRAID exclude directives.";
+
type = listOf str;
+
};
+
touchBeforeSync = mkOption {
+
default = true;
+
example = false;
+
description =
+
"Whether <command>snapraid touch</command> should be run before <command>snapraid sync</command>.";
+
type = bool;
+
};
+
sync.interval = mkOption {
+
default = "01:00";
+
example = "daily";
+
description = "How often to run <command>snapraid sync</command>.";
+
type = str;
+
};
+
scrub = {
+
interval = mkOption {
+
default = "Mon *-*-* 02:00:00";
+
example = "weekly";
+
description = "How often to run <command>snapraid scrub</command>.";
+
type = str;
+
};
+
plan = mkOption {
+
default = 8;
+
example = 5;
+
description =
+
"Percent of the array that should be checked by <command>snapraid scrub</command>.";
+
type = int;
+
};
+
olderThan = mkOption {
+
default = 10;
+
example = 20;
+
description =
+
"Number of days since data was last scrubbed before it can be scrubbed again.";
+
type = int;
+
};
+
};
+
extraConfig = mkOption {
+
default = "";
+
example = ''
+
nohidden
+
blocksize 256
+
hashsize 16
+
autosave 500
+
pool /pool
+
'';
+
description = "Extra config options for SnapRAID.";
+
type = lines;
+
};
+
};
+
+
config =
+
let
+
nParity = builtins.length cfg.parityFiles;
+
mkPrepend = pre: s: pre + s;
+
in
+
mkIf cfg.enable {
+
assertions = [
+
{
+
assertion = nParity <= 6;
+
message = "You can have no more than six SnapRAID parity files.";
+
}
+
{
+
assertion = builtins.length cfg.contentFiles >= nParity + 1;
+
message =
+
"There must be at least one SnapRAID content file for each SnapRAID parity file plus one.";
+
}
+
];
+
+
environment = {
+
systemPackages = with pkgs; [ snapraid ];
+
+
etc."snapraid.conf" = {
+
text = with cfg;
+
let
+
prependData = mkPrepend "data ";
+
prependContent = mkPrepend "content ";
+
prependExclude = mkPrepend "exclude ";
+
in
+
concatStringsSep "\n"
+
(map prependData
+
((mapAttrsToList (name: value: name + " " + value)) dataDisks)
+
++ zipListsWith (a: b: a + b)
+
([ "parity " ] ++ map (i: toString i + "-parity ") (range 2 6))
+
parityFiles ++ map prependContent contentFiles
+
++ map prependExclude exclude) + "\n" + extraConfig;
+
};
+
};
+
+
systemd.services = with cfg; {
+
snapraid-scrub = {
+
description = "Scrub the SnapRAID array";
+
startAt = scrub.interval;
+
serviceConfig = {
+
Type = "oneshot";
+
ExecStart = "${pkgs.snapraid}/bin/snapraid scrub -p ${
+
toString scrub.plan
+
} -o ${toString scrub.olderThan}";
+
Nice = 19;
+
IOSchedulingPriority = 7;
+
CPUSchedulingPolicy = "batch";
+
+
LockPersonality = true;
+
MemoryDenyWriteExecute = true;
+
NoNewPrivileges = true;
+
PrivateDevices = true;
+
PrivateTmp = true;
+
ProtectClock = true;
+
ProtectControlGroups = true;
+
ProtectHostname = true;
+
ProtectKernelLogs = true;
+
ProtectKernelModules = true;
+
ProtectKernelTunables = true;
+
RestrictAddressFamilies = "none";
+
RestrictNamespaces = true;
+
RestrictRealtime = true;
+
RestrictSUIDSGID = true;
+
SystemCallArchitectures = "native";
+
SystemCallFilter = "@system-service";
+
SystemCallErrorNumber = "EPERM";
+
CapabilityBoundingSet = "CAP_DAC_OVERRIDE";
+
+
ProtectSystem = "strict";
+
ProtectHome = "read-only";
+
ReadWritePaths =
+
# scrub requires access to directories containing content files
+
# to remove them if they are stale
+
let
+
contentDirs = map dirOf contentFiles;
+
in
+
unique (
+
attrValues dataDisks ++ contentDirs
+
);
+
};
+
unitConfig.After = "snapraid-sync.service";
+
};
+
snapraid-sync = {
+
description = "Synchronize the state of the SnapRAID array";
+
startAt = sync.interval;
+
serviceConfig = {
+
Type = "oneshot";
+
ExecStart = "${pkgs.snapraid}/bin/snapraid sync";
+
Nice = 19;
+
IOSchedulingPriority = 7;
+
CPUSchedulingPolicy = "batch";
+
+
LockPersonality = true;
+
MemoryDenyWriteExecute = true;
+
NoNewPrivileges = true;
+
PrivateDevices = true;
+
PrivateTmp = true;
+
ProtectClock = true;
+
ProtectControlGroups = true;
+
ProtectHostname = true;
+
ProtectKernelLogs = true;
+
ProtectKernelModules = true;
+
ProtectKernelTunables = true;
+
RestrictAddressFamilies = "none";
+
RestrictNamespaces = true;
+
RestrictRealtime = true;
+
RestrictSUIDSGID = true;
+
SystemCallArchitectures = "native";
+
SystemCallFilter = "@system-service";
+
SystemCallErrorNumber = "EPERM";
+
CapabilityBoundingSet = "CAP_DAC_OVERRIDE";
+
+
ProtectSystem = "strict";
+
ProtectHome = "read-only";
+
ReadWritePaths =
+
# sync requires access to directories containing content files
+
# to remove them if they are stale
+
let
+
contentDirs = map dirOf contentFiles;
+
in
+
unique (
+
attrValues dataDisks ++ parityFiles ++ contentDirs
+
);
+
} // optionalAttrs touchBeforeSync {
+
ExecStartPre = "${pkgs.snapraid}/bin/snapraid touch";
+
};
+
};
+
};
+
};
+
}