{ config, lib, pkgs, ... }: with lib; let cfg = config.malobeo.backup; hostToCommand = (hostname: datasetNames: (map (dataset: { name = "${hostname}_${dataset.sourceDataset}"; value = { inherit hostname; inherit (dataset) sourceDataset targetDataset; }; } ) datasetNames)); peers = import ./peers.nix; enableSnapshots = cfg.snapshots != null; enableBackups = cfg.hosts != null; in { options.malobeo.backup = { enable = mkOption { type = types.bool; default = false; description = "Enable sanoid/syncoid based backup functionality"; }; snapshots = mkOption { type = types.nullOr (types.listOf types.str); default = null; description = "Automatic snapshots will be created for the given datasets"; }; hosts = mkOption { default = null; type = types.nullOr (types.attrsOf (types.listOf (types.submodule { options = { sourceDataset = mkOption { type = types.str; description = "The source that needs to be backed up"; }; targetDataset = mkOption { type = types.str; description = "The target dataset where the backup should be stored"; }; }; }))); description = '' Hostname with list of datasets to backup. This option should be defined on hosts that will store backups. It is necessary to add the machines that get backed up to known hosts. This can be done for example systemwide using programs.ssh.knownHosts."10.100.0.101" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHqp2/YiiIhai7wyScGZJ20gtrzY+lp4N/8unyRs4qhc"; Or set it for the syncoid user directly. ''; }; sshKey = mkOption { default = null; type = types.nullOr types.str; description = "Set path to ssh key used for pull backups. Otherwise default key is used"; }; }; config = mkIf (cfg.enable) { services.sanoid = mkIf (enableSnapshots) { enable = true; templates."default" = { hourly = 0; daily = 30; #keep 30 daily snapshots monthly = 6; #keep 6 monthly backups yearly = 0; autosnap = true; #take snapshots automatically autoprune = true; #delete old snapshots }; datasets = builtins.listToAttrs (map (name: { inherit name; value = { useTemplate = [ "default" ]; recursive = true; }; }) cfg.snapshots); }; services.syncoid = mkIf (enableBackups) { enable = true; sshKey = cfg.sshKey; commonArgs = [ "--no-sync-snap" ]; interval = "*-*-* 04:15:00"; commands = builtins.mapAttrs (name: value: { source = "backup@${peers.${value.hostname}.address}:${value.sourceDataset}"; target = "${value.targetDataset}"; sendOptions = "w"; recvOptions = "\"\""; recursive = true; })(builtins.listToAttrs (builtins.concatLists (builtins.attrValues (builtins.mapAttrs hostToCommand cfg.hosts)))); }; }; }