diff options
author | Silvan Mosberger <infinisil@icloud.com> | 2019-03-04 01:22:29 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-04 01:22:29 +0100 |
commit | 8c4babb8ba22a9130560c207a0fcb2612b589d6c (patch) | |
tree | a77bebe46b3845398d27dfd9003d3e6b54eb6339 /nixos | |
parent | 2c613a48ca8df48b86667a04d55b02e7a847e67a (diff) | |
parent | 7a878660a7f045a03cfdeae2acda3622adaacc4e (diff) | |
download | nixlib-8c4babb8ba22a9130560c207a0fcb2612b589d6c.tar nixlib-8c4babb8ba22a9130560c207a0fcb2612b589d6c.tar.gz nixlib-8c4babb8ba22a9130560c207a0fcb2612b589d6c.tar.bz2 nixlib-8c4babb8ba22a9130560c207a0fcb2612b589d6c.tar.lz nixlib-8c4babb8ba22a9130560c207a0fcb2612b589d6c.tar.xz nixlib-8c4babb8ba22a9130560c207a0fcb2612b589d6c.tar.zst nixlib-8c4babb8ba22a9130560c207a0fcb2612b589d6c.zip |
Merge pull request #53463 from OlivierMarty/master
nixos/duplicity: init
Diffstat (limited to 'nixos')
-rw-r--r-- | nixos/modules/module-list.nix | 1 | ||||
-rw-r--r-- | nixos/modules/services/backup/duplicity.nix | 141 |
2 files changed, 142 insertions, 0 deletions
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 2ddc38d6c24a..5b95fc8ecc39 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -189,6 +189,7 @@ ./services/backup/duplicati.nix ./services/backup/crashplan.nix ./services/backup/crashplan-small-business.nix + ./services/backup/duplicity.nix ./services/backup/mysql-backup.nix ./services/backup/postgresql-backup.nix ./services/backup/restic.nix diff --git a/nixos/modules/services/backup/duplicity.nix b/nixos/modules/services/backup/duplicity.nix new file mode 100644 index 000000000000..a8d564248623 --- /dev/null +++ b/nixos/modules/services/backup/duplicity.nix @@ -0,0 +1,141 @@ +{ config, lib, pkgs, ...}: + +with lib; + +let + cfg = config.services.duplicity; + + stateDirectory = "/var/lib/duplicity"; + + localTarget = if hasPrefix "file://" cfg.targetUrl + then removePrefix "file://" cfg.targetUrl else null; + +in { + options.services.duplicity = { + enable = mkEnableOption "backups with duplicity"; + + root = mkOption { + type = types.path; + default = "/"; + description = '' + Root directory to backup. + ''; + }; + + include = mkOption { + type = types.listOf types.str; + default = []; + example = [ "/home" ]; + description = '' + List of paths to include into the backups. See the FILE SELECTION + section in <citerefentry><refentrytitle>duplicity</refentrytitle> + <manvolnum>1</manvolnum></citerefentry> for details on the syntax. + ''; + }; + + exclude = mkOption { + type = types.listOf types.str; + default = []; + description = '' + List of paths to exclude from backups. See the FILE SELECTION section in + <citerefentry><refentrytitle>duplicity</refentrytitle> + <manvolnum>1</manvolnum></citerefentry> for details on the syntax. + ''; + }; + + targetUrl = mkOption { + type = types.str; + example = "s3://host:port/prefix"; + description = '' + Target url to backup to. See the URL FORMAT section in + <citerefentry><refentrytitle>duplicity</refentrytitle> + <manvolnum>1</manvolnum></citerefentry> for supported urls. + ''; + }; + + secretFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Path of a file containing secrets (gpg passphrase, access key...) in + the format of EnvironmentFile as described by + <citerefentry><refentrytitle>systemd.exec</refentrytitle> + <manvolnum>5</manvolnum></citerefentry>. For example: + <programlisting> + PASSPHRASE=<replaceable>...</replaceable> + AWS_ACCESS_KEY_ID=<replaceable>...</replaceable> + AWS_SECRET_ACCESS_KEY=<replaceable>...</replaceable> + </programlisting> + ''; + }; + + frequency = mkOption { + type = types.nullOr types.str; + default = "daily"; + description = '' + Run duplicity with the given frequency (see + <citerefentry><refentrytitle>systemd.time</refentrytitle> + <manvolnum>7</manvolnum></citerefentry> for the format). + If null, do not run automatically. + ''; + }; + + extraFlags = mkOption { + type = types.listOf types.str; + default = []; + example = [ "--full-if-older-than" "1M" ]; + description = '' + Extra command-line flags passed to duplicity. See + <citerefentry><refentrytitle>duplicity</refentrytitle> + <manvolnum>1</manvolnum></citerefentry>. + ''; + }; + }; + + config = mkIf cfg.enable { + systemd = { + services.duplicity = { + description = "backup files with duplicity"; + + environment.HOME = stateDirectory; + + serviceConfig = { + ExecStart = '' + ${pkgs.duplicity}/bin/duplicity ${escapeShellArgs ( + [ + cfg.root + cfg.targetUrl + "--archive-dir" stateDirectory + ] + ++ concatMap (p: [ "--include" p ]) cfg.include + ++ concatMap (p: [ "--exclude" p ]) cfg.exclude + ++ cfg.extraFlags)} + ''; + PrivateTmp = true; + ProtectSystem = "strict"; + ProtectHome = "read-only"; + StateDirectory = baseNameOf stateDirectory; + } // optionalAttrs (localTarget != null) { + ReadWritePaths = localTarget; + } // optionalAttrs (cfg.secretFile != null) { + EnvironmentFile = cfg.secretFile; + }; + } // optionalAttrs (cfg.frequency != null) { + startAt = cfg.frequency; + }; + + tmpfiles.rules = optional (localTarget != null) "d ${localTarget} 0700 root root -"; + }; + + assertions = singleton { + # Duplicity will fail if the last file selection option is an include. It + # is not always possible to detect but this simple case can be caught. + assertion = cfg.include != [] -> cfg.exclude != [] || cfg.extraFlags != []; + message = '' + Duplicity will fail if you only specify included paths ("Because the + default is to include all files, the expression is redundant. Exiting + because this probably isn't what you meant.") + ''; + }; + }; +} |