aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--modules/backups.nix210
-rw-r--r--modules/default.nix2
-rw-r--r--modules/nas-client.nix84
3 files changed, 0 insertions, 296 deletions
diff --git a/modules/backups.nix b/modules/backups.nix
deleted file mode 100644
index 78b3144..0000000
--- a/modules/backups.nix
+++ /dev/null
@@ -1,210 +0,0 @@
-# Some examples for how to use this module
-#
-# Host with media files - backup /media only locally
-# my.modules.backups = {
-# enable = true;
-# passwordFile = config.age.secrets.restic_password.path
-# local.paths = [ "/media" "/home" "/var/lib/important" ];
-# remote.paths = [ "/home" "/var/lib/important" ]; # Excludes /media
-# };
-#
-# Another example - different exclusions for local vs remote
-# my.modules.backups = {
-# enable = true;
-# passwordFile = config.age.secrets.restic_password.path
-# local.paths = [ "/home" "/var/cache/downloads" ];
-# local.exclude = [ "*.tmp" ];
-# remote.paths = [ "/home" ]; # Skip cache directory for remote
-# remote.exclude = [ "*.tmp" "*.log" ]; # More aggressive exclusions for remote
-# };
-{
- pkgs,
- config,
- lib,
- ...
-}:
-let
- cfg = config.my.modules.backups;
-
- # Helper scripts for easy backup access
- restic-local = pkgs.writeShellScriptBin "restic-local" ''
- export RESTIC_REPOSITORY="${cfg.localBasePath}/${config.networking.hostName}"
- export RESTIC_PASSWORD_FILE="${cfg.passwordFile}"
- exec ${pkgs.restic}/bin/restic "$@"
- '';
-
- restic-remote = pkgs.writeShellScriptBin "restic-remote" ''
- export RESTIC_REPOSITORY="${cfg.remoteBaseRepository}:/${config.networking.hostName}/"
- export RESTIC_PASSWORD_FILE="${cfg.passwordFile}"
- ${lib.optionalString (cfg.remote.environmentFile != null) ''
- source ${cfg.remote.environmentFile}
- ''}
- exec ${pkgs.restic}/bin/restic "$@"
- '';
-
- # Common backup options shared between local and remote
- backupOptions = {
- paths = lib.mkOption {
- type = lib.types.listOf lib.types.str;
- default = [ ];
- description = "Paths to backup";
- example = [
- "/home"
- "/var/lib/important-data"
- ];
- };
-
- exclude = lib.mkOption {
- type = lib.types.listOf lib.types.str;
- default = [ ];
- description = "Paths to exclude from backup";
- example = [
- "*.tmp"
- "/var/cache"
- ];
- };
-
- extraBackupArgs = lib.mkOption {
- type = lib.types.listOf lib.types.str;
- default = [
- "--exclude-caches"
- "--compression=max"
- ];
- description = "Additional arguments to pass to restic backup";
- };
-
- pruneOpts = lib.mkOption {
- type = lib.types.listOf lib.types.str;
- default = [
- "--keep-daily 7"
- "--keep-weekly 4"
- "--keep-monthly 3"
- ];
- description = "Pruning options for old backups";
- };
-
- timerConfig = lib.mkOption {
- type = lib.types.attrs;
- default = {
- OnCalendar = "daily";
- RandomizedDelaySec = "5m";
- };
- description = "Systemd timer configuration";
- };
- };
-in
-{
- options.my.modules.backups = {
- enable = lib.mkEnableOption "backups";
-
- passwordFile = lib.mkOption {
- type = lib.types.str;
- default = config.age.secrets.restic_password.path;
- description = "Path to file containing restic repository password";
- example = "/run/secrets/restic-password";
- };
-
- localBasePath = lib.mkOption {
- type = lib.types.str;
- default = "/data/backups";
- description = "Base path for local backup repositories";
- example = "/mnt/backup-drive/backups";
- };
-
- remoteBaseRepository = lib.mkOption {
- type = lib.types.str;
- default = "gs:fcuny-infra-backups";
- description = "Base repository URL for remote backups";
- example = "s3:my-backup-bucket";
- };
-
- local = backupOptions;
-
- remote = backupOptions // {
- timerConfig = lib.mkOption {
- type = lib.types.attrs;
- default = {
- OnCalendar = "daily";
- # No randomized delay for remote to avoid overlap with local
- };
- description = "Systemd timer configuration for remote backups";
- };
-
- googleProjectId = lib.mkOption {
- type = lib.types.nullOr lib.types.str;
- default = "fcuny-infra";
- description = "Google Cloud project ID for GCS backups";
- example = "my-backup-project";
- };
-
- googleCredentialsFile = lib.mkOption {
- type = lib.types.nullOr lib.types.str;
- default = config.age.secrets.restic_gcs_credentials.path;
- description = "Path to Google Cloud service account credentials file";
- example = "/run/secrets/gcs-credentials";
- };
-
- environmentFile = lib.mkOption {
- type = lib.types.nullOr lib.types.path;
- default =
- if cfg.remote.googleProjectId != null && cfg.remote.googleCredentialsFile != null then
- pkgs.writeText "restic-gcs-env" ''
- GOOGLE_PROJECT_ID=${cfg.remote.googleProjectId}
- GOOGLE_APPLICATION_CREDENTIALS=${cfg.remote.googleCredentialsFile}
- ''
- else
- null;
- description = "Environment file for remote backup authentication";
- };
- };
-
- helpers = lib.mkOption {
- type = lib.types.bool;
- default = true;
- description = "Install helper scripts (restic-local, restic-remote)";
- };
- };
-
- config = lib.mkIf cfg.enable {
- environment.systemPackages = [
- pkgs.restic
- ]
- ++ lib.optionals cfg.helpers [
- restic-local
- restic-remote
- ];
-
- services.restic.backups = lib.mkMerge [
- # Local backup configuration - only if paths are specified
- (lib.mkIf (cfg.local.paths != [ ]) {
- local = {
- initialize = true;
- repository = "${cfg.localBasePath}/${config.networking.hostName}";
- passwordFile = cfg.passwordFile;
- paths = cfg.local.paths;
- exclude = cfg.local.exclude;
- extraBackupArgs = cfg.local.extraBackupArgs;
- timerConfig = cfg.local.timerConfig;
- pruneOpts = cfg.local.pruneOpts;
- };
- })
-
- # Remote backup configuration - only if paths are specified
- (lib.mkIf (cfg.remote.paths != [ ]) {
- remote = {
- initialize = true;
- repository = "${cfg.remoteBaseRepository}:/${config.networking.hostName}/";
- passwordFile = cfg.passwordFile;
- paths = cfg.remote.paths;
- exclude = cfg.remote.exclude;
- extraBackupArgs = cfg.remote.extraBackupArgs;
- timerConfig = cfg.remote.timerConfig;
- pruneOpts = cfg.remote.pruneOpts;
- }
- // lib.optionalAttrs (cfg.remote.environmentFile != null) {
- environmentFile = toString cfg.remote.environmentFile;
- };
- })
- ];
- };
-}
diff --git a/modules/default.nix b/modules/default.nix
index 756d704..d6d7b65 100644
--- a/modules/default.nix
+++ b/modules/default.nix
@@ -1,10 +1,8 @@
{ ... }:
{
imports = [
- ./backups.nix
./home-manager.nix
./host-config.nix
- ./nas-client.nix
./ssh.nix
./user.nix
];
diff --git a/modules/nas-client.nix b/modules/nas-client.nix
deleted file mode 100644
index fe0952e..0000000
--- a/modules/nas-client.nix
+++ /dev/null
@@ -1,84 +0,0 @@
-{
- config,
- lib,
- pkgs,
- ...
-}:
-
-let
- cfg = config.my.modules.nas-client;
-in
-{
- options.my.modules.nas-client = with lib; {
- enable = mkEnableOption "NAS client";
-
- volumes = mkOption {
- type = types.attrsOf (
- types.submodule {
- options = {
- server = mkOption {
- type = types.str;
- example = "nas";
- description = "Hostname of the server to connect to.";
- };
- remotePath = mkOption {
- type = types.str;
- example = "data";
- description = "Remote path on the NAS to mount.";
- };
- mountPoint = mkOption {
- type = types.str;
- description = "Local directory where the volume will be mounted.";
- };
- uid = mkOption {
- type = types.int;
- default = 1000;
- description = "User ID for mounted files.";
- };
- gid = mkOption {
- type = types.int;
- default = 1000;
- description = "Group ID for mounted files.";
- };
- options = mkOption {
- type = types.str;
- default = "rw";
- description = "Additional mount options.";
- };
- };
- }
- );
- default = { };
- description = "NAS volumes to mount.";
- };
- };
-
- config = lib.mkIf cfg.enable {
- boot.kernelModules = [
- "cifs"
- "cmac"
- "sha256"
- ];
-
- # this is required to get the credentials options to work
- environment.systemPackages = [ pkgs.cifs-utils ];
-
- systemd.mounts = lib.mapAttrsToList (name: volume: {
- description = "Mount for NAS volume ${name}";
- what = "//${volume.server}/${volume.remotePath}";
- where = volume.mountPoint;
- unitConfig = {
- # This ensures it uses mount.cifs
- Type = "cifs";
- };
- type = "cifs"; # Explicitly specify CIFS type otherwise we ran into issues when using the credentials file option
- options = "credentials=${config.age.secrets.nas_client_credentials.path},uid=${toString volume.uid},gid=${toString volume.gid},${volume.options}";
- }) cfg.volumes;
-
- systemd.automounts = lib.mapAttrsToList (name: volume: {
- description = "Automount for NAS volume ${name}";
- where = volume.mountPoint;
- wantedBy = [ "multi-user.target" ];
- }) cfg.volumes;
- };
-}