From 2ccaca429a0bf7dc08d09d2c5beb90f03fb61ab6 Mon Sep 17 00:00:00 2001
From: Gabriel Arazas <foo.dogsquared@gmail.com>
Date: Sat, 11 Dec 2021 13:31:28 +0800
Subject: [PATCH] Add modules

- `modules.bleachbit` for home-manager.
- `modules.hardware-setup.backup-archive` for NixOS. This might be
  converted to a generic backup service for removable devices.
---
 modules/home-manager/bleachbit.nix            | 93 +++++++++++++++++++
 .../nixos/hardware-setup/backup-archive.nix   | 77 +++++++++++++++
 2 files changed, 170 insertions(+)
 create mode 100644 modules/home-manager/bleachbit.nix
 create mode 100644 modules/nixos/hardware-setup/backup-archive.nix

diff --git a/modules/home-manager/bleachbit.nix b/modules/home-manager/bleachbit.nix
new file mode 100644
index 00000000..b7e4dd3d
--- /dev/null
+++ b/modules/home-manager/bleachbit.nix
@@ -0,0 +1,93 @@
+{ config, options, lib, pkgs, ... }:
+
+let cfg = config.modules.bleachbit;
+in {
+  options.modules.bleachbit = {
+    enable = lib.mkEnableOption "automated cleanup with Bleachbit";
+    dates = lib.mkOption {
+      type = lib.types.str;
+      description = ''
+        How often or when cleanup will occur. For most cases, it should be enough to clean it up once per month.
+
+        See systemd.time(7) to see the date format.
+      '';
+      default = "monthly";
+      example = "Fri 10:00:00";
+    };
+
+    persistent = lib.mkOption {
+      type = lib.types.bool;
+      description =
+        "Whether to enable persistence for the cleanup, allowing it to activate the next time it boots when missed.";
+      default = true;
+      example = false;
+    };
+
+    cleaners = lib.mkOption {
+      type = with lib.types; listOf str;
+      description = "List of cleaners to be used when cleaning.";
+      default = [
+        "bash.history"
+        "winetricks.temporary-files"
+        "wine.tmp"
+        "brave.history"
+        "brave.form_history"
+        "brave.passwords"
+        "chromium.form_history"
+        "chromium.history"
+        "chromium.passwords"
+        "discord.history"
+        "epiphany.passwords"
+        "firefox.forms"
+        "firefox.passwords"
+        "firefox.url_history"
+        "google_chrome.form_history"
+        "google_chrome.history"
+        "google_earth.temporary_files"
+        "google_toolbar.search_history"
+        "palemoon.forms"
+        "palemoon.passwords"
+        "palemoon.url_history"
+        "thumbnails.cache"
+        "waterfox.forms"
+        "waterfox.passwords"
+        "waterfox.url_history"
+        "zoom.logs"
+      ];
+    };
+  };
+
+  config = lib.mkIf cfg.enable {
+    systemd.user = {
+      services = {
+        hm-bleachbit-cleanup = {
+          Unit = {
+            Description = "Monthly cleanup with Bleachbit";
+            Documentation = [ "man:bleachbit(1)" "https://www.bleachbit.org" ];
+          };
+
+          Service = {
+            Restart = "on-failure";
+            ExecStart = "${pkgs.bleachbit}/bin/bleachbit --clean ${
+                lib.concatStringsSep " " cfg.cleaners
+              }";
+          };
+        };
+      };
+
+      timers = {
+        hm-bleachbit-cleanup = {
+          Unit = {
+            Description = "Periodic clean with Bleachbit";
+            Documentation = [ "man:bleachbit(1)" "https://www.bleachbit.org" ];
+          };
+
+          Timer = {
+            OnCalendar = cfg.dates;
+            Persistent = cfg.persistent;
+          };
+        };
+      };
+    };
+  };
+}
diff --git a/modules/nixos/hardware-setup/backup-archive.nix b/modules/nixos/hardware-setup/backup-archive.nix
new file mode 100644
index 00000000..ab7712c3
--- /dev/null
+++ b/modules/nixos/hardware-setup/backup-archive.nix
@@ -0,0 +1,77 @@
+# This is my external hard drive.
+{ config, options, lib, pkgs, ... }:
+
+# TODO: Make this a generic service.
+#       There are multiple external storage drives now.
+let
+  cfg = config.modules.hardware-setup.backup-archive;
+in {
+  options.modules.hardware-setup.backup-archive.enable = lib.mkEnableOption "external hard drive and automated backup service with BorgBackup";
+
+  config = lib.mkIf cfg.enable {
+    assertions = [{
+      assertion = config.modules.agenix.enable;
+      message = "Agenix module is not enabled.";
+    }];
+
+    age.secrets.archive-password.file = ../../../secrets/archive/password;
+    fileSystems."/mnt/external-storage" = {
+      device = "/dev/disk/by-uuid/665A391C5A38EB07";
+      fsType = "ntfs";
+      noCheck = true;
+      options = [
+        "nofail"
+        "noauto"
+        "user"
+
+        # See systemd.mount.5 and systemd.automount.5 manual page for more
+        # details.
+        "x-systemd.automount"
+        "x-systemd.device-timeout=2"
+        "x-systemd.idle-timeout=2"
+      ];
+    };
+
+    services.borgbackup.jobs.external-storage = {
+      dateFormat = "%F-%H-%M-%S-%z";
+      doInit = false;
+      removableDevice = true;
+      paths = [
+        "/home/*/.config/environment.d"
+        "/home/*/.config/systemd"
+        "/home/*/.gnupg"
+        "/home/*/.password-store"
+        "/home/*/.ssh"
+        "/home/*/.thunderbird"
+        "/home/*/dotfiles"
+        "/home/*/library"
+      ];
+      exclude = [
+        "*/.cache"
+        "*.pyc"
+        "*/node_modules"
+        "*/.next"
+        "*/result"
+        "projects/software/*/build"
+        "projects/software/*/target"
+      ];
+      repo = "/mnt/external-storage/backups";
+      encryption = {
+        mode = "repokey";
+        passCommand = "cat ${config.age.secrets.archive-password.path}";
+      };
+      compression = "lz4";
+      prune = {
+        prefix = "{hostname}-";
+        keep = {
+          within = "1w"; # Keep all archives from the last week.
+          daily = 30;
+          weekly = 4;
+          monthly = -1; # Keep at least one archive for each month.
+          yearly = 3;
+        };
+      };
+      startAt = "04/8:00:00"; # Every 8 hours starting at 04:00.
+    };
+  };
+}