From e1f987e83b1dca80569a5bda52ad277ed250412a Mon Sep 17 00:00:00 2001 From: Noah Masur <7386960+nmasur@users.noreply.github.com> Date: Fri, 31 Jan 2025 15:40:41 -0500 Subject: [PATCH] backups and fish functions --- .../shell/fish/functions/search-and-edit.fish | 2 +- modules/nixos/services/backups.nix | 103 ------------------ modules/nixos/services/default.nix | 46 -------- .../tools/misc/ip-check}/ip.fish | 0 pkgs/tools/misc/ip-check/package.nix | 10 ++ .../{services => programs}/dotfiles.nix | 4 +- .../modules/nmasur/presets/programs/fish.nix | 9 -- .../nmasur/presets/programs/notes/default.nix | 77 +++++++++++++ .../nmasur/presets/programs/notes}/note.fish | 4 +- .../presets/programs/notes}/syncnotes.fish | 0 .../nmasur/presets/services/calibre-web.nix | 8 +- .../nmasur/presets/services/litestream.nix | 68 ++++++++++++ .../nmasur/presets/services/restic.nix | 61 +++++++++++ 13 files changed, 225 insertions(+), 167 deletions(-) delete mode 100644 modules/nixos/services/backups.nix delete mode 100644 modules/nixos/services/default.nix rename {modules/common/shell/fish/functions => pkgs/tools/misc/ip-check}/ip.fish (100%) mode change 100644 => 100755 create mode 100644 pkgs/tools/misc/ip-check/package.nix rename platforms/home-manager/modules/nmasur/presets/{services => programs}/dotfiles.nix (91%) create mode 100644 platforms/home-manager/modules/nmasur/presets/programs/notes/default.nix rename {modules/common/shell/fish/functions => platforms/home-manager/modules/nmasur/presets/programs/notes}/note.fish (60%) rename {modules/common/shell/fish/functions => platforms/home-manager/modules/nmasur/presets/programs/notes}/syncnotes.fish (100%) create mode 100644 platforms/nixos/modules/nmasur/presets/services/litestream.nix create mode 100644 platforms/nixos/modules/nmasur/presets/services/restic.nix diff --git a/modules/common/shell/fish/functions/search-and-edit.fish b/modules/common/shell/fish/functions/search-and-edit.fish index b615d75..b5fd858 100644 --- a/modules/common/shell/fish/functions/search-and-edit.fish +++ b/modules/common/shell/fish/functions/search-and-edit.fish @@ -17,5 +17,5 @@ set vimfile ( \ ) and set line_number (echo $vimfile | tr -d '\r' | cut -d':' -f2) and set vimfile (echo $vimfile | tr -d '\r' | cut -d':' -f1) -and commandline -r "vim +$line_number $vimfile" +and commandline -r "vim +$line_number \"$vimfile\"" and commandline -f execute diff --git a/modules/nixos/services/backups.nix b/modules/nixos/services/backups.nix deleted file mode 100644 index f9220ae..0000000 --- a/modules/nixos/services/backups.nix +++ /dev/null @@ -1,103 +0,0 @@ -# This is my setup for backing up SQlite databases and other systems to S3 or -# S3-equivalent services (like Backblaze B2). - -{ config, lib, ... }: -{ - - options = { - - backup.s3 = { - endpoint = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = "S3 endpoint for backups"; - default = null; - }; - bucket = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = "S3 bucket for backups"; - default = null; - }; - accessKeyId = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = "S3 access key ID for backups"; - default = null; - }; - resticBucket = lib.mkOption { - type = lib.types.nullOr lib.types.str; - description = "S3 bucket for restic backups"; - default = null; - }; - }; - }; - - config = lib.mkIf (config.backup.s3.endpoint != null) { - - users.groups.backup = { }; - - secrets.backup = { - source = ../../../private/backup.age; - dest = "${config.secretsDirectory}/backup"; - group = "backup"; - permissions = "0440"; - }; - - users.users.litestream.extraGroups = [ "backup" ]; - - services.litestream = { - enable = true; - environmentFile = config.secrets.backup.dest; - settings = { }; - }; - - # Broken on 2024-08-23 - # https://github.com/NixOS/nixpkgs/commit/0875d0ce1c778f344cd2377a5337a45385d6ffa0 - insecurePackages = [ "litestream-0.3.13" ]; - - # Wait for secret to exist - systemd.services.litestream = { - after = [ "backup-secret.service" ]; - requires = [ "backup-secret.service" ]; - environment.AWS_ACCESS_KEY_ID = config.backup.s3.accessKeyId; - }; - - # # Backup library to object storage - # services.restic.backups.calibre = { - # user = "calibre-web"; - # repository = - # "s3://${config.backup.s3.endpoint}/${config.backup.s3.bucket}/calibre"; - # paths = [ - # "/var/books" - # "/var/lib/calibre-web/app.db" - # "/var/lib/calibre-web/gdrive.db" - # ]; - # initialize = true; - # timerConfig = { OnCalendar = "00:05:00"; }; - # environmentFile = backup.s3File; - # }; - - secrets.s3-glacier = { - source = ../../../private/s3-glacier.age; - dest = "${config.secretsDirectory}/s3-glacier"; - }; - secrets.restic = { - source = ../../../private/restic.age; - dest = "${config.secretsDirectory}/restic"; - }; - - services.restic.backups = lib.mkIf (config.backup.s3.resticBucket != null) { - default = { - repository = "s3:s3.us-east-1.amazonaws.com/${config.backup.s3.resticBucket}/restic"; - paths = [ ]; - environmentFile = config.secrets.s3-glacier.dest; - passwordFile = config.secrets.restic.dest; - pruneOpts = [ - "--keep-daily 14" - "--keep-weekly 6" - "--keep-monthly 12" - "--keep-yearly 100" - ]; - }; - }; - - }; -} diff --git a/modules/nixos/services/default.nix b/modules/nixos/services/default.nix deleted file mode 100644 index 0e1d2e9..0000000 --- a/modules/nixos/services/default.nix +++ /dev/null @@ -1,46 +0,0 @@ -# This file imports all the other files in this directory for use as modules in -# my config. - -{ ... }: -{ - - imports = [ - ./actualbudget.nix - ./audiobookshelf.nix - ./arr.nix - ./backups.nix - ./bind.nix - ./caddy.nix - ./calibre.nix - ./cloudflare-tunnel.nix - ./cloudflare.nix - ./filebrowser.nix - ./identity.nix - ./immich.nix - ./irc.nix - ./gitea-runner.nix - ./gitea.nix - ./gnupg.nix - ./grafana.nix - ./honeypot.nix - ./influxdb2.nix - ./jellyfin.nix - ./keybase.nix - ./mullvad.nix - ./n8n.nix - ./netdata.nix - ./nextcloud.nix - ./ntfy.nix - ./paperless.nix - ./postgresql.nix - ./prometheus.nix - ./samba.nix - ./secrets.nix - ./sshd.nix - ./transmission.nix - ./uptime-kuma.nix - ./vaultwarden.nix - ./victoriametrics.nix - ./wireguard.nix - ]; -} diff --git a/modules/common/shell/fish/functions/ip.fish b/pkgs/tools/misc/ip-check/ip.fish old mode 100644 new mode 100755 similarity index 100% rename from modules/common/shell/fish/functions/ip.fish rename to pkgs/tools/misc/ip-check/ip.fish diff --git a/pkgs/tools/misc/ip-check/package.nix b/pkgs/tools/misc/ip-check/package.nix new file mode 100644 index 0000000..048fe00 --- /dev/null +++ b/pkgs/tools/misc/ip-check/package.nix @@ -0,0 +1,10 @@ +{ pkgs, lib, ... }: + +pkgs.writers.writeFishBin "ip-check" { + makeWrapperArgs = [ + "--prefix" + "PATH" + ":" + "${lib.makeBinPath [ pkgs.curl ]}" + ]; +} builtins.readFile ./ip.fish diff --git a/platforms/home-manager/modules/nmasur/presets/services/dotfiles.nix b/platforms/home-manager/modules/nmasur/presets/programs/dotfiles.nix similarity index 91% rename from platforms/home-manager/modules/nmasur/presets/services/dotfiles.nix rename to platforms/home-manager/modules/nmasur/presets/programs/dotfiles.nix index dd2e290..9257d05 100644 --- a/platforms/home-manager/modules/nmasur/presets/services/dotfiles.nix +++ b/platforms/home-manager/modules/nmasur/presets/programs/dotfiles.nix @@ -6,13 +6,13 @@ }: let - cfg = config.nmasur.presets.services.dotfiles; + cfg = config.nmasur.presets.programs.dotfiles; in { # Allows me to make sure I can work on my dotfiles locally - options.nmasur.preset.services.dotfiles = { + options.nmasur.preset.programs.dotfiles = { enable = lib.mkEnableOption "Clone dotfiles repository"; repo = lib.mkOption { type = lib.types.str; diff --git a/platforms/home-manager/modules/nmasur/presets/programs/fish.nix b/platforms/home-manager/modules/nmasur/presets/programs/fish.nix index 601b081..c2b0b90 100644 --- a/platforms/home-manager/modules/nmasur/presets/programs/fish.nix +++ b/platforms/home-manager/modules/nmasur/presets/programs/fish.nix @@ -48,11 +48,6 @@ in description = "Tidy up JSON using jq"; body = "pbpaste | jq '.' | pbcopy"; # Need to fix for non-macOS }; - note = { - description = "Edit or create a note"; - argumentNames = "filename"; - body = builtins.readFile ./functions/note.fish; - }; recent = { description = "Open a recent file in Vim"; body = builtins.readFile ./functions/recent.fish; @@ -61,10 +56,6 @@ in description = "Search and open the relevant file in Vim"; body = builtins.readFile ./functions/search-and-edit.fish; }; - syncnotes = { - description = "Full git commit on notes"; - body = builtins.readFile ./functions/syncnotes.fish; - }; _which = { description = "Identify the path to a program in the shell"; body = "command --search (string sub --start=2 $argv)"; diff --git a/platforms/home-manager/modules/nmasur/presets/programs/notes/default.nix b/platforms/home-manager/modules/nmasur/presets/programs/notes/default.nix new file mode 100644 index 0000000..19c26a2 --- /dev/null +++ b/platforms/home-manager/modules/nmasur/presets/programs/notes/default.nix @@ -0,0 +1,77 @@ +{ + config, + pkgs, + lib, + ... +}: + +let + cfg = config.nmasur.presets.programs.notes; +in +{ + + options.nmasur.preset.programs.notes = { + enable = lib.mkEnableOption "Manage notes repository"; + repo = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "Git repo containing notes"; + default = null; + }; + path = lib.mkOption { + type = lib.types.path; + description = "Path to notes on disk"; + default = config.homePath + "/dev/personal/notes"; + }; + }; + + config = lib.mkIf cfg.enable { + + home.activation = lib.mkIf (cfg.repo != null) { + + # Always clone notes repository if it doesn't exist + clonenotes = config.lib.dag.entryAfter [ "writeBoundary" "loadkey" ] '' + if [ ! -d "${cfg.path}" ]; then + run mkdir --parents $VERBOSE_ARG $(dirname "${cfg.path}") + run ${pkgs.git}/bin/git \ + clone ${cfg.repo} "${cfg.path}" + fi + ''; + }; + + # Set a variable for notes repo, not necessary but convenient + home.sessionVariables.NOTES_PATH = cfg.path; + + programs.fish.functions = { + syncnotes = { + description = "Full git commit on notes"; + body = builtins.readFile lib.getExe ( + pkgs.writers.writeFishBin "syncnotes" { + makeWrapperArgs = [ + "--prefix" + "PATH" + ":" + "${lib.makeBinPath [ pkgs.git ]}" + ]; + } builtins.readFile ./syncnotes.fish + ); + }; + note = { + description = "Edit or create a note"; + argumentNames = "filename"; + body = builtins.readFile lib.getExe ( + pkgs.writers.writeFishBin "note" { + makeWrapperArgs = [ + "--prefix" + "PATH" + ":" + "${lib.makeBinPath [ + pkgs.vim + pkgs.fzf + ]}" + ]; + } builtins.readFile ./note.fish + ); + }; + }; + }; +} diff --git a/modules/common/shell/fish/functions/note.fish b/platforms/home-manager/modules/nmasur/presets/programs/notes/note.fish similarity index 60% rename from modules/common/shell/fish/functions/note.fish rename to platforms/home-manager/modules/nmasur/presets/programs/notes/note.fish index 58d1e29..83a0ed5 100644 --- a/modules/common/shell/fish/functions/note.fish +++ b/platforms/home-manager/modules/nmasur/presets/programs/notes/note.fish @@ -1,8 +1,8 @@ if test -n "$filename" - vim $NOTES_PATH/$filename.md + vim "$NOTES_PATH/$filename.md" else set file (ls $NOTES_PATH | fzf) if [ $status -eq 0 ] - vim $NOTES_PATH/$file + vim "$NOTES_PATH/$file" end end diff --git a/modules/common/shell/fish/functions/syncnotes.fish b/platforms/home-manager/modules/nmasur/presets/programs/notes/syncnotes.fish similarity index 100% rename from modules/common/shell/fish/functions/syncnotes.fish rename to platforms/home-manager/modules/nmasur/presets/programs/notes/syncnotes.fish diff --git a/platforms/nixos/modules/nmasur/presets/services/calibre-web.nix b/platforms/nixos/modules/nmasur/presets/services/calibre-web.nix index 80e1ee9..b632f3f 100644 --- a/platforms/nixos/modules/nmasur/presets/services/calibre-web.nix +++ b/platforms/nixos/modules/nmasur/presets/services/calibre-web.nix @@ -60,7 +60,7 @@ in users.users.${config.user}.extraGroups = [ "calibre-web" ]; # Run a backup on a schedule - systemd.timers.calibre-backup = lib.mkIf config.backups.calibre { + systemd.timers.calibre-backup = { timerConfig = { OnCalendar = "*-*-* 00:00:00"; # Once per day Unit = "calibre-backup.service"; @@ -71,7 +71,7 @@ in # Backup Calibre data to object storage systemd.services.calibre-backup = { description = "Backup Calibre data"; - environment.AWS_ACCESS_KEY_ID = config.backup.s3.accessKeyId; + environment.AWS_ACCESS_KEY_ID = config.nmasur.presets.services.litestream.s3.accessKeyId; serviceConfig = { Type = "oneshot"; User = "calibre-web"; @@ -81,8 +81,8 @@ in script = '' ${pkgs.awscli2}/bin/aws s3 sync \ ${libraryPath}/ \ - s3://${config.backup.s3.bucket}/calibre/ \ - --endpoint-url=https://${config.backup.s3.endpoint} + s3://${config.nmasur.presets.services.litestream.s3.bucket}/calibre/ \ + --endpoint-url=https://${config.nmasur.presets.services.litestream.s3.endpoint} ''; }; }; diff --git a/platforms/nixos/modules/nmasur/presets/services/litestream.nix b/platforms/nixos/modules/nmasur/presets/services/litestream.nix new file mode 100644 index 0000000..24145d1 --- /dev/null +++ b/platforms/nixos/modules/nmasur/presets/services/litestream.nix @@ -0,0 +1,68 @@ +# This is my setup for backing up SQlite databases and other systems to S3 or +# S3-equivalent services (like Backblaze B2). + +{ config, lib, ... }: + +let + cfg = config.nmasur.presets.services.litestream; +in +{ + + options.nmasur.presets.services.litestream = { + enable = lib.mkEnableOption "Litestream SQLite backups"; + s3 = { + endpoint = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "S3 endpoint for Litestream backups"; + # default = null; + }; + bucket = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "S3 bucket for Litestream backups"; + # default = null; + }; + accessKeyId = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "S3 access key ID for Litestream backups"; + # default = null; + }; + accessKeySecret = lib.mkOption { + type = lib.types.nullOr lib.types.path; + description = "S3 secret key path for Litestream backups"; + default = ../../../../../../private/backup.age; + }; + }; + }; + + config = lib.mkIf (cfg.enable) { + + users.groups.backup = { }; + + secrets.litestream-backup = { + source = cfg.s3.accessKeySecret; + dest = "${config.secretsDirectory}/backup"; + group = "backup"; + permissions = "0440"; + }; + + users.users.litestream.extraGroups = [ "backup" ]; + + services.litestream = { + enable = true; + environmentFile = config.secrets.litestream-backup.dest; + settings = { }; + }; + + # Broken on 2024-08-23 + # https://github.com/NixOS/nixpkgs/commit/0875d0ce1c778f344cd2377a5337a45385d6ffa0 + insecurePackages = [ "litestream-0.3.13" ]; + + # Wait for secret to exist + systemd.services.litestream = { + after = [ "backup-secret.service" ]; + requires = [ "backup-secret.service" ]; + environment.AWS_ACCESS_KEY_ID = cfg.s3.accessKeyId; + }; + + }; +} diff --git a/platforms/nixos/modules/nmasur/presets/services/restic.nix b/platforms/nixos/modules/nmasur/presets/services/restic.nix new file mode 100644 index 0000000..d4ad3b8 --- /dev/null +++ b/platforms/nixos/modules/nmasur/presets/services/restic.nix @@ -0,0 +1,61 @@ +{ config, lib, ... }: + +let + cfg = config.nmasur.presets.services.restic; +in +{ + + options.nmasur.presets.services.restic = { + enable = lib.mkEnableOption "Restic backup service"; + resticPassword = lib.mkOption { + type = lib.types.nullOr lib.types.path; + description = "Password file path for Restic backups"; + default = ../../../../../../private/restic.age; + }; + s3 = { + endpoint = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "S3 endpoint for Restic backups"; + default = "s3.us-east-1.amazonaws.com"; + }; + bucket = lib.mkOption { + type = lib.types.nullOr lib.types.str; + description = "S3 bucket for Restic backups"; + default = null; + }; + accessKeySecretPair = lib.mkOption { + type = lib.types.nullOr lib.types.path; + description = "Path to file containing S3 access and secret key for Restic backups"; + default = ../../../../../../private/s3-glacier.age; + }; + }; + }; + + config = lib.mkIf (cfg.enable) { + + secrets.restic-s3-creds = { + source = cfg.s3.accessKeySecretPair; + dest = "${config.secretsDirectory}/restic-s3-creds"; + }; + secrets.restic = { + source = cfg.resticPassword; + dest = "${config.secretsDirectory}/restic"; + }; + + services.restic.backups = { + default = { + repository = "s3:${cfg.endpoint}/${cfg.s3.bucket}/restic"; + paths = [ ]; + environmentFile = config.secrets.restic-s3-creds.dest; + passwordFile = config.secrets.restic.dest; + pruneOpts = [ + "--keep-daily 14" + "--keep-weekly 6" + "--keep-monthly 12" + "--keep-yearly 100" + ]; + }; + }; + + }; +}