From 8eb9ed31fc826c674aa2b78bc5f6fe51838201d5 Mon Sep 17 00:00:00 2001 From: Nick Date: Sun, 14 Dec 2025 01:52:25 -0600 Subject: [PATCH] feat: configured syncthing and photoprism --- modules/nixos/default.nix | 3 +- .../guests/photoprism/config/default.nix | 50 +++++++------- .../photoprism/photoprismEris/default.nix | 3 +- .../guests/syncthing/config/default.nix | 2 +- modules/nixos/homelab/restic/default.nix | 66 ++----------------- .../homelab/restic/resticCeres/default.nix | 64 ++++++++++++++++++ .../homelab/restic/resticEris/default.nix | 52 +++++++++++++++ secrets/secrets.yaml | 13 ++-- 8 files changed, 161 insertions(+), 92 deletions(-) create mode 100755 modules/nixos/homelab/restic/resticCeres/default.nix create mode 100755 modules/nixos/homelab/restic/resticEris/default.nix diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix index 7dd411a..b70671f 100755 --- a/modules/nixos/default.nix +++ b/modules/nixos/default.nix @@ -59,7 +59,7 @@ in impermanence lix microvm - restic + resticCeres # wireguard forgejoCeres jellyfinCeres @@ -81,6 +81,7 @@ in inherit (modules) impermanence lix + resticEris microvm sambaEris fireflyEris diff --git a/modules/nixos/homelab/guests/photoprism/config/default.nix b/modules/nixos/homelab/guests/photoprism/config/default.nix index a2d87ca..4fdba61 100755 --- a/modules/nixos/homelab/guests/photoprism/config/default.nix +++ b/modules/nixos/homelab/guests/photoprism/config/default.nix @@ -1,6 +1,7 @@ { flake, lib, + pkgs, ... }: let @@ -37,9 +38,13 @@ in PHOTOPRISM_ADMIN_USER = user; PHOTOPRISM_DISABLE_TLS = "true"; PHOTOPRISM_DEFAULT_LOCAL = "en"; + PHOTOPRISM_BACKUP_DATABASE = "false"; + PHOTOPRISM_BACKUP_ALBUMS = "true"; + PHOTOPRISM_SIDECAR_YAML = "true"; + PHOTOPRISM_READONLY = "true"; + PHOTOPRISM_INDEX_SCHEDULE = "0 2 * * *"; }; passwordFile = "/etc/photoprism-secrets/${user}-pass"; - # databasePasswordFile = "/etc/photoprism-secrets/${user}-pass"; storagePath = "/var/lib/${serviceCfg.name}"; originalsPath = "/var/lib/${serviceCfg.name}-media"; address = "0.0.0.0"; @@ -67,34 +72,29 @@ in systemd = { services = { - # fix-secrets-permissions = { - # description = "Fix secrets permissions for photoprism"; - # wantedBy = [ "multi-user.target" ]; - # before = [ - # "photoprism.service" - # ]; - # serviceConfig = { - # Type = "oneshot"; - # RemainAfterExit = true; - # }; - # script = '' - # mkdir -p /etc/photoprism-secrets - # cp /run/secrets/${user}-pass /etc/photoprism-secrets/${user}-pass - # chmod 755 /etc/photoprism-secrets - # chmod 644 /etc/photoprism-secrets/* - # ''; - # }; + photoprism-secrets = { + description = "Setup photoprism secrets"; + wantedBy = [ "multi-user.target" ]; + before = [ "photoprism.service" ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + }; + script = '' + mkdir -p /etc/photoprism-secrets + cp /run/secrets/${user}-pass /etc/photoprism-secrets/${user}-pass + chmod 755 /etc/photoprism-secrets + chmod 644 /etc/photoprism-secrets/${user}-pass + ''; + }; photoprism = { serviceConfig = { DynamicUser = lib.mkForce false; User = serviceCfg.name; Group = serviceCfg.name; - # Override LoadCredential to use our secrets path - LoadCredential = lib.mkForce [ - "PHOTOPRISM_ADMIN_PASSWORD_FILE:/run/secrets/${user}-pass" - ]; + StateDirectory = lib.mkForce [ ]; + StateDirectoryMode = lib.mkForce null; }; - # Make sure secrets are mounted before service starts after = [ "run-secrets.mount" ]; requires = [ "run-secrets.mount" ]; }; @@ -124,8 +124,8 @@ in }; microvm = { - vcpu = 1; - mem = 512; + vcpu = 2; + mem = 1024 * 4; hypervisor = "qemu"; interfaces = [ { diff --git a/modules/nixos/homelab/guests/photoprism/photoprismEris/default.nix b/modules/nixos/homelab/guests/photoprism/photoprismEris/default.nix index 92bf3b8..bf0db50 100755 --- a/modules/nixos/homelab/guests/photoprism/photoprismEris/default.nix +++ b/modules/nixos/homelab/guests/photoprism/photoprismEris/default.nix @@ -1,13 +1,14 @@ { flake, lib, + pkgs, labHelpers, ... }: let inherit (import ../../../helpers.nix { inherit flake; }) labHelpers; inherit (labHelpers) guestPath mediaPath; - inherit (import ../config { inherit flake lib; }) photoprismVM; + inherit (import ../config { inherit flake lib pkgs; }) photoprismVM; inherit (flake.config.services.instances) photoprism; inherit (flake.config.people) user0; interfaceCfg = photoprism.interfaces.interface0; diff --git a/modules/nixos/homelab/guests/syncthing/config/default.nix b/modules/nixos/homelab/guests/syncthing/config/default.nix index a856618..c081b87 100755 --- a/modules/nixos/homelab/guests/syncthing/config/default.nix +++ b/modules/nixos/homelab/guests/syncthing/config/default.nix @@ -5,7 +5,7 @@ let inherit (flake.config.people) user0; inherit (flake.config.services.instances) syncthing; - inherit (import ../../../../helpers.nix { inherit flake; }) labHelpers; + inherit (import ../../../helpers.nix { inherit flake; }) labHelpers; inherit (labHelpers) mediaPath docsPath miscPath; serviceCfg = syncthing; in diff --git a/modules/nixos/homelab/restic/default.nix b/modules/nixos/homelab/restic/default.nix index cbdf8fa..da65bd2 100755 --- a/modules/nixos/homelab/restic/default.nix +++ b/modules/nixos/homelab/restic/default.nix @@ -1,63 +1,11 @@ -{ - config, - flake, - ... -}: let - inherit (flake.config.services) instances; - inherit (flake.config.people) user0; - envFile = "backblaze/env"; - repoFile = "backblaze/repo"; - passFile = "restic/pass"; + importList = + let + content = builtins.readDir ./.; + dirContent = builtins.filter (n: content.${n} == "directory") (builtins.attrNames content); + in + map (name: ./. + "/${name}") dirContent; in { - services.restic = { - backups = { - remote = { - environmentFile = config.sops.secrets.${envFile}.path; - initialize = true; - passwordFile = config.sops.secrets.${passFile}.path; - repositoryFile = config.sops.secrets.${repoFile}.path; - timerConfig = { - OnCalendar = "0/4:00"; - Persistent = true; - }; - paths = - let - inst = instance: interface: instances.${instance}.interfaces.${interface}.paths.mntPaths.path0; - in - [ - "/home/${user0}/.ssh" - (inst "forgejo" "interface0") - (inst "mastodon" "interface0") - (inst "opencloud" "interface1") - (inst "minecraft" "interface0") - (inst "minecraft" "interface1") - ((inst "jellyfin" "interface0") + "/cache") - ((inst "jellyfin" "interface0") + "/data") - ((inst "jellyfin" "interface0") + "/media/music") - ]; - }; - }; - }; - - sops = { - secrets = builtins.listToAttrs ( - map - (secret: { - name = secret; - value = { - path = "/run/secrets/${secret}"; - owner = "root"; - group = "root"; - mode = "0600"; - }; - }) - [ - envFile - repoFile - passFile - ] - ); - }; + imports = importList; } diff --git a/modules/nixos/homelab/restic/resticCeres/default.nix b/modules/nixos/homelab/restic/resticCeres/default.nix new file mode 100755 index 0000000..eb0edea --- /dev/null +++ b/modules/nixos/homelab/restic/resticCeres/default.nix @@ -0,0 +1,64 @@ +{ + config, + flake, + ... +}: +let + inherit (flake.config.services) instances; + inherit (flake.config.machines.devices) ceres; + inherit (flake.config.people) user0; + envFile = "backblaze/${ceres.name}-env"; + repoFile = "backblaze/${ceres.name}-repo"; + passFile = "restic/${ceres.name}-pass"; +in +{ + services.restic = { + backups = { + remote = { + initialize = true; + environmentFile = config.sops.secrets.${envFile}.path; + passwordFile = config.sops.secrets.${passFile}.path; + repositoryFile = config.sops.secrets.${repoFile}.path; + timerConfig = { + OnCalendar = "0/4:00"; + Persistent = true; + }; + paths = + let + inst = instance: interface: instances.${instance}.interfaces.${interface}.paths.mntPaths.path0; + in + [ + "/home/${user0}/.ssh" + (inst "forgejo" "interface0") + (inst "mastodon" "interface0") + (inst "opencloud" "interface1") + (inst "minecraft" "interface0") + (inst "minecraft" "interface1") + ((inst "jellyfin" "interface0") + "/cache") + ((inst "jellyfin" "interface0") + "/data") + ((inst "jellyfin" "interface0") + "/media/music") + ]; + }; + }; + }; + + sops = { + secrets = builtins.listToAttrs ( + map + (secret: { + name = secret; + value = { + path = "/run/secrets/${secret}"; + owner = "root"; + group = "root"; + mode = "0600"; + }; + }) + [ + envFile + repoFile + passFile + ] + ); + }; +} diff --git a/modules/nixos/homelab/restic/resticEris/default.nix b/modules/nixos/homelab/restic/resticEris/default.nix new file mode 100755 index 0000000..973f325 --- /dev/null +++ b/modules/nixos/homelab/restic/resticEris/default.nix @@ -0,0 +1,52 @@ +{ + config, + flake, + ... +}: +let + inherit (flake.config.machines.devices) eris; + inherit (flake.config.people) user0; + envFile = "backblaze/${eris.name}-env"; + repoFile = "backblaze/${eris.name}-repo"; + passFile = "restic/${eris.name}-pass"; +in +{ + services.restic = { + backups = { + remote = { + environmentFile = config.sops.secrets.${envFile}.path; + initialize = true; + passwordFile = config.sops.secrets.${passFile}.path; + repositoryFile = config.sops.secrets.${repoFile}.path; + timerConfig = { + OnCalendar = "0/4:00"; + Persistent = true; + }; + paths = [ + "/home/${user0}/.ssh" + "/mnt/storage" + ]; + }; + }; + }; + + sops = { + secrets = builtins.listToAttrs ( + map + (secret: { + name = secret; + value = { + path = "/run/secrets/${secret}"; + owner = "root"; + group = "root"; + mode = "0600"; + }; + }) + [ + envFile + repoFile + passFile + ] + ); + }; +} diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml index b4d4268..ed1551b 100755 --- a/secrets/secrets.yaml +++ b/secrets/secrets.yaml @@ -65,10 +65,13 @@ torrent: nick-wireguard-pass: ENC[AES256_GCM,data:9vvKbANYt/zuPgIQmYFFhBdN59p6aa8hgErYBv325ByPkeGNrxZYhpzv8d8Y,iv:rJbMKsFRBaRyyCE3fI+2XsmVCxSgGdn7glrF/8QThSU=,tag:cg/JFl1iahoqelvrB/T0nA==,type:str] nick-qbittorrent-pass: ENC[AES256_GCM,data:KT1L8pFz0sczfftnpGxA8Od0jY3dHzzDWpMf1fSyHsM9,iv:uzLkGIlWhA3+DsQxjdLd+bF4zCgsoKYDIs2W2LHtK2M=,tag:goIJ1uuqyPGHzqJMYq2wQg==,type:str] backblaze: - env: ENC[AES256_GCM,data:cdOYt77KocuGB3aqYz13oBokoLkEIgI1AW+cYC5uutgZYujG3PqoLEh6Gvbpzn3O+0OWg1/4UAYr4f2v7oCsgwFzPWS3HrhqC5+kIBjrPCyAnxDxlu2xaQ9hR+ogFh5UTDo=,iv:6+jx4Dj5CNV72DAss6NNYm44f9gSHco/EUBvL2o2CNI=,tag:6/cx84MgTDqQJxu/zINEeA==,type:str] - repo: ENC[AES256_GCM,data:sRae9XELIfkWPaXelCdgEXIDbLTHVqGcRO0o+WA9aBfB8MUw92JjRCYgMgGXT0Apy38eszyuEHFB3XPpRmtQ7g==,iv:EilVA9zdHm6B9pTIhNxyj6Th1248nXvh0kpnEqZJ5HI=,tag:q9ASAgx5vgY0IePws4rT5Q==,type:str] + ceres-env: ENC[AES256_GCM,data:WQGj3+pgxWCd5qhS7ksOUWBeMzI1VsQVmgt2kFAqAggjLm0HDuVuGXI+aH4mh5i047USkU1z0oBGfIwNeiDfpaFlKeqLLQUCPZYSssPb5wUE3fGdkBHsCTfhW2TuOPmncYo=,iv:K+qVxHvp5DksSvX0HN/ct0VwM8WTtlxgpKBiS1TWWV0=,tag:YAKk7+LtwSYNnz7mzN44JA==,type:str] + ceres-repo: ENC[AES256_GCM,data:HPPfCfZnQpkgt+qsNWeecTQYDGB5eOcDHnYzI8u177C51BhnhAir14JWe+bL3cZY9oc9LynLjvl7UFePZcFCYw==,iv:/D4HV8GQEcn14YaB8NYA2VSm5F03aeDiXaHiDq4QT2M=,tag:XvkSTLbdWR8Pyoy9CBP6PQ==,type:str] + eris-env: ENC[AES256_GCM,data:0egE0S6ge+o404WKSwmOILvmVJoTnj9953IHAn+8vczZ++IQM+uoskxV2zsQ80tXII11c46VGfwqtJWC6pJLAdEPgFoQz4s4B21wkORRV8xAwnQ2jFiMHyWHhrF1jJtxcEI=,iv:E1lzUHI+usWyP5dne0EHrY+glBJX/A/pPHyy8pdiZzU=,tag:wwWLId8EO1qDfmcWW3Mlnw==,type:str] + eris-repo: ENC[AES256_GCM,data:Lro61R+gez+KlX3Tg5y2z/Pk3PhAjDpT1iP35wUSI1ZJm5pVYkPNZSJnz+vQZNrBkJQ+HVDtAQ==,iv:UJfAenX4bhWPxPN4cawhYYQxr7jAUfiZQBCxr7zyvJg=,tag:Q4qx3+VI4zbf6xxW1YOhsg==,type:str] restic: - pass: ENC[AES256_GCM,data:I5Bf7or9jNwtdK/r/DzUHw6FohzeMtWVrs5AG71geVr6,iv:WnHsFW6oJCBsm84y1rzQ6HbLG8ydPBPQQbHoXKGR7JM=,tag:HsoJxLv8FvrUNSwI0OFCbQ==,type:str] + ceres-pass: ENC[AES256_GCM,data:oIFx/v9WbgMT44U/W62+nVlH8Y8VBD7+GoSDMKsVEvbj,iv:epzLHQaGwvEgmx2NDn3MD5xaUnAHu3qcapxGzzavoTM=,tag:d5+qfobstLXwWx3PjxIrag==,type:str] + eris-pass: ENC[AES256_GCM,data:gsqlsENMD4RSnoTXMBBpgmGKqOlFCrISVUBuEOOPtvNv,iv:/iCn+eYVDC79oQXfgMMRcaKEadtlMF6VTI2FwAL7H7E=,tag:J7R7ADX/5HQSPnQWY+8Jtg==,type:str] passwords: user0: ENC[AES256_GCM,data:72ABhoc8Hjdf56eHkxu82Ls1zTJwUJRkly9hqlHKhQ4INepT66LrUGRHUG1x+4FemNWvAirEXVHvPVtu+rArCrDpGP2ZIbP77f8=,iv:ukq8E7orUwFOUfoqPp9RMjZNm0MMobXcjbWLzx9z1+4=,tag:E9OTDzLkliDIlH5DrLqQVw==,type:str] photoprism: @@ -89,7 +92,7 @@ sops: bXBOa1VSakoyaWxpODJEOU11QUZCaUEK8Ch9Ten3DdrPHF1DTH2qei85AlHUOaLD aNfzakake7ej+MxJYdKEU0bcWofNMKzIlZa2uM10KZSENDP8d8qlig== -----END AGE ENCRYPTED FILE----- - lastmodified: "2025-12-11T06:59:23Z" - mac: ENC[AES256_GCM,data:xGDaLeNV+YTJmX/v8WgRDPn683a8gfxSmE/Le+c9AB8VQfq+mKbqjz4DdtQ9TSdNz65BIjV1GCQJ1jsSxfqmJJaQJkVCgWCI+sKby/Qkpbjn+3xhMxWCbgI5kxasDGYHOXlcz5L4IXUg1pRIHQwuZjlA4q7H7fKUHim6UnUZzQ8=,iv:zywKqa6OWVb4TFhMAoHNasbkJdb9fLttGXCwGS+NzOE=,tag:7Vs8K3XeiFM6lNOTUDY67g==,type:str] + lastmodified: "2025-12-14T07:15:33Z" + mac: ENC[AES256_GCM,data:jH5VMFbTsriCcNwYxN4lgu3ORuoPYKBY1xl/09ecKLj/VtBMZcFAIRjsf101pFjN4MvcCtP3CgrI92LdL/LEbnTkT5LWULoqCvfXZNWSokaVvd9evIK1Gg3ZHwXC+1ONdYOHt/zLxLvT35Z2XqD7bkxOrDkmYYd0P+pkqyZDMRI=,iv:ynPngQxUSkMC82gD+rp8vvB0jblcTt45DTe5xFDm/qo=,tag:sQyZzFBKi4aPbXVG0OH6QQ==,type:str] unencrypted_suffix: _unencrypted version: 3.11.0