1{ config, lib, pkgs, ... }:
2
3# openafsBin, openafsSrv, mkCellServDB
4with import ./lib.nix { inherit config lib pkgs; };
5
6let
7 inherit (lib) concatStringsSep mkIf mkOption optionalString types;
8
9 bosConfig = pkgs.writeText "BosConfig" (''
10 restrictmode 1
11 restarttime 16 0 0 0 0
12 checkbintime 3 0 5 0 0
13 '' + (optionalString cfg.roles.database.enable ''
14 bnode simple vlserver 1
15 parm ${openafsSrv}/libexec/openafs/vlserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} ${cfg.roles.database.vlserverArgs}
16 end
17 bnode simple ptserver 1
18 parm ${openafsSrv}/libexec/openafs/ptserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} ${cfg.roles.database.ptserverArgs}
19 end
20 '') + (optionalString cfg.roles.fileserver.enable ''
21 bnode dafs dafs 1
22 parm ${openafsSrv}/libexec/openafs/dafileserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} -udpsize ${udpSizeStr} ${cfg.roles.fileserver.fileserverArgs}
23 parm ${openafsSrv}/libexec/openafs/davolserver ${optionalString cfg.dottedPrincipals "-allow-dotted-principals"} -udpsize ${udpSizeStr} ${cfg.roles.fileserver.volserverArgs}
24 parm ${openafsSrv}/libexec/openafs/salvageserver ${cfg.roles.fileserver.salvageserverArgs}
25 parm ${openafsSrv}/libexec/openafs/dasalvager ${cfg.roles.fileserver.salvagerArgs}
26 end
27 '') + (optionalString (cfg.roles.database.enable && cfg.roles.backup.enable) ''
28 bnode simple buserver 1
29 parm ${openafsSrv}/libexec/openafs/buserver ${cfg.roles.backup.buserverArgs} ${optionalString (cfg.roles.backup.cellServDB != []) "-cellservdb /etc/openafs/backup/"}
30 end
31 ''));
32
33 netInfo = if (cfg.advertisedAddresses != []) then
34 pkgs.writeText "NetInfo" ((concatStringsSep "\nf " cfg.advertisedAddresses) + "\n")
35 else null;
36
37 buCellServDB = pkgs.writeText "backup-cellServDB-${cfg.cellName}" (mkCellServDB cfg.cellName cfg.roles.backup.cellServDB);
38
39 cfg = config.services.openafsServer;
40
41 udpSizeStr = toString cfg.udpPacketSize;
42
43in {
44
45 options = {
46
47 services.openafsServer = {
48
49 enable = mkOption {
50 default = false;
51 type = types.bool;
52 description = ''
53 Whether to enable the OpenAFS server. An OpenAFS server needs a
54 complex setup. So, be aware that enabling this service and setting
55 some options does not give you a turn-key-ready solution. You need
56 at least a running Kerberos 5 setup, as OpenAFS relies on it for
57 authentication. See the Guide "QuickStartUnix" coming with
58 <literal>pkgs.openafs.doc</literal> for complete setup
59 instructions.
60 '';
61 };
62
63 advertisedAddresses = mkOption {
64 default = [];
65 description = "List of IP addresses this server is advertised under. See NetInfo(5)";
66 };
67
68 cellName = mkOption {
69 default = "";
70 type = types.str;
71 description = "Cell name, this server will serve.";
72 example = "grand.central.org";
73 };
74
75 cellServDB = mkOption {
76 default = [];
77 type = with types; listOf (submodule [ { options = cellServDBConfig;} ]);
78 description = "Definition of all cell-local database server machines.";
79 };
80
81 package = mkOption {
82 default = pkgs.openafs.server or pkgs.openafs;
83 type = types.package;
84 description = "OpenAFS package for the server binaries";
85 };
86
87 roles = {
88 fileserver = {
89 enable = mkOption {
90 default = true;
91 type = types.bool;
92 description = "Fileserver role, serves files and volumes from its local storage.";
93 };
94
95 fileserverArgs = mkOption {
96 default = "-vattachpar 128 -vhashsize 11 -L -rxpck 400 -cb 1000000";
97 type = types.str;
98 description = "Arguments to the dafileserver process. See its man page.";
99 };
100
101 volserverArgs = mkOption {
102 default = "";
103 type = types.str;
104 description = "Arguments to the davolserver process. See its man page.";
105 example = "-sync never";
106 };
107
108 salvageserverArgs = mkOption {
109 default = "";
110 type = types.str;
111 description = "Arguments to the salvageserver process. See its man page.";
112 example = "-showlog";
113 };
114
115 salvagerArgs = mkOption {
116 default = "";
117 type = types.str;
118 description = "Arguments to the dasalvager process. See its man page.";
119 example = "-showlog -showmounts";
120 };
121 };
122
123 database = {
124 enable = mkOption {
125 default = true;
126 type = types.bool;
127 description = ''
128 Database server role, maintains the Volume Location Database,
129 Protection Database (and Backup Database, see
130 <literal>backup</literal> role). There can be multiple
131 servers in the database role for replication, which then need
132 reliable network connection to each other.
133
134 Servers in this role appear in AFSDB DNS records or the
135 CellServDB.
136 '';
137 };
138
139 vlserverArgs = mkOption {
140 default = "";
141 type = types.str;
142 description = "Arguments to the vlserver process. See its man page.";
143 example = "-rxbind";
144 };
145
146 ptserverArgs = mkOption {
147 default = "";
148 type = types.str;
149 description = "Arguments to the ptserver process. See its man page.";
150 example = "-restricted -default_access S---- S-M---";
151 };
152 };
153
154 backup = {
155 enable = mkOption {
156 default = false;
157 type = types.bool;
158 description = ''
159 Backup server role. Use in conjunction with the
160 <literal>database</literal> role to maintain the Backup
161 Database. Normally only used in conjunction with tape storage
162 or IBM's Tivoli Storage Manager.
163 '';
164 };
165
166 buserverArgs = mkOption {
167 default = "";
168 type = types.str;
169 description = "Arguments to the buserver process. See its man page.";
170 example = "-p 8";
171 };
172
173 cellServDB = mkOption {
174 default = [];
175 type = with types; listOf (submodule [ { options = cellServDBConfig;} ]);
176 description = ''
177 Definition of all cell-local backup database server machines.
178 Use this when your cell uses less backup database servers than
179 other database server machines.
180 '';
181 };
182 };
183 };
184
185 dottedPrincipals= mkOption {
186 default = false;
187 type = types.bool;
188 description = ''
189 If enabled, allow principal names containing (.) dots. Enabling
190 this has security implications!
191 '';
192 };
193
194 udpPacketSize = mkOption {
195 default = 1310720;
196 type = types.int;
197 description = ''
198 UDP packet size to use in Bytes. Higher values can speed up
199 communications. The default of 1 MB is a sufficient in most
200 cases. Make sure to increase the kernel's UDP buffer size
201 accordingly via <literal>net.core(w|r|opt)mem_max</literal>
202 sysctl.
203 '';
204 };
205
206 };
207
208 };
209
210 config = mkIf cfg.enable {
211
212 assertions = [
213 { assertion = cfg.cellServDB != [];
214 message = "You must specify all cell-local database servers in config.services.openafsServer.cellServDB.";
215 }
216 { assertion = cfg.cellName != "";
217 message = "You must specify the local cell name in config.services.openafsServer.cellName.";
218 }
219 ];
220
221 environment.systemPackages = [ openafsBin ];
222
223 environment.etc = {
224 bosConfig = {
225 source = bosConfig;
226 target = "openafs/BosConfig";
227 mode = "0644";
228 };
229 cellServDB = {
230 text = mkCellServDB cfg.cellName cfg.cellServDB;
231 target = "openafs/server/CellServDB";
232 mode = "0644";
233 };
234 thisCell = {
235 text = cfg.cellName;
236 target = "openafs/server/ThisCell";
237 mode = "0644";
238 };
239 buCellServDB = {
240 enable = (cfg.roles.backup.cellServDB != []);
241 text = mkCellServDB cfg.cellName cfg.roles.backup.cellServDB;
242 target = "openafs/backup/CellServDB";
243 };
244 };
245
246 systemd.services = {
247 openafs-server = {
248 description = "OpenAFS server";
249 after = [ "syslog.target" "network.target" ];
250 wantedBy = [ "multi-user.target" ];
251 restartIfChanged = false;
252 unitConfig.ConditionPathExists = [
253 "|/etc/openafs/server/rxkad.keytab"
254 "|/etc/openafs/server/KeyFileExt"
255 ];
256 preStart = ''
257 mkdir -m 0755 -p /var/openafs
258 ${optionalString (netInfo != null) "cp ${netInfo} /var/openafs/netInfo"}
259 ${optionalString (cfg.roles.backup.cellServDB != []) "cp ${buCellServDB}"}
260 '';
261 serviceConfig = {
262 ExecStart = "${openafsBin}/bin/bosserver -nofork";
263 ExecStop = "${openafsBin}/bin/bos shutdown localhost -wait -localauth";
264 };
265 };
266 };
267 };
268}