{
  config,
  lib,
  pkgs,
  ...
}: let
  inherit
    (lib)
    attrsets
    concatStringsSep
    mkEnableOption
    mkIf
    mkOption
    optional
    ;

  cfg = config.my.services.restic-backup;
  excludeArg = "--exclude-file=" + (pkgs.writeText "excludes.txt" (concatStringsSep "\n" cfg.exclude));
  makePruneOpts = pruneOpts:
    attrsets.mapAttrsToList (name: value: "--keep-${name} ${toString value}") pruneOpts;
in {
  options.my.services.restic-backup = let
    inherit (lib) types;
  in {
    enable = mkEnableOption "Enable Restic backups for this host";

    repo = mkOption {
      type = types.str;
      default = null;
      example = "/mnt/hdd";
      description = "Restic backup repo";
    };

    paths = mkOption {
      type = types.listOf types.str;
      default = [];
      example = [
        "/var/lib"
        "/home"
      ];
      description = "Paths to backup";
    };

    exclude = mkOption {
      type = types.listOf types.str;
      default = [];
      example = [
        # very large paths
        "/var/lib/docker"
        "/var/lib/systemd"
        "/var/lib/libvirt"

        # temporary files created by `cargo` and `go build`
        "**/target"
        "/home/*/go/bin"
        "/home/*/go/pkg"
      ];
      description = "Paths to exclude from backup";
    };

    prune = mkOption {
      type = types.attrs;
      default = {
        daily = 7;
        weekly = 4;
        monthly = 6;
      };
    };

    passwordFile = mkOption {
      type = types.str;
      default = "/root/restic/password";
    };

    environmentFile = mkOption {
      type = types.str;
      default = "/root/restic/creds";
    };

    timerConfig = mkOption {
      type = types.attrsOf types.str;
      default = {
        OnCalendar = "daily";
      };
    };
  };

  config = mkIf cfg.enable {
    environment.systemPackages = [pkgs.restic];

    services.restic.backups.backblaze = {
      initialize = true;

      paths = cfg.paths;

      repository = cfg.repo;
      passwordFile = cfg.passwordFile;
      environmentFile = cfg.environmentFile;

      extraBackupArgs =
        ["--verbose=1"]
        ++ optional (builtins.length cfg.exclude != 0) excludeArg;

      timerConfig = cfg.timerConfig;

      pruneOpts = makePruneOpts cfg.prune;
    };
  };
}