From 967ba3841196507ded170d8a49461fdfafb85f9d Mon Sep 17 00:00:00 2001 From: Geir Okkenhaug Jerstad Date: Wed, 11 Jun 2025 09:33:24 +0200 Subject: [PATCH] Implement media group for NFS permission management - Create shared media-group.nix module with fixed GID (993) - Add both geir and sma users to media group for shared NFS access - Update NFS server configuration to use root:media ownership with 0775 permissions - Convert all media services to use media group instead of users group: - Jellyfin, Calibre-web, Audiobookshelf, Transmission - Enable group write access to all NFS shares (/mnt/storage/*) - Maintain security with root ownership while allowing group collaboration This resolves NFS permission issues by providing consistent group-based access control across all media services and storage directories. --- machines/grey-area/services/audiobook.nix | 13 +++++++--- machines/grey-area/services/calibre-web.nix | 17 +++++++++---- machines/grey-area/services/jellyfin.nix | 21 ++++++++++------ machines/sleeper-service/nfs.nix | 25 ++++++++++++------- .../sleeper-service/services/transmission.nix | 15 ++++++----- modules/users/geir.nix | 5 ++++ modules/users/media-group.nix | 12 +++++++++ modules/users/sma.nix | 5 ++++ 8 files changed, 83 insertions(+), 30 deletions(-) create mode 100644 modules/users/media-group.nix diff --git a/machines/grey-area/services/audiobook.nix b/machines/grey-area/services/audiobook.nix index d1f7da3..4a97a7a 100644 --- a/machines/grey-area/services/audiobook.nix +++ b/machines/grey-area/services/audiobook.nix @@ -1,11 +1,18 @@ -{ configs, pkgs, ... }: { + configs, + pkgs, + ... +}: { + imports = [ + ../../../modules/users/media-group.nix + ]; + environment.systemPackages = [ pkgs.audiobookshelf ]; - services.audiobookshelf.group = "users"; + services.audiobookshelf.group = "media"; services.audiobookshelf.enable = true; - services.audiobookshelf.host = "0.0.0.0" ; + services.audiobookshelf.host = "0.0.0.0"; services.audiobookshelf.port = 8000; services.audiobookshelf.openFirewall = true; } diff --git a/machines/grey-area/services/calibre-web.nix b/machines/grey-area/services/calibre-web.nix index db6bd44..53f7e4b 100644 --- a/machines/grey-area/services/calibre-web.nix +++ b/machines/grey-area/services/calibre-web.nix @@ -1,16 +1,23 @@ -{ config, pkgs, ... }: { + config, + pkgs, + ... +}: { + imports = [ + ../../../modules/users/media-group.nix + ]; + services.calibre-web = { enable = true; - group = "users"; + group = "media"; listen = { - ip = "0.0.0.0"; - port = 8083; + ip = "0.0.0.0"; + port = 8083; }; options = { calibreLibrary = "/mnt/remote/media/books/calibre/"; enableBookUploading = true; }; }; - networking.firewall.allowedTCPPorts = [ 8083 ]; + networking.firewall.allowedTCPPorts = [8083]; } diff --git a/machines/grey-area/services/jellyfin.nix b/machines/grey-area/services/jellyfin.nix index f4625e7..ade7aec 100644 --- a/machines/grey-area/services/jellyfin.nix +++ b/machines/grey-area/services/jellyfin.nix @@ -1,9 +1,16 @@ -{ config, pkgs, ... }: { - services.jellyfin = { - enable = true; - group = "users"; - }; - networking.firewall.allowedTCPPorts = [ 8096 8920 ]; - networking.firewall.allowedUDPPorts = [ 1900 7359 ]; + config, + pkgs, + ... +}: { + imports = [ + ../../../modules/users/media-group.nix + ]; + + services.jellyfin = { + enable = true; + group = "media"; + }; + networking.firewall.allowedTCPPorts = [8096 8920]; + networking.firewall.allowedUDPPorts = [1900 7359]; } diff --git a/machines/sleeper-service/nfs.nix b/machines/sleeper-service/nfs.nix index 8398cab..939e361 100644 --- a/machines/sleeper-service/nfs.nix +++ b/machines/sleeper-service/nfs.nix @@ -1,8 +1,14 @@ # NFS Server Configuration # Network File System server for home lab storage -{ config, pkgs, ... }: - { + config, + pkgs, + ... +}: { + imports = [ + ../../modules/users/media-group.nix + ]; + # NFS server configuration services.nfs.server = { enable = true; @@ -16,13 +22,14 @@ createMountPoints = true; }; - # Ensure the storage subdirectories exist (ZFS dataset is mounted at /mnt/storage) - # systemd.tmpfiles.rules = [ - # "d /mnt/storage/media 0755 sma users -" - # "d /mnt/storage/downloads 0755 sma users -" - # "d /mnt/storage/backups 0755 sma users -" - # "d /mnt/storage/shares 0755 sma users -" - # ]; + # Ensure the storage subdirectories exist with proper ownership (ZFS dataset is mounted at /mnt/storage) + # Setting ownership to root:media with group write permissions for shared access + systemd.tmpfiles.rules = [ + "d /mnt/storage/media 0775 root media -" + "d /mnt/storage/downloads 0775 root media -" + "d /mnt/storage/backups 0775 root media -" + "d /mnt/storage/shares 0775 root media -" + ]; # Required packages for NFS environment.systemPackages = with pkgs; [ diff --git a/machines/sleeper-service/services/transmission.nix b/machines/sleeper-service/services/transmission.nix index 363bff1..7214992 100644 --- a/machines/sleeper-service/services/transmission.nix +++ b/machines/sleeper-service/services/transmission.nix @@ -1,14 +1,18 @@ { config, pkgs, ... }: { + imports = [ + ../../../modules/users/media-group.nix + ]; + services.transmission = { package = pkgs.transmission_4; enable = true; user = "sma"; # Using admin user for server processes - group = "users"; + group = "media"; settings.rpc-port = 9091; settings.rpc-bind-address = "0.0.0.0"; - downloadDirPermissions = "770"; + downloadDirPermissions = "775"; settings = { download-dir = "/mnt/storage/downloads"; rpc-whitelist = "127.0.0.1,10.0.0.*,100.*.*.*"; @@ -16,8 +20,7 @@ }; }; - # Ensure downloads directory exists even without Transmission - systemd.tmpfiles.rules = [ - "d /mnt/storage/downloads 0755 sma users -" - ]; + # Downloads directory ownership will be handled by NFS module tmpfiles rules + # Removed duplicate tmpfiles rule since NFS module already creates this directory +} } diff --git a/modules/users/geir.nix b/modules/users/geir.nix index e0c2de5..9c806a2 100644 --- a/modules/users/geir.nix +++ b/modules/users/geir.nix @@ -8,6 +8,10 @@ # Import custom packages from the flake homeLabPackages = import ../../packages {inherit pkgs;}; in { + imports = [ + ./media-group.nix + ]; + users.users.geir = { description = "Geir Okkenhaug Jerstad - Primary User"; isNormalUser = true; @@ -22,6 +26,7 @@ in { "audio" # audio devices "video" # video devices "render" # GPU access + "media" # shared media access for NFS shares ]; shell = pkgs.zsh; diff --git a/modules/users/media-group.nix b/modules/users/media-group.nix new file mode 100644 index 0000000..26666a2 --- /dev/null +++ b/modules/users/media-group.nix @@ -0,0 +1,12 @@ +# Media Group Configuration +# Shared group for NFS media access permissions +{ + config, + pkgs, + ... +}: { + # Create the media group for shared NFS access + users.groups.media = { + gid = 993; # Fixed GID for consistency across machines + }; +} diff --git a/modules/users/sma.nix b/modules/users/sma.nix index ed9f355..1c626b6 100644 --- a/modules/users/sma.nix +++ b/modules/users/sma.nix @@ -6,6 +6,10 @@ pkgs, ... }: { + imports = [ + ./media-group.nix + ]; + users.users.sma = { description = "Diziet Sma - System Administrator"; isNormalUser = true; @@ -20,6 +24,7 @@ "incus-admin" # container management "podman" # container runtime "docker" # docker compatibility (if needed) + "media" # shared media access for NFS shares ]; # Security-focused shell setup