+{ lib, pkgs, config, name, ... }:
+
+let
+ cfg = config.myEnv.backup;
+ varDir = "/var/lib/duply";
+ duplyProfile = profile: remote: prefix: ''
+ GPG_PW="${cfg.password}"
+ TARGET="${cfg.remotes.${remote}.remote profile.bucket}${prefix}"
+ export AWS_ACCESS_KEY_ID="${cfg.remotes.${remote}.accessKeyId}"
+ export AWS_SECRET_ACCESS_KEY="${cfg.remotes.${remote}.secretAccessKey}"
+ SOURCE="${profile.rootDir}"
+ FILENAME=".duplicity-ignore"
+ DUPL_PARAMS="$DUPL_PARAMS --exclude-if-present '$FILENAME'"
+ VERBOSITY=4
+ ARCH_DIR="${varDir}/caches"
+
+ # Do a full backup after 1 month
+ MAX_FULLBKP_AGE=1M
+ DUPL_PARAMS="$DUPL_PARAMS --allow-source-mismatch --exclude-other-filesystems --full-if-older-than $MAX_FULLBKP_AGE "
+ # Backups older than 2months are deleted
+ MAX_AGE=2M
+ # Keep 2 full backups
+ MAX_FULL_BACKUPS=2
+ MAX_FULLS_WITH_INCRS=2
+ '';
+ action = "bkp_purge_purgeFull_purgeIncr";
+ varName = k: remoteName:
+ if remoteName == "eriomem" then k else remoteName + "_" + k;
+in
+{
+ options = {
+ services.duplyBackup.enable = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ description = ''
+ Whether to enable remote backups.
+ '';
+ };
+ services.duplyBackup.profiles = lib.mkOption {
+ type = lib.types.attrsOf (lib.types.submodule {
+ options = {
+ rootDir = lib.mkOption {
+ type = lib.types.path;
+ description = ''
+ Path to backup
+ '';
+ };
+ bucket = lib.mkOption {
+ type = lib.types.str;
+ default = "immae-${name}";
+ description = ''
+ Bucket to use
+ '';
+ };
+ remotes = lib.mkOption {
+ type = lib.types.listOf lib.types.str;
+ default = ["eriomem"];
+ description = ''
+ Remotes to use for backup
+ '';
+ };
+ excludeFile = lib.mkOption {
+ type = lib.types.lines;
+ default = "";
+ description = ''
+ Content to put in exclude file
+ '';
+ };
+ };
+ });
+ };
+ };
+
+ config = lib.mkIf config.services.duplyBackup.enable {
+ system.activationScripts.backup = ''
+ install -m 0700 -o root -g root -d ${varDir} ${varDir}/caches
+ '';
+ secrets.keys = lib.listToAttrs (lib.flatten (lib.mapAttrsToList (k: v:
+ map (remote: [
+ (lib.nameValuePair "backup/${varName k remote}/conf" {
+ permissions = "0400";
+ text = duplyProfile v remote "${k}/";
+ })
+ (lib.nameValuePair "backup/${varName k remote}/exclude" {
+ permissions = "0400";
+ text = v.excludeFile;
+ })
+ (lib.nameValuePair "backup/${varName k remote}" {
+ permissions = "0500";
+ isDir = true;
+ })
+ ]) v.remotes) config.services.duplyBackup.profiles));
+
+ services.cron = {
+ enable = true;
+ systemCronJobs = let
+ backups = pkgs.writeScript "backups" ''
+ #!${pkgs.stdenv.shell}
+
+ ${builtins.concatStringsSep "\n" (lib.flatten (lib.mapAttrsToList (k: v:
+ map (remote: [
+ ''
+ touch ${varDir}/${varName k remote}.log
+ ${pkgs.duply}/bin/duply ${config.secrets.fullPaths."backup/${varName k remote}"}/ ${action} --force >> ${varDir}/${varName k remote}.log
+ [[ $? = 0 ]] || echo -e "Error when doing backup for ${varName k remote}, see above\n---------------------------------------" >&2
+ ''
+ ]) v.remotes
+ ) config.services.duplyBackup.profiles))}
+ '';
+ in
+ [
+ "0 2 * * * root ${backups}"
+ ];
+
+ };
+
+ security.pki.certificateFiles = [
+ (pkgs.fetchurl {
+ url = "http://downloads.e.eriomem.net/eriomemca.pem";
+ sha256 = "1ixx4c6j3m26j8dp9a3dkvxc80v1nr5aqgmawwgs06bskasqkvvh";
+ })
+ ];
+
+ myServices.monitoring.fromMasterActivatedPlugins = [ "eriomem" ];
+ myServices.monitoring.fromMasterObjects.service = [
+ {
+ service_description = "eriomem backup is up and not full";
+ host_name = config.hostEnv.fqdn;
+ use = "external-service";
+ check_command = "check_backup_eriomem";
+
+ check_interval = 120;
+ notification_interval = "1440";
+
+ servicegroups = "webstatus-backup";
+ }
+
+ {
+ service_description = "ovh backup is up and not full";
+ host_name = config.hostEnv.fqdn;
+ use = "external-service";
+ check_command = "check_ok";
+
+ check_interval = 120;
+ notification_interval = "1440";
+
+ servicegroups = "webstatus-backup";
+ }
+ ];
+ };
+}