From 75dc495709f2785106d194a835279e2cdb8ffc78 Mon Sep 17 00:00:00 2001 From: arcnmx Date: Wed, 2 Oct 2024 19:43:48 -0700 Subject: [PATCH] fix(backups): plex --- nixos/backups/restic.nix | 61 +++++++++++++++++++++++++--------------- nixos/plex.nix | 42 +++++++++++++++++---------- systems/reisen/setup.sh | 18 +++++------- 3 files changed, 73 insertions(+), 48 deletions(-) diff --git a/nixos/backups/restic.nix b/nixos/backups/restic.nix index 59687db1..ac9dc8d7 100644 --- a/nixos/backups/restic.nix +++ b/nixos/backups/restic.nix @@ -1,10 +1,11 @@ -{config, systemConfig, lib, ...}: let +{pkgs, config, systemConfig, lib, ...}: let inherit (lib.modules) mkIf mkMerge mkDefault; inherit (lib.attrsets) mapAttrs' mapAttrsToList nameValuePair; - inherit (lib.lists) concatMap; - inherit (lib.strings) replaceStrings; + inherit (lib.lists) concatMap toList; + inherit (lib.strings) replaceStrings concatMapStringsSep; inherit (config.sops.secrets) restic-shared-repo-b2 restic-shared-password restic-shared-env-b2; group = "backups"; + mkSharedPath = subpath: "/mnt/shared/${subpath}"; # TODO: this properly as a module or something sharedServices = { hass.config = config.services.home-assistant; @@ -13,11 +14,27 @@ kanidm = { config = config.services.kanidm; enable = config.services.kanidm.enableServer; + subpath = "kanidm/kanidm.db"; }; mosquitto.config = config.services.mosquitto; plex = { config = config.services.plex; compression = "auto"; + subpath = [ + "plex/Plex Media Server/Preferences.xml" + #"plex/Databases" # omitted, see dynamicFilesFrom to select only the latest backup... + ]; + settings = { + dynamicFilesFrom = let + databases = [ + "com.plexapp.plugins.library.blobs.db" + "com.plexapp.plugins.library.db" + ]; + ls = "${pkgs.coreutils}/bin/ls"; + tail = "${pkgs.coreutils}/bin/tail"; + mkLatestDb = database: ''${ls} ${mkSharedPath "plex/Databases/${database}"}* | ${tail} -n1''; + in concatMapStringsSep " &&\n" mkLatestDb databases; + }; }; postgresql = { # TODO: synchronize with postgresqlBackup service via flock or After= @@ -40,31 +57,31 @@ in { services.restic.backups = let isBackup = config.networking.hostName == "hakurei"; - mkSharedPath = subpath: "/mnt/shared/${subpath}"; - mkBackupB2 = name: subpath': { config, enable ? config.enable, user ? config.user or null, subpath ? subpath', path ? mkSharedPath subpath, compression ? "max" }: let + mkBackupB2 = name: subpath': { config, enable ? config.enable, user ? config.user or null, subpath ? subpath', compression ? "max", settings ? {} }: let tags = [ "infra" "shared-${name}" "system-${systemConfig.name}" ]; - in mkIf (enable || isBackup) { - user = mkIf (enable && user != null) user; - repositoryFile = restic-shared-repo-b2.path; - passwordFile = restic-shared-password.path; - environmentFile = restic-shared-env-b2.path; - paths = [path]; - extraBackupArgs = mkMerge [ - (mkIf (compression != "auto") [ - "--compression" compression - ]) - (concatMap (tag: ["--tag" tag]) tags) - ]; - timerConfig = { - OnCalendar = "03:30"; - Persistent = true; - RandomizedDelaySec = "4h"; + conf = { + user = mkIf (enable && user != null) user; + repositoryFile = restic-shared-repo-b2.path; + passwordFile = restic-shared-password.path; + environmentFile = restic-shared-env-b2.path; + paths = map mkSharedPath (toList subpath); + extraBackupArgs = mkMerge [ + (mkIf (compression != "auto") [ + "--compression" compression + ]) + (concatMap (tag: ["--tag" tag]) tags) + ]; + timerConfig = { + OnCalendar = "03:30"; + Persistent = true; + RandomizedDelaySec = "4h"; + }; }; - }; + in mkIf (enable || isBackup) (mkMerge [ conf settings ]); backups = mapAttrs' (subpath: service: let name = replaceStrings [ "/" ] [ "-" ] subpath; in nameValuePair "${name}-b2" (mkBackupB2 name subpath service)) sharedServices; diff --git a/nixos/plex.nix b/nixos/plex.nix index a8981046..f052b872 100644 --- a/nixos/plex.nix +++ b/nixos/plex.nix @@ -5,38 +5,50 @@ ... }: let inherit (lib.modules) mkIf mkForce mkDefault; - inherit (lib.strings) escapeShellArg; + inherit (lib.attrsets) mapAttrs' filterAttrs mapAttrsToList nameValuePair; + inherit (lib.strings) escapeShellArg concatStringsSep; cfg = config.services.plex; + plexCaches = { + mesa_shader_cache.path = null; + Cache = {}; + Logs = {}; + CrashReports.subpath = "Crash Reports"; + Diagnostics = {}; + Drivers = {}; + Codecs = {}; + Scanners = {}; + Updates = {}; + Caches.subpath = "Plug-in Support/Caches"; + }; in { services.plex.enable = mkDefault true; systemd.services.plex = mkIf cfg.enable { gensokyo-zone = { sharedMounts.plex.path = mkDefault cfg.dataDir; - cacheMounts = { - "plex/Cache" = { - path = mkDefault "${cfg.dataDir}/Cache"; - }; - "plex/Logs" = { - path = mkDefault "${cfg.dataDir}/Logs"; - }; - "plex/mesa_shader_cache" = { - path = mkDefault "${cfg.dataDir}/mesa_shader_cache"; - }; - }; + cacheMounts = mapAttrs' (name: _: nameValuePair "plex/${name}" { + path = mkDefault "${cfg.dataDir}/${name}"; + }) plexCaches; }; # /var/lib/plex/mesa_shader_cache environment.MESA_SHADER_CACHE_DIR = mkDefault cfg.dataDir; serviceConfig = { ExecStartPre = let + ln = "${pkgs.coreutils}/bin/ln"; + install = "${pkgs.coreutils}/bin/install"; # systemd doesn't seem to like spaces so use a symlink instead... + mkCacheSetup = name: { path ? "Plex Media Server/${subpath}", subpath ? name }: + ''${ln} -srfT "$PLEX_DATADIR/"${escapeShellArg name} "$PLEX_DATADIR/"${escapeShellArg path}''; + cacheSetup = mapAttrsToList mkCacheSetup (filterAttrs (_: cache: cache.path or "" != null) plexCaches); preStartScript = pkgs.writeShellScript "plex-run-prestart" '' set -eu if [[ ! -d $PLEX_DATADIR ]]; then - ${pkgs.coreutils}/bin/install -d -m 0755 -o ${escapeShellArg cfg.user} -g ${escapeShellArg cfg.group} "$PLEX_DATADIR/Plex Media Server" + ${install} -d -m 0755 -o ${escapeShellArg cfg.user} -g ${escapeShellArg cfg.group} "$PLEX_DATADIR/Plex Media Server" fi - ${pkgs.coreutils}/bin/ln -sfT ../Cache "$PLEX_DATADIR/Plex Media Server/Cache" - ${pkgs.coreutils}/bin/ln -sfT ../Logs "$PLEX_DATADIR/Plex Media Server/Logs" + if [[ ! -d $PLEX_DATADIR/Databases ]]; then + ${install} -d -m 0755 -o ${escapeShellArg cfg.user} -g ${escapeShellArg cfg.group} "$PLEX_DATADIR/Databases" + fi + ${concatStringsSep "\n" cacheSetup} ''; in mkForce [ diff --git a/systems/reisen/setup.sh b/systems/reisen/setup.sh index 995b8cf4..3e3500d1 100644 --- a/systems/reisen/setup.sh +++ b/systems/reisen/setup.sh @@ -162,20 +162,16 @@ mkcache zigbee2mqtt 100317 100317 0700 mkcache taskchampion 100917 100917 0750 mkcache minecraft 100913 100913 0750 mkcache plex 0 0 0755 -if [[ ! -d /rpool/caches/plex/Cache ]]; then - mkdir /rpool/caches/plex/Cache -fi -if [[ ! -d /rpool/caches/plex/Logs ]]; then - mkdir /rpool/caches/plex/Logs -fi -if [[ ! -d /rpool/caches/plex/mesa_shader_cache ]]; then - mkdir /rpool/caches/plex/mesa_shader_cache -fi +for plexcache in Logs CrashReports Diagnostics Cache Caches Drivers Codecs Scanners Updates mesa_shader_cache; do + if [[ ! -d /rpool/caches/plex/$plexcache ]]; then + mkdir /rpool/caches/plex/$plexcache + fi + chown 100193:100193 /rpool/caches/plex/$plexcache + chmod 0775 /rpool/caches/plex/$plexcache +done if [[ ! -d /rpool/caches/plex/tautulli/cache ]]; then mkdir -p /rpool/caches/plex/tautulli/cache fi -chown 100193:100193 /rpool/caches/plex/{Cache,Logs,mesa_shader_cache} -chmod 0775 /rpool/caches/plex/{Cache,Logs,mesa_shader_cache} chown 100195:65534 /rpool/caches/plex/tautulli/cache chmod 0755 /rpool/caches/plex/tautulli/cache