{
  self,
  pkgs,
  lib,
  config,
  ...
}: let
  inherit (lib.lists) forEach;
  inherit (lib.strings) concatStringsSep;

  inherit (builtins) attrNames;

  inherit (config.services.secrets) secrets;
  backupSchedules = import "${self}/data/backupSchedules.nix";

  repoRoot = "s3:s3.eu-central-003.backblazeb2.com/Chaos-Backups/Restic";
in {
  environment.systemPackages = [
    # TODO: add ones in container too
    (pkgs.writeShellScriptBin "restic-all" ''
      ${concatStringsSep "\n" (forEach (attrNames config.services.restic.backups) (
        name: "restic-${name} $@"
      ))}
    '')
  ];

  services.restic.backups = {
    social = {
      user = "root";
      paths = [
        "/var/lib/gotosocial"
      ];

      repository = "${repoRoot}/Social-02";
      environmentFile = secrets.restic_backups_env.path;
      passwordFile = secrets.restic_password_social.path;
      createWrapper = true;

      pruneOpts = ["--keep-last 10"];
      timerConfig = backupSchedules.restic.medium;

      backupPrepareCommand = let
        # Because gotosocial-admin isn't a seporate package we need to generate a seperate config
        # and duplicate the wrapper for use in a systemd unit
        gotoSocialConfigFile = (pkgs.formats.yaml {}).generate "config.yml" config.services.gotosocial.settings;
        gotoSocialAdmin = "${(pkgs.writeShellScriptBin "gts-admin" ''
          exec systemd-run \
            -u gotosocial-admin.service \
            -p Group=gotosocial \
            -p User=gotosocial \
            -q -t -G --wait --service-type=exec \
            ${pkgs.gotosocial}/bin/gotosocial --config-path ${gotoSocialConfigFile} admin "$@"
        '')}/bin/gts-admin";
      in "${
        (pkgs.writeShellScriptBin "backupPrepareCommand" ''
          systemctl stop gotosocial

          ${gotoSocialAdmin} export --path /var/lib/gotosocial/gts-export.json

          ${gotoSocialAdmin} media prune all --dry-run=false

          systemctl start gotosocial
        '')
      }/bin/backupPrepareCommand";

      backupCleanupCommand = "${
        (pkgs.writeShellScriptBin "backupCleanupCommand" ''
          rm /var/lib/gotosocial/gts-export.json || true
        '')
      }/bin/backupCleanupCommand";
    };
    forgejo = {
      user = "root";
      paths = [
        "/var/lib/forgejo"
      ];

      repository = "${repoRoot}/Forgejo";
      environmentFile = secrets.restic_backups_env.path;
      passwordFile = secrets.restic_password_forgejo.path;
      createWrapper = true;

      pruneOpts = ["--keep-last 50"];
      timerConfig = backupSchedules.restic.high;
    };
    radicale = {
      user = "root";
      paths = [
        "/var/lib/radicale"
      ];

      repository = "${repoRoot}/Radicale";
      environmentFile = secrets.restic_backups_env.path;
      passwordFile = secrets.restic_password_radicale.path;
      createWrapper = true;

      pruneOpts = ["--keep-last 50"];
      timerConfig = backupSchedules.restic.high;
    };
    vault = {
      user = "root";
      paths = [
        "/var/lib/vault"
      ];

      repository = "${repoRoot}/Vault";
      environmentFile = secrets.restic_backups_env.path;
      passwordFile = secrets.restic_password_vault.path;
      createWrapper = true;

      timerConfig = backupSchedules.restic.high;
    };
  };
}