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}