From 1403b1f9c0b2b8f7f1ad971b698e68ec79541857 Mon Sep 17 00:00:00 2001 From: Tibo De Peuter Date: Fri, 17 Jul 2026 23:24:17 +0200 Subject: [PATCH] refactor: abstract NFS mount creation via custom options --- modules/apps/arr/default.nix | 39 ++++++++--------- modules/apps/calibre/default.nix | 30 ++++---------- modules/apps/freshrss/default.nix | 11 ++--- modules/apps/gitea/default.nix | 21 +--------- modules/apps/homepage/default.nix | 9 +--- modules/apps/jellyfin/default.nix | 43 ++++--------------- modules/common/default.nix | 1 + modules/common/nfs.nix | 46 +++++++++++++++++++++ modules/fileSystems/media/video/default.nix | 13 +++--- 9 files changed, 93 insertions(+), 120 deletions(-) create mode 100644 modules/common/nfs.nix diff --git a/modules/apps/arr/default.nix b/modules/apps/arr/default.nix index 5f69663..1b1ce53 100644 --- a/modules/apps/arr/default.nix +++ b/modules/apps/arr/default.nix @@ -61,29 +61,26 @@ in { virtualisation.containers.enable = lib.mkIf inUse true; }; - fileSystems = let - mkFileSystem = device: { - inherit device; - fsType = "nfs"; - options = [ - "rw" - "auto" - "nfsvers=4.2" - "rsize=1048576" "wsize=1048576" - "hard" - "timeo=600" "retrans=2" - "_netdev" "nosuid" "tcp" - ]; - }; - + homelab.nfsMounts = let hugoBackup = "192.168.0.11:/mnt/BIG/BACKUP"; + arrOptions = [ + "auto" + "rsize=1048576" "wsize=1048576" + "hard" + "timeo=600" "retrans=2" + "_netdev" + ]; + mkMount = device: { + inherit device; + extraOptions = arrOptions; + }; in lib.mkIf inUse { - "/srv/bazarr-backup" = lib.mkIf cfg.bazarr.enable (mkFileSystem "${hugoBackup}/BAZARR"); - "/srv/prowlarr-backup" = lib.mkIf cfg.bazarr.enable (mkFileSystem "${hugoBackup}/PROWLARR"); - "/srv/qbittorrent" = lib.mkIf cfg.qbittorrent.enable (mkFileSystem "192.168.0.11:/mnt/SMALL/CONFIG/QBITTORRENT"); - "/srv/radarr-backup" = lib.mkIf cfg.radarr.enable (mkFileSystem "${hugoBackup}/RADARR"); - "/srv/sonarr-backup" = lib.mkIf cfg.sonarr.enable (mkFileSystem "${hugoBackup}/SONARR"); - "/srv/torrent" = mkFileSystem "192.168.0.11:/mnt/SMALL/MEDIA/TORRENT"; + "/srv/bazarr-backup" = lib.mkIf cfg.bazarr.enable (mkMount "${hugoBackup}/BAZARR"); + "/srv/prowlarr-backup" = lib.mkIf cfg.bazarr.enable (mkMount "${hugoBackup}/PROWLARR"); + "/srv/qbittorrent" = lib.mkIf cfg.qbittorrent.enable (mkMount "192.168.0.11:/mnt/SMALL/CONFIG/QBITTORRENT"); + "/srv/radarr-backup" = lib.mkIf cfg.radarr.enable (mkMount "${hugoBackup}/RADARR"); + "/srv/sonarr-backup" = lib.mkIf cfg.sonarr.enable (mkMount "${hugoBackup}/SONARR"); + "/srv/torrent" = mkMount "192.168.0.11:/mnt/SMALL/MEDIA/TORRENT"; }; # Make sure the Docker network exists. diff --git a/modules/apps/calibre/default.nix b/modules/apps/calibre/default.nix index 9018f1e..ea722bc 100644 --- a/modules/apps/calibre/default.nix +++ b/modules/apps/calibre/default.nix @@ -42,17 +42,13 @@ in { shell = null; }; - fileSystems."${books}" = { + homelab.nfsMounts."${books}" = { device = "192.168.0.11:/mnt/SMALL/MEDIA/BOOKS"; - fsType = "nfs"; - options = [ - "rw" + extraOptions = [ "auto" - "nfsvers=4.2" "rsize=1048576" "wsize=1048576" - "soft" "timeo=600" "retrans=2" - "_netdev" "nosuid" "tcp" + "_netdev" ]; }; @@ -66,17 +62,13 @@ in { # Calibre desktop (lib.mkIf cfg.desktop.enable { - fileSystems."${calibre-config}" = { + homelab.nfsMounts."${calibre-config}" = { device = "192.168.0.11:/mnt/SMALL/CONFIG/CALIBRE"; - fsType = "nfs"; - options = [ - "rw" + extraOptions = [ "auto" - "nfsvers=4.2" "rsize=1048576" "wsize=1048576" - "soft" "timeo=600" "retrans=2" - "_netdev" "nosuid" "tcp" + "_netdev" ]; }; @@ -124,17 +116,13 @@ in { # Calibre Web (lib.mkIf cfg.web.enable { - fileSystems."${calibre-web-config}" = { + homelab.nfsMounts."${calibre-web-config}" = { device = "192.168.0.11:/mnt/SMALL/CONFIG/CALIBRE-WEB"; - fsType = "nfs"; - options = [ - "rw" + extraOptions = [ "auto" - "nfsvers=4.2" "rsize=1048576" "wsize=1048576" - "soft" "timeo=600" "retrans=2" - "_netdev" "nosuid" "tcp" + "_netdev" ]; }; diff --git a/modules/apps/freshrss/default.nix b/modules/apps/freshrss/default.nix index bf6af85..c0729a1 100644 --- a/modules/apps/freshrss/default.nix +++ b/modules/apps/freshrss/default.nix @@ -20,18 +20,13 @@ in { lib.mkIf cfg.enable { homelab.virtualisation.containers.enable = true; - fileSystems."/srv/freshrss" = { + homelab.nfsMounts."/srv/freshrss" = { device = "192.168.0.11:/mnt/SMALL/CONFIG/FRESHRSS"; - fsType = "nfs"; - options = [ - "rw" + extraOptions = [ "auto" - "nfsvers=4.2" - "async" "soft" "timeo=600" + "timeo=600" "retrans=2" "_netdev" - "nosuid" - "tcp" ]; }; diff --git a/modules/apps/gitea/default.nix b/modules/apps/gitea/default.nix index 95feea5..9073c38 100644 --- a/modules/apps/gitea/default.nix +++ b/modules/apps/gitea/default.nix @@ -40,32 +40,13 @@ in { # Use filesystem mounts because rootless containers otherwise don't have access to the mount path (nested in docker directories). # You could probably fix this by modifying the access rights on the path, but what would the point of that be? - fileSystems = { - # Mount options: - # - hard: retry requests indefinitely if the server becomes unresponsive. - # - nosuid: prevent set-user-id and set-group-id bits + homelab.nfsMounts = { "/srv/gitea-config" = { device = "192.168.0.11:/mnt/SMALL/CONFIG/GITEA"; - fsType = "nfs"; - options = [ - "rw" - "nfsvers=4.2" - "async" "soft" "timeo=100" "retry=50" "actimeo=1800" "lookupcache=all" - "nosuid" - "tcp" - ]; }; "/srv/gitea-git" = { device = "192.168.0.11:/mnt/SMALL/DATA/GIT"; - fsType = "nfs"; - options = [ - "rw" - "nfsvers=4.2" - "async" "soft" "timeo=100" "retry=50" "actimeo=1800" "lookupcache=all" - "nosuid" - "tcp" - ]; }; }; diff --git a/modules/apps/homepage/default.nix b/modules/apps/homepage/default.nix index b34f32f..cc1b43b 100644 --- a/modules/apps/homepage/default.nix +++ b/modules/apps/homepage/default.nix @@ -34,15 +34,10 @@ in { shell = null; }; - fileSystems."${homepage-config}" = { + homelab.nfsMounts."${homepage-config}" = { device = "192.168.0.11:/mnt/SMALL/CONFIG/HOMEPAGE"; - fsType = "nfs"; - options = [ - "rw" + extraOptions = [ "auto" - "nfsvers=4.2" - "async" "soft" "timeo=100" "retry=50" "actimeo=1800" "lookupcache=all" - "nosuid" "tcp" ]; }; diff --git a/modules/apps/jellyfin/default.nix b/modules/apps/jellyfin/default.nix index 6e422b2..560f527 100644 --- a/modules/apps/jellyfin/default.nix +++ b/modules/apps/jellyfin/default.nix @@ -25,42 +25,15 @@ in { virtualisation.containers.enable = true; }; - fileSystems = { - "/srv/audio" = { - device = "192.168.0.11:/mnt/SMALL/MEDIA/AUDIO"; - fsType = "nfs"; - options = [ - "ro" - "nfsvers=4.2" - "async" "soft" - "timeo=100" "retry=50" "actimeo=1800" "lookupcache=all" - "nosuid" "tcp" - ]; - }; - - "/srv/homevideo" = { - device = "192.168.0.11:/mnt/BIG/MEDIA/HOMEVIDEO/ARCHIVE"; - fsType = "nfs"; - options = [ - "ro" - "nfsvers=4.2" - "async" "soft" - "timeo=100" "retry=50" "actimeo=1800" "lookupcache=all" - "nosuid" "tcp" - ]; - }; - - "/srv/photo" = { - device = "192.168.0.11:/mnt/BIG/MEDIA/PHOTO/ARCHIVE"; - fsType = "nfs"; - options = [ - "ro" - "nfsvers=4.2" - "async" "soft" - "timeo=100" "retry=50" "actimeo=1800" "lookupcache=all" - "nosuid" "tcp" - ]; + homelab.nfsMounts = let + mkMount = device: { + inherit device; + readOnly = true; }; + in { + "/srv/audio" = mkMount "192.168.0.11:/mnt/SMALL/MEDIA/AUDIO"; + "/srv/homevideo" = mkMount "192.168.0.11:/mnt/BIG/MEDIA/HOMEVIDEO/ARCHIVE"; + "/srv/photo" = mkMount "192.168.0.11:/mnt/BIG/MEDIA/PHOTO/ARCHIVE"; }; users.users.jellyfin = { diff --git a/modules/common/default.nix b/modules/common/default.nix index 5d4b801..0a6ac0e 100644 --- a/modules/common/default.nix +++ b/modules/common/default.nix @@ -2,6 +2,7 @@ imports = [ ./docker.nix ./monitoring.nix + ./nfs.nix ]; config = { diff --git a/modules/common/nfs.nix b/modules/common/nfs.nix new file mode 100644 index 0000000..251676f --- /dev/null +++ b/modules/common/nfs.nix @@ -0,0 +1,46 @@ +{ config, lib, ... }: + +{ + options.homelab.nfsMounts = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule { + options = { + device = lib.mkOption { + type = lib.types.str; + description = "The NFS device, e.g. 192.168.0.11:/mnt/POOL/DATA"; + }; + readOnly = lib.mkOption { + type = lib.types.bool; + default = false; + description = "Whether to mount the NFS share read-only"; + }; + extraOptions = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ + "async" + "soft" + "timeo=100" + "retry=50" + "actimeo=1800" + "lookupcache=all" + ]; + description = "Extra NFS mount options to append"; + }; + }; + }); + default = {}; + description = "NFS mounts to automatically configure with standard homelab options"; + }; + + config = { + fileSystems = lib.mapAttrs (path: cfg: { + device = cfg.device; + fsType = "nfs"; + options = [ + "nfsvers=4.2" + "nosuid" + "tcp" + ] ++ (if cfg.readOnly then [ "ro" ] else [ "rw" ]) + ++ cfg.extraOptions; + }) config.homelab.nfsMounts; + }; +} diff --git a/modules/fileSystems/media/video/default.nix b/modules/fileSystems/media/video/default.nix index e46193c..55b6068 100644 --- a/modules/fileSystems/media/video/default.nix +++ b/modules/fileSystems/media/video/default.nix @@ -25,17 +25,14 @@ in { }; config = lib.mkIf cfg.enable { - fileSystems."${cfg.hostPath}" = { + homelab.nfsMounts."${cfg.hostPath}" = { device = "192.168.0.11:${remotePath}"; - fsType = "nfs"; - options = [ - permissionsOption + readOnly = permissionsOption == "ro"; + extraOptions = [ "auto" - "nfsvers=4.2" - "async" "soft" "rsize=1048576" "wsize=1048576" - "timeo=600" "retry=50" "retrans=2" "actimeo=1800" "lookupcache=all" - "_netdev" "nosuid" "tcp" + "timeo=600" "retrans=2" + "_netdev" ]; }; };