diff --git a/machines/modules/malobeo/backup.nix b/machines/modules/malobeo/backup.nix new file mode 100644 index 0000000..9ae4b30 --- /dev/null +++ b/machines/modules/malobeo/backup.nix @@ -0,0 +1,84 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.malobeo.backup; + newfunc = (hostname: datasetNames: (map (dataset: { name = "${hostname}_${dataset.sourceDataset}"; value = { inherit hostname; inherit dataset; }; } ) datasetNames)); + peers = import ./peers.nix; +in +{ + options.malobeo.backup = { + enable = mkOption { + type = types.bool; + default = false; + description = "Enable sharing metrics"; + }; + + snapshots = mkOption { + type = types.listOf types.str; + default = []; + description = "Automatic snapshots will be created for the given datasets"; + }; + + #TODO: instead listof str we need dataset here to declare the dataset name on the source host + # and also the dataset name on target host (which stores the backups) + hosts = mkOption { + type = types.attrsOf (types.listOf (types.submodule { + options = { + sourceDataset = mkOption { + type = types.str; + }; + targetDataset = mkOption { + type = types.str; + }; + }; + })); + description = "Hostname with list of datasets to backup."; + }; + }; + + config = mkIf (cfg.enable) { + services.sanoid = { + 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 = with config; { + enable = true; + + sshKey = sops.secrets.backup_key.path; + + commonArgs = [ + "--no-sync-snap" + ]; + + interval = "*-*-* 04:15:00"; + + commands = builtins.mapAttrs (name: value: { + source = "backup@${peers.${value.hostname}.address}:${value.dataset.sourceDataset}"; + target = "${value.dataset.targetDataset}"; + sendOptions = "w"; + recvOptions = "\"\""; + recursive = true; + })(builtins.listToAttrs (builtins.concatLists (builtins.attrValues (builtins.mapAttrs newfunc cfg.hosts)))); + }; + + sops.secrets.backup_key = { + owner = config.services.syncoid.user; + key = "backup_key"; + }; + }; +} diff --git a/outputs.nix b/outputs.nix index 4f341e6..b7c2db6 100644 --- a/outputs.nix +++ b/outputs.nix @@ -116,6 +116,7 @@ in (utils.lib.eachSystem (builtins.filter filter_system utils.lib.defaultSystems metrics.imports = [ ./machines/modules/malobeo/metrics.nix ]; disko.imports = [ ./machines/modules/disko ]; users.imports = [ ./machines/modules/malobeo/users.nix ]; + backup.imports = [ ./machines/modules/malobeo/backup.nix ]; }; hydraJobs = nixpkgs.lib.mapAttrs (_: nixpkgs.lib.hydraJob) (