at 25.11-pre 6.0 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7let 8 9 inInitrd = config.boot.initrd.supportedFilesystems.nfs or false; 10 11 nfsStateDir = "/var/lib/nfs"; 12 13 rpcMountpoint = "${nfsStateDir}/rpc_pipefs"; 14 15 format = pkgs.formats.ini { }; 16 17 idmapdConfFile = format.generate "idmapd.conf" cfg.idmapd.settings; 18 19 # merge parameters from services.nfs.server 20 nfsConfSettings = 21 lib.optionalAttrs (cfg.server.nproc != null) { 22 nfsd.threads = cfg.server.nproc; 23 } 24 // lib.optionalAttrs (cfg.server.hostName != null) { 25 nfsd.host = cfg.server.hostName; 26 } 27 // lib.optionalAttrs (cfg.server.mountdPort != null) { 28 mountd.port = cfg.server.mountdPort; 29 } 30 // lib.optionalAttrs (cfg.server.statdPort != null) { 31 statd.port = cfg.server.statdPort; 32 } 33 // lib.optionalAttrs (cfg.server.lockdPort != null) { 34 lockd.port = cfg.server.lockdPort; 35 lockd.udp-port = cfg.server.lockdPort; 36 }; 37 38 nfsConfDeprecated = 39 cfg.extraConfig 40 + '' 41 [nfsd] 42 threads=${toString cfg.server.nproc} 43 ${lib.optionalString (cfg.server.hostName != null) "host=${cfg.server.hostName}"} 44 ${cfg.server.extraNfsdConfig} 45 46 [mountd] 47 ${lib.optionalString (cfg.server.mountdPort != null) "port=${toString cfg.server.mountdPort}"} 48 49 [statd] 50 ${lib.optionalString (cfg.server.statdPort != null) "port=${toString cfg.server.statdPort}"} 51 52 [lockd] 53 ${lib.optionalString (cfg.server.lockdPort != null) '' 54 port=${toString cfg.server.lockdPort} 55 udp-port=${toString cfg.server.lockdPort} 56 ''} 57 ''; 58 59 nfsConfFile = 60 if cfg.settings != { } then 61 format.generate "nfs.conf" (lib.recursiveUpdate nfsConfSettings cfg.settings) 62 else 63 pkgs.writeText "nfs.conf" nfsConfDeprecated; 64 65 requestKeyConfFile = pkgs.writeText "request-key.conf" '' 66 create id_resolver * * ${pkgs.nfs-utils}/bin/nfsidmap -t 600 %k %d 67 ''; 68 69 cfg = config.services.nfs; 70 71in 72 73{ 74 ###### interface 75 76 options = { 77 services.nfs = { 78 idmapd.settings = lib.mkOption { 79 type = format.type; 80 default = { }; 81 description = '' 82 libnfsidmap configuration. Refer to 83 <https://linux.die.net/man/5/idmapd.conf> 84 for details. 85 ''; 86 example = lib.literalExpression '' 87 { 88 Translation = { 89 GSS-Methods = "static,nsswitch"; 90 }; 91 Static = { 92 "root/hostname.domain.com@REALM.COM" = "root"; 93 }; 94 } 95 ''; 96 }; 97 settings = lib.mkOption { 98 type = format.type; 99 default = { }; 100 description = '' 101 General configuration for NFS daemons and tools. 102 See {manpage}`nfs.conf(5)` and related man pages for details. 103 ''; 104 example = lib.literalExpression '' 105 { 106 mountd.manage-gids = true; 107 } 108 ''; 109 }; 110 extraConfig = lib.mkOption { 111 type = lib.types.lines; 112 default = ""; 113 description = '' 114 Extra nfs-utils configuration. 115 ''; 116 }; 117 }; 118 }; 119 120 ###### implementation 121 122 config = 123 lib.mkIf (config.boot.supportedFilesystems.nfs or config.boot.supportedFilesystems.nfs4 or false) 124 { 125 126 warnings = 127 (lib.optional (cfg.extraConfig != "") '' 128 `services.nfs.extraConfig` is deprecated. Use `services.nfs.settings` instead. 129 '') 130 ++ (lib.optional (cfg.server.extraNfsdConfig != "") '' 131 `services.nfs.server.extraNfsdConfig` is deprecated. Use `services.nfs.settings` instead. 132 ''); 133 assertions = [ 134 { 135 assertion = cfg.settings != { } -> cfg.extraConfig == "" && cfg.server.extraNfsdConfig == ""; 136 message = "`services.nfs.settings` cannot be used together with `services.nfs.extraConfig` and `services.nfs.server.extraNfsdConfig`."; 137 } 138 ]; 139 140 services.rpcbind.enable = true; 141 142 services.nfs.idmapd.settings = { 143 General = lib.mkMerge [ 144 { Pipefs-Directory = rpcMountpoint; } 145 (lib.mkIf (config.networking.domain != null) { Domain = config.networking.domain; }) 146 ]; 147 Mapping = { 148 Nobody-User = "nobody"; 149 Nobody-Group = "nogroup"; 150 }; 151 Translation = { 152 Method = "nsswitch"; 153 }; 154 }; 155 156 system.fsPackages = [ pkgs.nfs-utils ]; 157 158 boot.initrd.kernelModules = lib.mkIf inInitrd [ "nfs" ]; 159 160 systemd.packages = [ pkgs.nfs-utils ]; 161 162 environment.systemPackages = [ pkgs.keyutils ]; 163 164 environment.etc = { 165 "idmapd.conf".source = idmapdConfFile; 166 "nfs.conf".source = nfsConfFile; 167 "request-key.conf".source = requestKeyConfFile; 168 }; 169 170 systemd.services.nfs-blkmap = { 171 restartTriggers = [ nfsConfFile ]; 172 }; 173 174 systemd.targets.nfs-client = { 175 wantedBy = [ 176 "multi-user.target" 177 "remote-fs.target" 178 ]; 179 }; 180 181 systemd.services.nfs-idmapd = { 182 restartTriggers = [ idmapdConfFile ]; 183 }; 184 185 systemd.services.nfs-mountd = { 186 restartTriggers = [ nfsConfFile ]; 187 enable = lib.mkDefault false; 188 }; 189 190 systemd.services.nfs-server = { 191 restartTriggers = [ nfsConfFile ]; 192 enable = lib.mkDefault false; 193 }; 194 195 systemd.services.auth-rpcgss-module = { 196 unitConfig.ConditionPathExists = [ 197 "" 198 "/etc/krb5.keytab" 199 ]; 200 }; 201 202 systemd.services.rpc-gssd = { 203 restartTriggers = [ nfsConfFile ]; 204 unitConfig.ConditionPathExists = [ 205 "" 206 "/etc/krb5.keytab" 207 ]; 208 }; 209 210 systemd.services.rpc-statd = { 211 restartTriggers = [ nfsConfFile ]; 212 213 preStart = '' 214 mkdir -p /var/lib/nfs/{sm,sm.bak} 215 ''; 216 }; 217 218 }; 219}