1{ config, lib, pkgs, ... }:
2
3# TODO: test configuration when building nixexpr (use -t parameter)
4# TODO: support sqlite3 (it's deprecate?) and mysql
5
6with lib;
7
8let
9 libDir = "/var/lib/bacula";
10
11 fd_cfg = config.services.bacula-fd;
12 fd_conf = pkgs.writeText "bacula-fd.conf"
13 ''
14 Client {
15 Name = "${fd_cfg.name}";
16 FDPort = ${toString fd_cfg.port};
17 WorkingDirectory = "${libDir}";
18 Pid Directory = "/var/run";
19 ${fd_cfg.extraClientConfig}
20 }
21
22 ${concatStringsSep "\n" (mapAttrsToList (name: value: ''
23 Director {
24 Name = "${name}";
25 Password = "${value.password}";
26 Monitor = "${value.monitor}";
27 }
28 '') fd_cfg.director)}
29
30 Messages {
31 Name = Standard;
32 syslog = all, !skipped, !restored
33 ${fd_cfg.extraMessagesConfig}
34 }
35 '';
36
37 sd_cfg = config.services.bacula-sd;
38 sd_conf = pkgs.writeText "bacula-sd.conf"
39 ''
40 Storage {
41 Name = "${sd_cfg.name}";
42 SDPort = ${toString sd_cfg.port};
43 WorkingDirectory = "${libDir}";
44 Pid Directory = "/var/run";
45 ${sd_cfg.extraStorageConfig}
46 }
47
48 ${concatStringsSep "\n" (mapAttrsToList (name: value: ''
49 Device {
50 Name = "${name}";
51 Archive Device = "${value.archiveDevice}";
52 Media Type = "${value.mediaType}";
53 ${value.extraDeviceConfig}
54 }
55 '') sd_cfg.device)}
56
57 ${concatStringsSep "\n" (mapAttrsToList (name: value: ''
58 Director {
59 Name = "${name}";
60 Password = "${value.password}";
61 Monitor = "${value.monitor}";
62 }
63 '') sd_cfg.director)}
64
65 Messages {
66 Name = Standard;
67 syslog = all, !skipped, !restored
68 ${sd_cfg.extraMessagesConfig}
69 }
70 '';
71
72 dir_cfg = config.services.bacula-dir;
73 dir_conf = pkgs.writeText "bacula-dir.conf"
74 ''
75 Director {
76 Name = "${dir_cfg.name}";
77 Password = "${dir_cfg.password}";
78 DirPort = ${toString dir_cfg.port};
79 Working Directory = "${libDir}";
80 Pid Directory = "/var/run/";
81 QueryFile = "${pkgs.bacula}/etc/query.sql";
82 ${dir_cfg.extraDirectorConfig}
83 }
84
85 Catalog {
86 Name = "PostgreSQL";
87 dbname = "bacula";
88 user = "bacula";
89 }
90
91 Messages {
92 Name = Standard;
93 syslog = all, !skipped, !restored
94 ${dir_cfg.extraMessagesConfig}
95 }
96
97 ${dir_cfg.extraConfig}
98 '';
99
100 directorOptions = {...}:
101 {
102 options = {
103 password = mkOption {
104 # TODO: required?
105 description = ''
106 Specifies the password that must be supplied for a Director to b
107 '';
108 };
109
110 monitor = mkOption {
111 default = "no";
112 example = "yes";
113 description = ''
114 If Monitor is set to no (default), this director will have full
115 '';
116 };
117 };
118 };
119
120 deviceOptions = {...}:
121 {
122 options = {
123 archiveDevice = mkOption {
124 # TODO: required?
125 description = ''
126 The specified name-string gives the system file name of the storage device managed by this storage daemon. This will usually be the device file name of a removable storage device (tape drive), for example " /dev/nst0" or "/dev/rmt/0mbn". For a DVD-writer, it will be for example /dev/hdc. It may also be a directory name if you are archiving to disk storage.
127 '';
128 };
129
130 mediaType = mkOption {
131 # TODO: required?
132 description = ''
133 The specified name-string names the type of media supported by this device, for example, "DLT7000". Media type names are arbitrary in that you set them to anything you want, but they must be known to the volume database to keep track of which storage daemons can read which volumes. In general, each different storage type should have a unique Media Type associated with it. The same name-string must appear in the appropriate Storage resource definition in the Director's configuration file.
134 '';
135 };
136
137 extraDeviceConfig = mkOption {
138 default = "";
139 description = ''
140 Extra configuration to be passed in Device directive.
141 '';
142 example = ''
143 LabelMedia = yes
144 Random Access = no
145 AutomaticMount = no
146 RemovableMedia = no
147 MaximumOpenWait = 60
148 AlwaysOpen = no
149 '';
150 };
151 };
152 };
153
154in {
155 options = {
156 services.bacula-fd = {
157 enable = mkOption {
158 type = types.bool;
159 default = false;
160 description = ''
161 Whether to enable the Bacula File Daemon.
162 '';
163 };
164
165 name = mkOption {
166 default = "${config.networking.hostName}-fd";
167 description = ''
168 The client name that must be used by the Director when connecting.
169 Generally, it is a good idea to use a name related to the machine
170 so that error messages can be easily identified if you have multiple
171 Clients. This directive is required.
172 '';
173 };
174
175 port = mkOption {
176 default = 9102;
177 type = types.int;
178 description = ''
179 This specifies the port number on which the Client listens for
180 Director connections. It must agree with the FDPort specified in
181 the Client resource of the Director's configuration file.
182 '';
183 };
184
185 director = mkOption {
186 default = {};
187 description = ''
188 This option defines director resources in Bacula File Daemon.
189 '';
190 type = with types; attrsOf (submodule directorOptions);
191 };
192
193 extraClientConfig = mkOption {
194 default = "";
195 description = ''
196 Extra configuration to be passed in Client directive.
197 '';
198 example = ''
199 Maximum Concurrent Jobs = 20;
200 Heartbeat Interval = 30;
201 '';
202 };
203
204 extraMessagesConfig = mkOption {
205 default = "";
206 description = ''
207 Extra configuration to be passed in Messages directive.
208 '';
209 example = ''
210 console = all
211 '';
212 };
213 };
214
215 services.bacula-sd = {
216 enable = mkOption {
217 type = types.bool;
218 default = false;
219 description = ''
220 Whether to enable Bacula Storage Daemon.
221 '';
222 };
223
224 name = mkOption {
225 default = "${config.networking.hostName}-sd";
226 description = ''
227 Specifies the Name of the Storage daemon.
228 '';
229 };
230
231 port = mkOption {
232 default = 9103;
233 type = types.int;
234 description = ''
235 Specifies port number on which the Storage daemon listens for Director connections. The default is 9103.
236 '';
237 };
238
239 director = mkOption {
240 default = {};
241 description = ''
242 This option defines Director resources in Bacula Storage Daemon.
243 '';
244 type = with types; attrsOf (submodule directorOptions);
245 };
246
247 device = mkOption {
248 default = {};
249 description = ''
250 This option defines Device resources in Bacula Storage Daemon.
251 '';
252 type = with types; attrsOf (submodule deviceOptions);
253 };
254
255 extraStorageConfig = mkOption {
256 default = "";
257 description = ''
258 Extra configuration to be passed in Storage directive.
259 '';
260 example = ''
261 Maximum Concurrent Jobs = 20;
262 Heartbeat Interval = 30;
263 '';
264 };
265
266 extraMessagesConfig = mkOption {
267 default = "";
268 description = ''
269 Extra configuration to be passed in Messages directive.
270 '';
271 example = ''
272 console = all
273 '';
274 };
275
276 };
277
278 services.bacula-dir = {
279 enable = mkOption {
280 type = types.bool;
281 default = false;
282 description = ''
283 Whether to enable Bacula Director Daemon.
284 '';
285 };
286
287 name = mkOption {
288 default = "${config.networking.hostName}-dir";
289 description = ''
290 The director name used by the system administrator. This directive is required.
291 '';
292 };
293
294 port = mkOption {
295 default = 9101;
296 type = types.int;
297 description = ''
298 Specify the port (a positive integer) on which the Director daemon will listen for Bacula Console connections. This same port number must be specified in the Director resource of the Console configuration file. The default is 9101, so normally this directive need not be specified. This directive should not be used if you specify DirAddresses (N.B plural) directive.
299 '';
300 };
301
302 password = mkOption {
303 # TODO: required?
304 description = ''
305 Specifies the password that must be supplied for a Director.
306 '';
307 };
308
309 extraMessagesConfig = mkOption {
310 default = "";
311 description = ''
312 Extra configuration to be passed in Messages directive.
313 '';
314 example = ''
315 console = all
316 '';
317 };
318
319 extraDirectorConfig = mkOption {
320 default = "";
321 description = ''
322 Extra configuration to be passed in Director directive.
323 '';
324 example = ''
325 Maximum Concurrent Jobs = 20;
326 Heartbeat Interval = 30;
327 '';
328 };
329
330 extraConfig = mkOption {
331 default = "";
332 type = types.lines;
333 description = ''
334 Extra configuration for Bacula Director Daemon.
335 '';
336 example = ''
337 TODO
338 '';
339 };
340 };
341 };
342
343 config = mkIf (fd_cfg.enable || sd_cfg.enable || dir_cfg.enable) {
344 systemd.services.bacula-fd = mkIf fd_cfg.enable {
345 after = [ "network.target" ];
346 description = "Bacula File Daemon";
347 wantedBy = [ "multi-user.target" ];
348 path = [ pkgs.bacula ];
349 serviceConfig.ExecStart = "${pkgs.bacula}/sbin/bacula-fd -f -u root -g bacula -c ${fd_conf}";
350 serviceConfig.ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
351 };
352
353 systemd.services.bacula-sd = mkIf sd_cfg.enable {
354 after = [ "network.target" ];
355 description = "Bacula Storage Daemon";
356 wantedBy = [ "multi-user.target" ];
357 path = [ pkgs.bacula ];
358 serviceConfig.ExecStart = "${pkgs.bacula}/sbin/bacula-sd -f -u bacula -g bacula -c ${sd_conf}";
359 serviceConfig.ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
360 };
361
362 services.postgresql.enable = dir_cfg.enable == true;
363
364 systemd.services.bacula-dir = mkIf dir_cfg.enable {
365 after = [ "network.target" "postgresql.service" ];
366 description = "Bacula Director Daemon";
367 wantedBy = [ "multi-user.target" ];
368 path = [ pkgs.bacula ];
369 serviceConfig.ExecStart = "${pkgs.bacula}/sbin/bacula-dir -f -u bacula -g bacula -c ${dir_conf}";
370 serviceConfig.ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
371 preStart = ''
372 if ! test -e "${libDir}/db-created"; then
373 ${pkgs.postgresql}/bin/createuser --no-superuser --no-createdb --no-createrole bacula
374 #${pkgs.postgresql}/bin/createdb --owner bacula bacula
375
376 # populate DB
377 ${pkgs.bacula}/etc/create_bacula_database postgresql
378 ${pkgs.bacula}/etc/make_bacula_tables postgresql
379 ${pkgs.bacula}/etc/grant_bacula_privileges postgresql
380 touch "${libDir}/db-created"
381 else
382 ${pkgs.bacula}/etc/update_bacula_tables postgresql || true
383 fi
384 '';
385 };
386
387 environment.systemPackages = [ pkgs.bacula ];
388
389 users.users.bacula = {
390 group = "bacula";
391 uid = config.ids.uids.bacula;
392 home = "${libDir}";
393 createHome = true;
394 description = "Bacula Daemons user";
395 shell = "${pkgs.bash}/bin/bash";
396 };
397
398 users.groups.bacula.gid = config.ids.gids.bacula;
399 };
400}