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