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