1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.services.nfs.server; 8 9 exports = pkgs.writeText "exports" cfg.exports; 10 11in 12 13{ 14 15 ###### interface 16 17 options = { 18 19 services.nfs = { 20 21 server = { 22 enable = mkOption { 23 type = types.bool; 24 default = false; 25 description = '' 26 Whether to enable the kernel's NFS server. 27 ''; 28 }; 29 30 extraNfsdConfig = mkOption { 31 type = types.str; 32 default = ""; 33 description = '' 34 Extra configuration options for the [nfsd] section of /etc/nfs.conf. 35 ''; 36 }; 37 38 exports = mkOption { 39 type = types.lines; 40 default = ""; 41 description = '' 42 Contents of the /etc/exports file. See 43 <citerefentry><refentrytitle>exports</refentrytitle> 44 <manvolnum>5</manvolnum></citerefentry> for the format. 45 ''; 46 }; 47 48 hostName = mkOption { 49 type = types.nullOr types.str; 50 default = null; 51 description = '' 52 Hostname or address on which NFS requests will be accepted. 53 Default is all. See the <option>-H</option> option in 54 <citerefentry><refentrytitle>nfsd</refentrytitle> 55 <manvolnum>8</manvolnum></citerefentry>. 56 ''; 57 }; 58 59 nproc = mkOption { 60 type = types.int; 61 default = 8; 62 description = '' 63 Number of NFS server threads. Defaults to the recommended value of 8. 64 ''; 65 }; 66 67 createMountPoints = mkOption { 68 type = types.bool; 69 default = false; 70 description = "Whether to create the mount points in the exports file at startup time."; 71 }; 72 73 mountdPort = mkOption { 74 type = types.nullOr types.int; 75 default = null; 76 example = 4002; 77 description = '' 78 Use fixed port for rpc.mountd, useful if server is behind firewall. 79 ''; 80 }; 81 82 lockdPort = mkOption { 83 type = types.nullOr types.int; 84 default = null; 85 example = 4001; 86 description = '' 87 Use a fixed port for the NFS lock manager kernel module 88 (<literal>lockd/nlockmgr</literal>). This is useful if the 89 NFS server is behind a firewall. 90 ''; 91 }; 92 93 statdPort = mkOption { 94 type = types.nullOr types.int; 95 default = null; 96 example = 4000; 97 description = '' 98 Use a fixed port for <command>rpc.statd</command>. This is 99 useful if the NFS server is behind a firewall. 100 ''; 101 }; 102 103 }; 104 105 }; 106 107 }; 108 109 110 ###### implementation 111 112 config = mkIf cfg.enable { 113 114 services.nfs.extraConfig = '' 115 [nfsd] 116 threads=${toString cfg.nproc} 117 ${optionalString (cfg.hostName != null) "host=${cfg.hostName}"} 118 ${cfg.extraNfsdConfig} 119 120 [mountd] 121 ${optionalString (cfg.mountdPort != null) "port=${toString cfg.mountdPort}"} 122 123 [statd] 124 ${optionalString (cfg.statdPort != null) "port=${toString cfg.statdPort}"} 125 126 [lockd] 127 ${optionalString (cfg.lockdPort != null) '' 128 port=${toString cfg.lockdPort} 129 udp-port=${toString cfg.lockdPort} 130 ''} 131 ''; 132 133 services.rpcbind.enable = true; 134 135 boot.supportedFilesystems = [ "nfs" ]; # needed for statd and idmapd 136 137 environment.etc.exports.source = exports; 138 139 systemd.services.nfs-server = 140 { enable = true; 141 wantedBy = [ "multi-user.target" ]; 142 143 preStart = 144 '' 145 mkdir -p /var/lib/nfs/v4recovery 146 ''; 147 }; 148 149 systemd.services.nfs-mountd = 150 { enable = true; 151 restartTriggers = [ exports ]; 152 153 preStart = 154 '' 155 mkdir -p /var/lib/nfs 156 157 ${optionalString cfg.createMountPoints 158 '' 159 # create export directories: 160 # skip comments, take first col which may either be a quoted 161 # "foo bar" or just foo (-> man export) 162 sed '/^#.*/d;s/^"\([^"]*\)".*/\1/;t;s/[ ].*//' ${exports} \ 163 | xargs -d '\n' mkdir -p 164 '' 165 } 166 ''; 167 }; 168 169 }; 170 171}