{ config, pkgs, lib, inputs, ... }: with lib; let cfg = config.custom.misc.backup; in { options.custom.misc.backup = { enable = mkEnableOption "Enables backup"; small = lib.mkOption { type = types.listOf types.str; description = "paths to include in the small backup"; }; medium = lib.mkOption { type = types.listOf types.str; default = cfg.small; description = "paths to include in the medium backup"; }; large = lib.mkOption { type = types.listOf types.str; default = cfg.small // cfg.medium; description = "paths to include in the large backup"; }; excludePaths = lib.mkOption { type = types.listOf types.str; default = [ "**/Cache" "**/.cache" "**/__pycache__" "**/node_modules" "**/venv" "*.o" "*.out" ]; description = "paths to exclude from the backup"; }; excludePathsRemote = lib.mkOption { type = types.listOf types.str; default = cfg.excludePaths ++ [ "**/dont_remotebackup" ]; description = "paths to exclude from the remote backup"; }; }; config = let checkStorageSpace = pkgs.writeShellApplication { name = "checkBackupStorageSpace"; text = '' # Check how much space is used by the backup paths echo "Checking storage space (small) with excluded paths..." du -sch ${ builtins.concatStringsSep " " (map (x: "--exclude=" + x) cfg.excludePaths) } ${builtins.concatStringsSep " " cfg.small} echo "Checking storage space (small) with excluded paths (remote)..." du -sch ${ builtins.concatStringsSep " " (map (x: "--exclude=" + x) cfg.excludePathsRemote) } ${builtins.concatStringsSep " " cfg.small} echo "Checking storage space (medium) with excluded paths..." du -sch ${ builtins.concatStringsSep " " (map (x: "--exclude=" + x) cfg.excludePaths) } ${builtins.concatStringsSep " " cfg.medium} echo "Checking storage space (medium) with excluded paths (remote)..." du -sch ${ builtins.concatStringsSep " " (map (x: "--exclude=" + x) cfg.excludePathsRemote) } ${builtins.concatStringsSep " " cfg.medium} echo "Checking storage space (full) with excluded paths..." du -sch ${ builtins.concatStringsSep " " (map (x: "--exclude=" + x) cfg.excludePaths) } ${builtins.concatStringsSep " " cfg.large} echo "Checking storage space (full) with excluded paths (remote)..." du -sch ${ builtins.concatStringsSep " " (map (x: "--exclude=" + x) cfg.excludePathsRemote) } ${builtins.concatStringsSep " " cfg.large} ''; }; cli = "${pkgs.internxt-cli}/bin/internxt"; startInternxtWebdav = pkgs.writeShellApplication { name = "startInternxtWebdav"; excludeShellChecks = [ "SC1091" ]; text = '' set +o pipefail set +o errexit #don't exit on error to allow checking login status LOGGED_IN=$(${cli} whoami | grep "You are logged in") if [ -z "$LOGGED_IN" ]; then if [ -z "$USERNAME" ] || [ -z "$PASSWORD" ]; then set -a; source ${config.age.secrets.restic-internxt.path}; set +a fi ${cli} login-legacy --non-interactive -e "$USERNAME" -p "$PASSWORD" LOGGED_IN=$(${cli} whoami | grep "You are logged in") if [ -z "$LOGGED_IN" ]; then echo "Internxt CLI login failed. Aborting backup." exit 1 fi fi WEBDAV_ENABLED=$(${cli} webdav status | grep -c "status: online") if [ "$WEBDAV_ENABLED" -eq 0 ]; then ${cli} webdav enable WEBDAV_ENABLED=$(${cli} webdav status | grep -c "status: online") if [ "$WEBDAV_ENABLED" -eq 0 ]; then echo "Internxt WebDAV enable failed. Aborting backup." exit 1 fi fi ''; }; stopInternxtWebdav = pkgs.writeShellApplication { name = "stopInternxtWebdav"; text = '' set +o errexit WEBDAV_ENABLED=$(${cli} webdav status | grep -c "status: online") if [ "$WEBDAV_ENABLED" -eq 1 ]; then ${cli} webdav disable fi ''; }; in mkIf cfg.enable { environment.systemPackages = [ checkStorageSpace startInternxtWebdav stopInternxtWebdav ]; age.secrets.restic-pw = { file = ../../secrets/restic-pw.age; }; age.secrets.restic-s3 = { file = ../../secrets/restic-s3.age; }; age.secrets.restic-gdrive = { file = ../../secrets/restic-gdrive.age; }; age.secrets.restic-internxt = { file = ../../secrets/restic-internxt.age; }; services.restic = { backups = { #localbackup = { # initialize = true; # passwordFile = config.age.secrets.restic-pw.path; # exclude = cfg.excludePaths; # paths = cfg.large; # pruneOpts = [ "--keep-daily 7" "--keep-weekly 3" "--keep-monthly 3" "--keep-yearly 3" ]; # repository = "/mnt/2tb/restic"; #}; localbackup-1tb-ssd = { initialize = true; passwordFile = config.age.secrets.restic-pw.path; exclude = cfg.excludePaths; paths = cfg.large; timerConfig = { OnCalendar = "04:00"; Persistent = true; }; pruneOpts = [ "--keep-daily 7" "--keep-weekly 3" "--keep-monthly 3" "--keep-yearly 3" ]; repository = "/1tbssd/restic"; }; localbackup-2tb-hdd = { initialize = true; passwordFile = config.age.secrets.restic-pw.path; exclude = cfg.excludePaths; paths = cfg.large; timerConfig = { OnCalendar = "04:00"; Persistent = true; }; pruneOpts = [ "--keep-daily 7" "--keep-weekly 3" "--keep-monthly 3" "--keep-yearly 3" ]; repository = "/hdd/restic"; }; #localbackup-1tb = { # initialize = true; # passwordFile = config.age.secrets.restic-pw.path; # exclude = cfg.excludePaths; # paths = cfg.large; # repository = "/mnt/1tb/restic"; # pruneOpts = [ "--keep-daily 5" "--keep-weekly 3" "--keep-monthly 3" "--keep-yearly 3" ]; # timerConfig = { # OnCalendar = "*-*-03,06,09,12,15,18,21,24,27,30 02:00:00"; # Persistent = true; # }; #}; remotebackup-gdrive = { initialize = true; passwordFile = config.age.secrets.restic-pw.path; exclude = cfg.excludePathsRemote; paths = cfg.medium; rcloneConfigFile = config.age.secrets.restic-gdrive.path; repository = "rclone:it-experts:backup"; pruneOpts = [ "--keep-daily 5" "--keep-weekly 3" "--keep-monthly 3" "--keep-yearly 3" ]; timerConfig = { OnCalendar = "*-*-03,06,09,12,15,18,21,24,27,30 02:00:00"; Persistent = true; }; }; remotebackup = { initialize = true; passwordFile = config.age.secrets.restic-pw.path; environmentFile = config.age.secrets.restic-s3.path; exclude = cfg.excludePathsRemote; paths = cfg.small; pruneOpts = [ "--keep-daily 5" "--keep-weekly 3" "--keep-monthly 3" "--keep-yearly 3" ]; timerConfig = { OnCalendar = "*-*-03,06,09,12,15,18,21,24,27,30 02:00:00"; Persistent = true; }; repository = "s3:s3.us-west-002.backblazeb2.com/kop-bucket"; }; remotebackup-large = let cli = "${pkgs.internxt-cli}/bin/internxt"; in { initialize = true; passwordFile = config.age.secrets.restic-pw.path; environmentFile = config.age.secrets.restic-internxt.path; exclude = cfg.excludePathsRemote; paths = cfg.large; backupPrepareCommand = '' ${startInternxtWebdav}/bin/startInternxtWebdav ''; backupCleanupCommand = '' ${stopInternxtWebdav}/bin/stopInternxtWebdav ''; pruneOpts = [ "--keep-daily 5" "--keep-weekly 3" "--keep-monthly 3" "--keep-yearly 3" ]; timerConfig = { OnCalendar = "*-*-03,06,09,12,15,18,21,24,27,30 02:00:00"; Persistent = true; }; rcloneConfig = { type = "webdav"; url = "https://127.0.0.1:3005"; }; rcloneOptions = { "no-check-certificate" = true; }; repository = "rclone:internxt:backup"; }; }; }; }; }