diff --git a/nixarr/default.nix b/nixarr/default.nix index 6452145..ba7aa9b 100644 --- a/nixarr/default.nix +++ b/nixarr/default.nix @@ -7,99 +7,6 @@ with lib; let cfg = config.nixarr; globals = config.util-nixarr.globals; - list-unlinked = pkgs.writeShellApplication { - name = "list-unlinked"; - runtimeInputs = with pkgs; [util-linux]; - text = '' - if [ "$#" -ne 1 ]; then - echo "Illegal number of parameters. Must be one file path" - fi - - find "$1" -type f -links 1 -exec du -h {} + | sort -h - ''; - }; - fix-permissions = pkgs.writeShellApplication { - name = "fix-permissions"; - runtimeInputs = with pkgs; [util-linux]; - text = - '' - if [ "$EUID" -ne 0 ]; then - echo "Please run as root" - exit - fi - - find "${cfg.mediaDir}" \( -type d -exec chmod 0775 {} + -true \) -o \( -exec chmod 0664 {} + \) - '' - + strings.optionalString cfg.jellyfin.enable '' - chown -R ${globals.libraryOwner.user}:${globals.libraryOwner.group} "${cfg.mediaDir}/library" - chown -R ${globals.jellyfin.user}:root "${cfg.jellyfin.stateDir}" - find "${cfg.jellyfin.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.plex.enable '' - chown -R ${globals.libraryOwner.user}:${globals.libraryOwner.group} "${cfg.mediaDir}/library" - chown -R ${globals.plex.user}:root "${cfg.plex.stateDir}" - find "${cfg.plex.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.audiobookshelf.enable '' - chown -R ${globals.libraryOwner.user}:${globals.libraryOwner.group} "${cfg.mediaDir}/library" - chown -R ${globals.audiobookshelf.user}:root "${cfg.audiobookshelf.stateDir}" - find "${cfg.audiobookshelf.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.transmission.enable '' - chown -R ${globals.transmission.user}:${globals.transmission.group} "${cfg.mediaDir}/torrents" - chown -R ${globals.transmission.user}:${globals.transmission.group} "${cfg.transmission.stateDir}" - find "${cfg.transmission.stateDir}" \( -type d -exec chmod 0750 {} + -true \) -o \( -exec chmod 0640 {} + \) - '' - + strings.optionalString cfg.sabnzbd.enable '' - chown -R ${globals.sabnzbd.user}:${globals.sabnzbd.group} "${cfg.mediaDir}/usenet" - chown -R ${globals.sabnzbd.user}:root "${cfg.sabnzbd.stateDir}" - find "${cfg.sabnzbd.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.transmission.privateTrackers.cross-seed.enable '' - chown -R ${globals.cross-seed.user}:root "${cfg.transmission.privateTrackers.cross-seed.stateDir}" - find "${cfg.transmission.privateTrackers.cross-seed.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.prowlarr.enable '' - chown -R ${globals.prowlarr.user}:root "${cfg.prowlarr.stateDir}" - find "${cfg.prowlarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.sonarr.enable '' - chown -R ${globals.sonarr.user}:root "${cfg.sonarr.stateDir}" - find "${cfg.sonarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.radarr.enable '' - chown -R ${globals.radarr.user}:root "${cfg.radarr.stateDir}" - find "${cfg.radarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.lidarr.enable '' - chown -R ${globals.lidarr.user}:root "${cfg.lidarr.stateDir}" - find "${cfg.lidarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.bazarr.enable '' - chown -R ${globals.bazarr.user}:root "${cfg.bazarr.stateDir}" - find "${cfg.bazarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.readarr.enable '' - chown -R ${globals.readarr.user}:root "${cfg.readarr.stateDir}" - find "${cfg.readarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.readarr-audiobook.enable '' - chown -R ${globals.readarr.user}:root "${cfg.readarr-audiobook.stateDir}" - find "${cfg.readarr-audiobook.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.jellyseerr.enable '' - chown -R ${globals.jellyseerr.user}:root "${cfg.jellyseerr.stateDir}" - find "${cfg.jellyseerr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.autobrr.enable '' - chown -R ${globals.autobrr.user}:root "${cfg.autobrr.stateDir}" - find "${cfg.autobrr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - '' - + strings.optionalString cfg.recyclarr.enable '' - chown -R ${globals.recyclarr.user}:root "${cfg.recyclarr.stateDir}" - find "${cfg.recyclarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) - ''; - }; in { imports = [ ./audiobookshelf @@ -109,6 +16,7 @@ in { ./jellyfin ./jellyseerr ./lidarr + ./nixarr-command ./openssh ./plex ./prowlarr @@ -140,6 +48,8 @@ in { - **Optional Automatic Port Forwarding:** This module has a UPNP support that lets services request ports from your router automatically, if you enable it. + Also comes with the `nixarr` command that helps you manage your library. + It is possible, _but not recommended_, to run the "*Arrs" behind a VPN, because it can cause rate limiting issues. Generally, you should use VPN on transmission and maybe jellyfin, depending on your setup. @@ -304,13 +214,11 @@ in { users.groups.media.members = cfg.mediaUsers; systemd.tmpfiles.rules = [ - "d '${cfg.mediaDir}' 0775 root media - -" + "d '${cfg.mediaDir}' 0775 ${globals.libraryOwner.user} ${globals.libraryOwner.group} - -" ]; environment.systemPackages = with pkgs; [ jdupes - list-unlinked - fix-permissions ]; vpnNamespaces.wg = mkIf cfg.vpn.enable { diff --git a/nixarr/nixarr-command/default.nix b/nixarr/nixarr-command/default.nix new file mode 100644 index 0000000..e8a9fb2 --- /dev/null +++ b/nixarr/nixarr-command/default.nix @@ -0,0 +1,131 @@ +{ + inputs, + config, + pkgs, + lib, + ... +}: +with lib; let + nixarr = config.nixarr; + globals = config.util-nixarr.globals; + nixarr-command = pkgs.writeShellApplication { + name = "nixarr"; + runtimeInputs = with pkgs; [util-linux]; + text = '' + command="''${1:-}" + + # Check if a parameter is provided + if [ -z "$command" ]; then + echo "Usage: nixarr " + echo "" + echo "Commands:" + echo " fix-permissions Sets correct permissions for any directory managed by Nixarr." + echo " list-unlinked Lists unlinked directories and files, in the given directory." + echo " Use on the media directory to diagnose harddrive space issues." + exit 1 + fi + + fix-permissions() { + if [ "$EUID" -ne 0 ]; then + echo "Please run as root" + exit + fi + + find "${nixarr.mediaDir}" \( -type d -exec chmod 0775 {} + -true \) -o \( -exec chmod 0664 {} + \) + ${strings.optionalString nixarr.jellyfin.enable '' + chown -R ${globals.libraryOwner.user}:${globals.libraryOwner.group} "${nixarr.mediaDir}/library" + chown -R ${globals.jellyfin.user}:root "${nixarr.jellyfin.stateDir}" + find "${nixarr.jellyfin.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.plex.enable '' + chown -R ${globals.libraryOwner.user}:${globals.libraryOwner.group} "${nixarr.mediaDir}/library" + chown -R ${globals.plex.user}:root "${nixarr.plex.stateDir}" + find "${nixarr.plex.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.audiobookshelf.enable '' + chown -R ${globals.libraryOwner.user}:${globals.libraryOwner.group} "${nixarr.mediaDir}/library" + chown -R ${globals.audiobookshelf.user}:root "${nixarr.audiobookshelf.stateDir}" + find "${nixarr.audiobookshelf.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.transmission.enable '' + chown -R ${globals.transmission.user}:${globals.transmission.group} "${nixarr.mediaDir}/torrents" + chown -R ${globals.transmission.user}:${globals.cross-seed.group} "${nixarr.transmission.stateDir}" + find "${nixarr.transmission.stateDir}" \( -type d -exec chmod 0750 {} + -true \) -o \( -exec chmod 0640 {} + \) + ''} + ${strings.optionalString nixarr.sabnzbd.enable '' + chown -R ${globals.sabnzbd.user}:${globals.sabnzbd.group} "${nixarr.mediaDir}/usenet" + chown -R ${globals.sabnzbd.user}:root "${nixarr.sabnzbd.stateDir}" + find "${nixarr.sabnzbd.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.transmission.privateTrackers.cross-seed.enable '' + chown -R ${globals.cross-seed.user}:root "${nixarr.transmission.privateTrackers.cross-seed.stateDir}" + find "${nixarr.transmission.privateTrackers.cross-seed.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.prowlarr.enable '' + chown -R ${globals.prowlarr.user}:root "${nixarr.prowlarr.stateDir}" + find "${nixarr.prowlarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.sonarr.enable '' + chown -R ${globals.sonarr.user}:root "${nixarr.sonarr.stateDir}" + find "${nixarr.sonarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.radarr.enable '' + chown -R ${globals.radarr.user}:root "${nixarr.radarr.stateDir}" + find "${nixarr.radarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.lidarr.enable '' + chown -R ${globals.lidarr.user}:root "${nixarr.lidarr.stateDir}" + find "${nixarr.lidarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.bazarr.enable '' + chown -R ${globals.bazarr.user}:root "${nixarr.bazarr.stateDir}" + find "${nixarr.bazarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.readarr.enable '' + chown -R ${globals.readarr.user}:root "${nixarr.readarr.stateDir}" + find "${nixarr.readarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.readarr-audiobook.enable '' + chown -R ${globals.readarr.user}:root "${nixarr.readarr-audiobook.stateDir}" + find "${nixarr.readarr-audiobook.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.jellyseerr.enable '' + chown -R ${globals.jellyseerr.user}:root "${nixarr.jellyseerr.stateDir}" + find "${nixarr.jellyseerr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.autobrr.enable '' + chown -R ${globals.autobrr.user}:root "${nixarr.autobrr.stateDir}" + find "${nixarr.autobrr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + ${strings.optionalString nixarr.recyclarr.enable '' + chown -R ${globals.recyclarr.user}:root "${nixarr.recyclarr.stateDir}" + find "${nixarr.recyclarr.stateDir}" \( -type d -exec chmod 0700 {} + -true \) -o \( -exec chmod 0600 {} + \) + ''} + } + + list-unlinked() { + if [ "$#" -ne 1 ]; then + echo "Illegal number of parameters. Must be one file path" + fi + + find "$1" -type f -links 1 -exec du -h {} + | sort -h + } + + # Handle the command + case "$1" in + fix-permissions) + fix-permissions + ;; + list-unlinked) + if [ "$#" -ne 1 ]; then + echo "Illegal number of parameters. Must be one file path" + fi + + find "$1" -type f -links 1 -exec du -h {} + | sort -h + ;; + esac + ''; + }; +in { + config.environment.systemPackages = [ nixarr-command ]; +} diff --git a/nixarr/transmission/default.nix b/nixarr/transmission/default.nix index a8ede6b..5efe61e 100644 --- a/nixarr/transmission/default.nix +++ b/nixarr/transmission/default.nix @@ -296,9 +296,9 @@ in { }; systemd.tmpfiles.rules = [ - "d '${cfg.stateDir}' 0750 ${globals.transmission.user} ${globals.cross-seed.group} - -" + "d '${cfg.stateDir}' 0750 ${globals.transmission.user} ${globals.cross-seed.group} - -" # This is fixes a bug in nixpks (https://github.com/NixOS/nixpkgs/issues/291883) - "d '${cfg.stateDir}/.config' 0750 ${globals.transmission.user} ${globals.cross-seed.group} - -" + "d '${cfg.stateDir}/.config' 0750 ${globals.transmission.user} ${globals.cross-seed.group} - -" "d '${cfg.stateDir}/.config/transmission-daemon' 0750 ${globals.transmission.user} ${globals.cross-seed.group} - -" # Media Dirs