From f96ed50dfa5707b5abc95acfd6bc37ec0a4647e9 Mon Sep 17 00:00:00 2001 From: Joseph Hanson Date: Mon, 24 Feb 2025 16:14:45 -0600 Subject: [PATCH] Add 'my packages' --- flake.nix | 25 ++-- .../shadowfax/config/borgmatic/default.nix | 10 ++ .../hosts/shadowfax/config/borgmatic/plex.nix | 34 ++++++ nixos/hosts/shadowfax/config/sops-secrets.nix | 74 ++++++------ nixos/hosts/shadowfax/default.nix | 1 + nixos/hosts/shadowfax/secrets.sops.yaml | 6 +- nixos/lib/default.nix | 114 +++++++++--------- nixos/packages/borgmatic/default.nix | 46 +++++++ 8 files changed, 209 insertions(+), 101 deletions(-) create mode 100644 nixos/hosts/shadowfax/config/borgmatic/default.nix create mode 100644 nixos/hosts/shadowfax/config/borgmatic/plex.nix create mode 100644 nixos/packages/borgmatic/default.nix diff --git a/flake.nix b/flake.nix index 3542e1e..0f3b971 100644 --- a/flake.nix +++ b/flake.nix @@ -134,6 +134,7 @@ inherit inputs; # Import overlays for building nixosconfig with them. overlays = import ./nixos/overlays {inherit inputs;}; + # generate a base nixos configuration with the specified overlays, hardware modules, and any AerModules applied mkNixosConfig = { hostname, @@ -162,20 +163,24 @@ } ], profileModules ? [], - }: + }: let + pkgs = import nixpkgs { + inherit system; + overlays = builtins.attrValues overlays; + config = { + allowUnfree = true; + allowUnfreePredicate = _: true; + }; + }; + in nixpkgs.lib.nixosSystem { inherit system lib; modules = baseModules ++ hardwareModules ++ profileModules; - specialArgs = {inherit self inputs nixpkgs;}; - # Add our overlays - pkgs = import nixpkgs { - inherit system; - overlays = builtins.attrValues overlays; - config = { - allowUnfree = true; - allowUnfreePredicate = _: true; - }; + specialArgs = { + inherit self inputs nixpkgs; + myPkgs = lib.myLib.mkMyPkgs pkgs; }; + inherit pkgs; }; in { "shadowfax" = mkNixosConfig { diff --git a/nixos/hosts/shadowfax/config/borgmatic/default.nix b/nixos/hosts/shadowfax/config/borgmatic/default.nix new file mode 100644 index 0000000..66ec49f --- /dev/null +++ b/nixos/hosts/shadowfax/config/borgmatic/default.nix @@ -0,0 +1,10 @@ +{ lib, ... }: +let + dir = ./.; + files = lib.filterAttrs (name: type: + type == "regular" && name != "default.nix" && lib.hasSuffix ".nix" name + ) (builtins.readDir dir); + imports = map (name: "${dir}/${name}") (builtins.attrNames files); +in { + imports = imports; +} diff --git a/nixos/hosts/shadowfax/config/borgmatic/plex.nix b/nixos/hosts/shadowfax/config/borgmatic/plex.nix new file mode 100644 index 0000000..9736c1f --- /dev/null +++ b/nixos/hosts/shadowfax/config/borgmatic/plex.nix @@ -0,0 +1,34 @@ +{ + config, + lib, + pkgs, + ... +}: { + services.borgmatic = { + enable = true; + configurations.plex = { + source_directories = [ + "/mnt/restic_nightly_backup/nahar/containers/volumes/plex/Library/" + ]; + + repositories = [ + { + label = "local"; + path = "/eru/borg/plex"; + } + ]; + + storage.encryption_passcommand = ''${pkgs.coreutils-full}/bin/cat ${config.sops.secrets."borgmatic/encryption_passphrase".path}''; + + # Retention settings + retention.keep_daily = 7; + retention.keep_weekly = 4; + retention.keep_monthly = 6; + zfs = { + zfs_command = "${pkgs.zfs}/bin/zfs"; + mount_command = "${pkgs.util-linux}/bin/mount"; + umount_command = "${pkgs.util-linux}/bin/umount"; + }; + }; + }; +} diff --git a/nixos/hosts/shadowfax/config/sops-secrets.nix b/nixos/hosts/shadowfax/config/sops-secrets.nix index 5d23620..3624bda 100644 --- a/nixos/hosts/shadowfax/config/sops-secrets.nix +++ b/nixos/hosts/shadowfax/config/sops-secrets.nix @@ -1,5 +1,4 @@ -{ ... }: -{ +{...}: { secrets = { # Minio "minio" = { @@ -7,204 +6,209 @@ owner = "minio"; group = "minio"; mode = "400"; - restartUnits = [ "minio.service" ]; + restartUnits = ["minio.service"]; }; # Syncthing "syncthing/publicCert" = { sopsFile = ../secrets.sops.yaml; owner = "jahanson"; mode = "400"; - restartUnits = [ "syncthing.service" ]; + restartUnits = ["syncthing.service"]; }; "syncthing/privateKey" = { sopsFile = ../secrets.sops.yaml; owner = "jahanson"; mode = "400"; - restartUnits = [ "syncthing.service" ]; + restartUnits = ["syncthing.service"]; }; # Prowlarr "arr/prowlarr/apiKey" = { sopsFile = ../secrets.sops.yaml; owner = "prowlarr"; mode = "400"; - restartUnits = [ "prowlarr.service" ]; + restartUnits = ["prowlarr.service"]; }; "arr/prowlarr/postgres/dbName" = { sopsFile = ../secrets.sops.yaml; owner = "prowlarr"; mode = "400"; - restartUnits = [ "prowlarr.service" ]; + restartUnits = ["prowlarr.service"]; }; "arr/prowlarr/postgres/user" = { sopsFile = ../secrets.sops.yaml; owner = "prowlarr"; mode = "400"; - restartUnits = [ "prowlarr.service" ]; + restartUnits = ["prowlarr.service"]; }; "arr/prowlarr/postgres/password" = { sopsFile = ../secrets.sops.yaml; owner = "prowlarr"; mode = "400"; - restartUnits = [ "prowlarr.service" ]; + restartUnits = ["prowlarr.service"]; }; "arr/prowlarr/postgres/host" = { sopsFile = ../secrets.sops.yaml; owner = "prowlarr"; mode = "400"; - restartUnits = [ "prowlarr.service" ]; + restartUnits = ["prowlarr.service"]; }; # Sonarr "arr/sonarr/1080p/apiKey" = { sopsFile = ../secrets.sops.yaml; owner = "sonarr"; mode = "400"; - restartUnits = [ "sonarr-tv1080p.service" ]; + restartUnits = ["sonarr-tv1080p.service"]; }; "arr/sonarr/1080p/postgres/dbName" = { sopsFile = ../secrets.sops.yaml; owner = "sonarr"; mode = "400"; - restartUnits = [ "sonarr-tv1080p.service" ]; + restartUnits = ["sonarr-tv1080p.service"]; }; "arr/sonarr/1080p/postgres/user" = { sopsFile = ../secrets.sops.yaml; owner = "sonarr"; mode = "400"; - restartUnits = [ "sonarr-tv1080p.service" ]; + restartUnits = ["sonarr-tv1080p.service"]; }; "arr/sonarr/1080p/postgres/password" = { sopsFile = ../secrets.sops.yaml; owner = "sonarr"; mode = "400"; - restartUnits = [ "sonarr-tv1080p.service" ]; + restartUnits = ["sonarr-tv1080p.service"]; }; "arr/sonarr/1080p/postgres/host" = { sopsFile = ../secrets.sops.yaml; owner = "sonarr"; mode = "400"; - restartUnits = [ "sonarr-tv1080p.service" ]; + restartUnits = ["sonarr-tv1080p.service"]; }; "arr/sonarr/1080p/extraEnvVars" = { sopsFile = ../secrets.sops.yaml; owner = "sonarr"; mode = "400"; - restartUnits = [ "sonarr-tv1080p.service" ]; + restartUnits = ["sonarr-tv1080p.service"]; }; "arr/sonarr/anime/apiKey" = { sopsFile = ../secrets.sops.yaml; owner = "sonarr"; mode = "400"; - restartUnits = [ "sonarr-anime.service" ]; + restartUnits = ["sonarr-anime.service"]; }; "arr/sonarr/anime/postgres/dbName" = { sopsFile = ../secrets.sops.yaml; owner = "sonarr"; mode = "400"; - restartUnits = [ "sonarr-anime.service" ]; + restartUnits = ["sonarr-anime.service"]; }; "arr/sonarr/anime/postgres/user" = { sopsFile = ../secrets.sops.yaml; owner = "sonarr"; mode = "400"; - restartUnits = [ "sonarr-anime.service" ]; + restartUnits = ["sonarr-anime.service"]; }; "arr/sonarr/anime/postgres/password" = { sopsFile = ../secrets.sops.yaml; owner = "sonarr"; mode = "400"; - restartUnits = [ "sonarr-anime.service" ]; + restartUnits = ["sonarr-anime.service"]; }; "arr/sonarr/anime/postgres/host" = { sopsFile = ../secrets.sops.yaml; owner = "sonarr"; mode = "400"; - restartUnits = [ "sonarr-anime.service" ]; + restartUnits = ["sonarr-anime.service"]; }; "arr/sonarr/anime/extraEnvVars" = { sopsFile = ../secrets.sops.yaml; owner = "sonarr"; mode = "400"; - restartUnits = [ "sonarr-anime.service" ]; + restartUnits = ["sonarr-anime.service"]; }; # Radarr "arr/radarr/1080p/apiKey" = { sopsFile = ../secrets.sops.yaml; owner = "radarr"; mode = "400"; - restartUnits = [ "radarr-movies1080p.service" ]; + restartUnits = ["radarr-movies1080p.service"]; }; "arr/radarr/1080p/postgres/dbName" = { sopsFile = ../secrets.sops.yaml; owner = "radarr"; mode = "400"; - restartUnits = [ "radarr-movies1080p.service" ]; + restartUnits = ["radarr-movies1080p.service"]; }; "arr/radarr/1080p/postgres/user" = { sopsFile = ../secrets.sops.yaml; owner = "radarr"; mode = "400"; - restartUnits = [ "radarr-movies1080p.service" ]; + restartUnits = ["radarr-movies1080p.service"]; }; "arr/radarr/1080p/postgres/password" = { sopsFile = ../secrets.sops.yaml; owner = "radarr"; mode = "400"; - restartUnits = [ "radarr-movies1080p.service" ]; + restartUnits = ["radarr-movies1080p.service"]; }; "arr/radarr/1080p/postgres/host" = { sopsFile = ../secrets.sops.yaml; owner = "radarr"; mode = "400"; - restartUnits = [ "radarr-movies1080p.service" ]; + restartUnits = ["radarr-movies1080p.service"]; }; "arr/radarr/1080p/extraEnvVars" = { sopsFile = ../secrets.sops.yaml; owner = "radarr"; mode = "400"; - restartUnits = [ "radarr-movies1080p.service" ]; + restartUnits = ["radarr-movies1080p.service"]; }; "arr/radarr/anime/apiKey" = { sopsFile = ../secrets.sops.yaml; owner = "radarr"; mode = "400"; - restartUnits = [ "radarr-anime.service" ]; + restartUnits = ["radarr-anime.service"]; }; "arr/radarr/anime/postgres/dbName" = { sopsFile = ../secrets.sops.yaml; owner = "radarr"; mode = "400"; - restartUnits = [ "radarr-anime.service" ]; + restartUnits = ["radarr-anime.service"]; }; "arr/radarr/anime/postgres/user" = { sopsFile = ../secrets.sops.yaml; owner = "radarr"; mode = "400"; - restartUnits = [ "radarr-anime.service" ]; + restartUnits = ["radarr-anime.service"]; }; "arr/radarr/anime/postgres/password" = { sopsFile = ../secrets.sops.yaml; owner = "radarr"; mode = "400"; - restartUnits = [ "radarr-anime.service" ]; + restartUnits = ["radarr-anime.service"]; }; "arr/radarr/anime/postgres/host" = { sopsFile = ../secrets.sops.yaml; owner = "radarr"; mode = "400"; - restartUnits = [ "radarr-anime.service" ]; + restartUnits = ["radarr-anime.service"]; }; "arr/radarr/anime/extraEnvVars" = { sopsFile = ../secrets.sops.yaml; owner = "radarr"; mode = "400"; - restartUnits = [ "radarr-anime.service" ]; + restartUnits = ["radarr-anime.service"]; }; # Unpackerr "arr/unpackerr/extraEnvVars" = { sopsFile = ../secrets.sops.yaml; owner = "unpackerr"; mode = "400"; - restartUnits = [ "unpackerr.service" ]; + restartUnits = ["unpackerr.service"]; + }; + "borgmatic/encryption_passphrase" = { + sopsFile = ../secrets.sops.yaml; + mode = "400"; + restartUnits = ["borgmatic.service"]; }; }; } diff --git a/nixos/hosts/shadowfax/default.nix b/nixos/hosts/shadowfax/default.nix index 84823a5..12fa137 100644 --- a/nixos/hosts/shadowfax/default.nix +++ b/nixos/hosts/shadowfax/default.nix @@ -43,6 +43,7 @@ in { (import ../../profiles/disko-nixos.nix { disks = ["/dev/sda|/dev/disk/by-id/nvme-Samsung_SSD_970_EVO_Plus_500GB_S58SNM0W406409E"]; }) + ./config/borgmatic inputs.nix-minecraft.nixosModules.minecraft-servers ]; diff --git a/nixos/hosts/shadowfax/secrets.sops.yaml b/nixos/hosts/shadowfax/secrets.sops.yaml index 73f8132..6290243 100644 --- a/nixos/hosts/shadowfax/secrets.sops.yaml +++ b/nixos/hosts/shadowfax/secrets.sops.yaml @@ -11,6 +11,8 @@ postgres: port: ENC[AES256_GCM,data:Z0fHNA==,iv:otbEsYxhJ6/YR+A5oRx3Dwrqk6T6BL9OGka5yu1H+HA=,tag:T+KW8DaRJ8NN7k1mIMn6QA==,type:int] pushover: userKey: ENC[AES256_GCM,data:RYn9OCGaEgu/41kMolmqjYtr8FRmyEOvNStk+7Uz1A==,iv:L4pJJxGPhrmGSJdRDIP/OONibHvIP8KUdXwED29kTJ8=,tag:6TxYaUA6QA1NroBXhQHRlQ==,type:str] +borgmatic: + encryption_passphrase: ENC[AES256_GCM,data:Rzmb+tNo0IG6Ub3Z5pB+XahW7gtZOPs5Cjvrzw4m47q0D7bErACTzQx7VdrSJcm8+g==,iv:cQsm3MfrY4KCTvByUcQe0n51UVm/kNtTUGORx0r+wjg=,tag:j/n/4TI193ec3/mOJeB1Lg==,type:str] arr: prowlarr: apiKey: ENC[AES256_GCM,data:qxm2yp8ReuMgQ0155mKBAWickKusOaa/FeoIopj9l1Z3,iv:pAeDxK6CGap4fKU5xQ5hZR9It6/1uo27dKZBi5Bl3rc=,tag:HZl914AfFU4D5J7cDS3I1g==,type:str] @@ -133,8 +135,8 @@ sops: aVlOSHhFb2I5UnYwVytyQzlWTXBDYUUKdQKilmfJ1F7UYKtQV9zV95FcRIK17p4M vGvu/pGJ32tH8xI7cNs9I5Hmg9c5wOam21W1FDk+VlJ/ClXqQzS0MA== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-02-10T19:15:54Z" - mac: ENC[AES256_GCM,data:KyP1lzKD/iV6SgHbsEYvVRwgrFy/PqHGMVEjeTAcLFCFrIyn9/Gd5ravTOj+37phVARnHI3h2vetqzOBO7/tE4jz0nsEGawOfVMOTKR1Y7+35TKJaC4FTO3/hfczjzolvoLk8011J9aoeC44yx+UT8Ijehc3mkd4x8zVvOK/OG4=,iv:e6FudQPXESAw/CNVqJWGZG+/8j/J88Z8InjM++GJ9lM=,tag:KaQkmLGSU+jJF3f6YBKhmQ==,type:str] + lastmodified: "2025-02-24T21:27:42Z" + mac: ENC[AES256_GCM,data:5E9adS+q+Vb45MtKDuI65GaKxb/yksqSN73ZFHYhdL+w6Lk4/WPd9n7qTENKfFkYN2qIRP3S4IQUBwobep4wiEQt4v8XdNN7gR7cgI/2u4y/iKptyv/YWyj+YYfFaZjJ6lqxod3MAq92L4xYq+91aKoWEW/ErpDy8N3xOe7GI6U=,iv:WGWCD9pfu7ijiDXhcV26j7XpFl5dVglWZeMVQFyFUSA=,tag:PP4yI+iLaaPLG0YoI19zTQ==,type:str] pgp: [] unencrypted_suffix: _unencrypted version: 3.9.4 diff --git a/nixos/lib/default.nix b/nixos/lib/default.nix index 7a3a45b..c0c209c 100644 --- a/nixos/lib/default.nix +++ b/nixos/lib/default.nix @@ -1,63 +1,69 @@ -{ lib, ... }: +{lib, ...}: +with lib; rec { + firstOrDefault = first: default: + if first != null + then first + else default; + existsOrDefault = x: set: default: + if builtins.hasAttr x set + then builtins.getAttr x set + else default; -with lib; -rec { - - firstOrDefault = first: default: if first != null then first else default; - existsOrDefault = - x: set: default: - if builtins.hasAttr x set then builtins.getAttr x set else default; + # Create custom package set + mkMyPkgs = pkgs: { + borgmatic = pkgs.callPackage ../../nixos/packages/borgmatic {}; + }; # main service builder - mkService = - options: - ( - let - user = existsOrDefault "user" options "568"; - group = existsOrDefault "group" options "568"; + mkService = options: ( + let + user = existsOrDefault "user" options "568"; + group = existsOrDefault "group" options "568"; - enableBackups = - (lib.attrsets.hasAttrByPath [ "persistence" "folder" ] options) - && (lib.attrsets.attrByPath [ "persistence" "enable" ] true options); + enableBackups = + (lib.attrsets.hasAttrByPath ["persistence" "folder"] options) + && (lib.attrsets.attrByPath ["persistence" "enable"] true options); - # Security options for containers - containerExtraOptions = - lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "privileged" ] false options) [ - "--privileged" - ] - ++ lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "readOnly" ] false options) [ - "--read-only" - ] - ++ lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "tmpfs" ] false options) [ - (map (folders: "--tmpfs=${folders}") tmpfsFolders) - ] - ++ lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "noNewPrivileges" ] false options) [ - "--security-opt=no-new-privileges" - ] - ++ lib.optionals (lib.attrsets.attrByPath [ "container" "caps" "dropAll" ] false options) [ - "--cap-drop=ALL" - ]; - in - { - virtualisation.oci-containers.containers.${options.app} = mkIf options.container.enable { - image = "${options.container.image}"; - user = "${user}:${group}"; - environment = { + # Security options for containers + containerExtraOptions = + lib.optionals (lib.attrsets.attrByPath ["container" "caps" "privileged"] false options) [ + "--privileged" + ] + ++ lib.optionals (lib.attrsets.attrByPath ["container" "caps" "readOnly"] false options) [ + "--read-only" + ] + ++ lib.optionals (lib.attrsets.attrByPath ["container" "caps" "tmpfs"] false options) [ + (map (folders: "--tmpfs=${folders}") tmpfsFolders) + ] + ++ lib.optionals (lib.attrsets.attrByPath ["container" "caps" "noNewPrivileges"] false options) [ + "--security-opt=no-new-privileges" + ] + ++ lib.optionals (lib.attrsets.attrByPath ["container" "caps" "dropAll"] false options) [ + "--cap-drop=ALL" + ]; + in { + virtualisation.oci-containers.containers.${options.app} = mkIf options.container.enable { + image = "${options.container.image}"; + user = "${user}:${group}"; + environment = + { TZ = options.timeZone; - } // options.container.env; - environmentFiles = lib.attrsets.attrByPath [ "container" "envFiles" ] [ ] options; - volumes = - [ "/etc/localtime:/etc/localtime:ro" ] - ++ lib.optionals (lib.attrsets.hasAttrByPath [ "container" "persistentFolderMount" ] options) [ - "${options.persistence.folder}:${options.container.persistentFolderMount}:rw" - ] - ++ lib.attrsets.attrByPath [ "container" "volumes" ] [ ] options; - extraOptions = containerExtraOptions; - }; - systemd.tmpfiles.rules = lib.optionals (lib.attrsets.hasAttrByPath [ + } + // options.container.env; + environmentFiles = lib.attrsets.attrByPath ["container" "envFiles"] [] options; + volumes = + ["/etc/localtime:/etc/localtime:ro"] + ++ lib.optionals (lib.attrsets.hasAttrByPath ["container" "persistentFolderMount"] options) [ + "${options.persistence.folder}:${options.container.persistentFolderMount}:rw" + ] + ++ lib.attrsets.attrByPath ["container" "volumes"] [] options; + extraOptions = containerExtraOptions; + }; + systemd.tmpfiles.rules = lib.optionals (lib.attrsets.hasAttrByPath [ "persistence" "folder" - ] options) [ "d ${options.persistence.folder} 0750 ${user} ${group} -" ]; - } - ); + ] + options) ["d ${options.persistence.folder} 0750 ${user} ${group} -"]; + } + ); } diff --git a/nixos/packages/borgmatic/default.nix b/nixos/packages/borgmatic/default.nix new file mode 100644 index 0000000..f30576b --- /dev/null +++ b/nixos/packages/borgmatic/default.nix @@ -0,0 +1,46 @@ +{ + lib, + python3, + fetchFromGitHub, +}: +python3.pkgs.buildPythonApplication rec { + pname = "borgmatic"; + version = "1.9.12"; + pyproject = true; + + src = fetchFromGitHub { + owner = "borgmatic-collective"; + repo = "borgmatic"; + rev = version; + hash = "sha256-tTnk2xO5F5AoQICZGVnEj8v6kNA7Wkd8kzvm4i3r0kU="; + }; + + build-system = [ + python3.pkgs.setuptools + ]; + + dependencies = with python3.pkgs; [ + jsonschema + packaging + requests + ruamel-yaml + ]; + + optional-dependencies = with python3.pkgs; { + Apprise = [ + apprise + ]; + }; + + pythonImportsCheck = [ + "borgmatic" + ]; + + meta = { + description = "Simple, configuration-driven backup software for servers and workstations"; + homepage = "https://github.com/borgmatic-collective/borgmatic/"; + changelog = "https://github.com/borgmatic-collective/borgmatic/blob/${src.rev}/NEWS"; + license = lib.licenses.gpl3Only; + mainProgram = "borgmatic"; + }; +}