8 # TODO: test configuration when building nixexpr (use -t parameter)
9 # TODO: support sqlite3 (it's deprecate?) and mysql
22 libDir = "/var/lib/bacula";
24 yes_no = bool: if bool then "yes" else "no";
27 optionalString tls_cfg.enable (
28 concatStringsSep "\n" (
29 [ "TLS Enable = yes;" ]
30 ++ optional (tls_cfg.require != null) "TLS Require = ${yes_no tls_cfg.require};"
31 ++ optional (tls_cfg.certificate != null) ''TLS Certificate = "${tls_cfg.certificate}";''
32 ++ [ ''TLS Key = "${tls_cfg.key}";'' ]
33 ++ optional (tls_cfg.verifyPeer != null) "TLS Verify Peer = ${yes_no tls_cfg.verifyPeer};"
35 tls_cfg.allowedCN != [ ]
36 ) "TLS Allowed CN = ${concatStringsSep " " (tls_cfg.allowedCN)};"
38 tls_cfg.caCertificateFile != null
39 ) ''TLS CA Certificate File = "${tls_cfg.caCertificateFile}";''
43 fd_cfg = config.services.bacula-fd;
44 fd_conf = pkgs.writeText "bacula-fd.conf" ''
46 Name = "${fd_cfg.name}";
47 FDPort = ${toString fd_cfg.port};
48 WorkingDirectory = ${libDir};
50 ${fd_cfg.extraClientConfig}
51 ${tls_conf fd_cfg.tls}
54 ${concatStringsSep "\n" (
55 mapAttrsToList (name: value: ''
58 Password = ${value.password};
59 Monitor = ${value.monitor};
67 syslog = all, !skipped, !restored
68 ${fd_cfg.extraMessagesConfig}
72 sd_cfg = config.services.bacula-sd;
73 sd_conf = pkgs.writeText "bacula-sd.conf" ''
75 Name = "${sd_cfg.name}";
76 SDPort = ${toString sd_cfg.port};
77 WorkingDirectory = ${libDir};
79 ${sd_cfg.extraStorageConfig}
80 ${tls_conf sd_cfg.tls}
83 ${concatStringsSep "\n" (
84 mapAttrsToList (name: value: ''
87 Device = ${concatStringsSep ", " (map (a: "\"${a}\"") value.devices)};
88 Changer Device = ${value.changerDevice};
89 Changer Command = ${value.changerCommand};
90 ${value.extraAutochangerConfig}
92 '') sd_cfg.autochanger
95 ${concatStringsSep "\n" (
96 mapAttrsToList (name: value: ''
99 Archive Device = ${value.archiveDevice};
100 Media Type = ${value.mediaType};
101 ${value.extraDeviceConfig}
106 ${concatStringsSep "\n" (
107 mapAttrsToList (name: value: ''
110 Password = ${value.password};
111 Monitor = ${value.monitor};
112 ${tls_conf value.tls}
119 syslog = all, !skipped, !restored
120 ${sd_cfg.extraMessagesConfig}
124 dir_cfg = config.services.bacula-dir;
125 dir_conf = pkgs.writeText "bacula-dir.conf" ''
127 Name = "${dir_cfg.name}";
128 Password = ${dir_cfg.password};
129 DirPort = ${toString dir_cfg.port};
130 Working Directory = ${libDir};
131 Pid Directory = /run/;
132 QueryFile = ${pkgs.bacula}/etc/query.sql;
133 ${tls_conf dir_cfg.tls}
134 ${dir_cfg.extraDirectorConfig}
145 syslog = all, !skipped, !restored
146 ${dir_cfg.extraMessagesConfig}
149 ${dir_cfg.extraConfig}
153 name: destination: "[${name}](#opt-${builtins.replaceStrings [ "<" ">" ] [ "_" "_" ] destination})";
155 destination: submodulePath:
156 linkOption "${submodulePath}.${destination}" "${submodulePath}.${destination}";
167 Specifies if TLS should be enabled.
168 If this set to `false` TLS will be completely disabled, even if ${tlsLink "tls.require" submodulePath} is true.
172 type = types.nullOr types.bool;
175 Require TLS or TLS-PSK encryption.
176 This directive is ignored unless one of ${tlsLink "tls.enable" submodulePath} is true or TLS PSK Enable is set to `yes`.
177 If TLS is not required while TLS or TLS-PSK are enabled, then the Bacula component
178 will connect with other components either with or without TLS or TLS-PSK
180 If ${tlsLink "tls.enable" submodulePath} or TLS-PSK is enabled and TLS is required, then the Bacula
181 component will refuse any connection request that does not use TLS.
184 certificate = mkOption {
185 type = types.nullOr types.path;
188 The full path to the PEM encoded TLS certificate.
189 It will be used as either a client or server certificate,
190 depending on the connection direction.
191 This directive is required in a server context, but it may
192 not be specified in a client context if ${tlsLink "tls.verifyPeer" submodulePath} is
193 `false` in the corresponding server context.
199 The path of a PEM encoded TLS private key.
200 It must correspond to the TLS certificate.
203 verifyPeer = mkOption {
204 type = types.nullOr types.bool;
207 Verify peer certificate.
208 Instructs server to request and verify the client's X.509 certificate.
209 Any client certificate signed by a known-CA will be accepted.
210 Additionally, the client's X509 certificate Common Name must meet the value of the Address directive.
211 If ${tlsLink "tls.allowedCN" submodulePath} is used,
212 the client's x509 certificate Common Name must also correspond to
213 one of the CN specified in the ${tlsLink "tls.allowedCN" submodulePath} directive.
214 This directive is valid only for a server and not in client context.
216 Standard from Bacula is `true`.
219 allowedCN = mkOption {
220 type = types.listOf types.str;
223 Common name attribute of allowed peer certificates.
224 This directive is valid for a server and in a client context.
225 If this directive is specified, the peer certificate will be verified against this list.
226 In the case this directive is configured on a server side, the allowed
227 CN list will not be checked if ${tlsLink "tls.verifyPeer" submodulePath} is false.
230 caCertificateFile = mkOption {
231 type = types.nullOr types.path;
234 The path specifying a PEM encoded TLS CA certificate(s).
235 Multiple certificates are permitted in the file.
236 One of TLS CA Certificate File or TLS CA Certificate Dir are required in a server context, unless
237 ${tlsLink "tls.verifyPeer" submodulePath} is false, and are always required in a client context.
248 password = mkOption {
252 Specifies the password that must be supplied for the default Bacula
253 Console to be authorized. The same password must appear in the
254 Director resource of the Console configuration file. For added
255 security, the password is never passed across the network but instead
256 a challenge response hash code created with the password. This
257 directive is required. If you have either /dev/random or bc on your
258 machine, Bacula will generate a random password during the
259 configuration process, otherwise it will be left blank and you must
262 The password is plain text. It is not generated through any special
263 process but as noted above, it is better to use random text for
276 If Monitor is set to `no`, this director will have
277 full access to this Storage daemon. If Monitor is set to
278 `yes`, this director will only be able to fetch the
279 current status of this Storage daemon.
281 Please note that if this director is being used by a Monitor, we
282 highly recommend to set this directive to yes to avoid serious
288 type = types.submodule (tlsOptions "${submodulePath}.director.<name>");
290 TLS Options for the Director in this Configuration.
300 changerDevice = mkOption {
303 The specified name-string must be the generic SCSI device name of the
304 autochanger that corresponds to the normal read/write Archive Device
305 specified in the Device resource. This generic SCSI device name
306 should be specified if you have an autochanger or if you have a
307 standard tape drive and want to use the Alert Command (see below).
308 For example, on Linux systems, for an Archive Device name of
309 `/dev/nst0`, you would specify
310 `/dev/sg0` for the Changer Device name. Depending
311 on your exact configuration, and the number of autochangers or the
312 type of autochanger, what you specify here can vary. This directive
313 is optional. See the Using AutochangersAutochangersChapter chapter of
314 this manual for more details of using this and the following
315 autochanger directives.
319 changerCommand = mkOption {
322 The name-string specifies an external program to be called that will
323 automatically change volumes as required by Bacula. Normally, this
324 directive will be specified only in the AutoChanger resource, which
325 is then used for all devices. However, you may also specify the
326 different Changer Command in each Device resource. Most frequently,
327 you will specify the Bacula supplied mtx-changer script as follows:
329 `"/path/mtx-changer %c %o %S %a %d"`
331 and you will install the mtx on your system (found in the depkgs
332 release). An example of this command is in the default bacula-sd.conf
333 file. For more details on the substitution characters that may be
334 specified to configure your autochanger please see the
335 AutochangersAutochangersChapter chapter of this manual. For FreeBSD
336 users, you might want to see one of the several chio scripts in
337 examples/autochangers.
339 default = "/etc/bacula/mtx-changer %c %o %S %a %d";
344 type = types.listOf types.str;
347 extraAutochangerConfig = mkOption {
351 Extra configuration to be passed in Autochanger directive.
364 archiveDevice = mkOption {
368 The specified name-string gives the system file name of the storage
369 device managed by this storage daemon. This will usually be the
370 device file name of a removable storage device (tape drive), for
371 example `/dev/nst0` or
372 `/dev/rmt/0mbn`. For a DVD-writer, it will be for
373 example `/dev/hdc`. It may also be a directory name
374 if you are archiving to disk storage. In this case, you must supply
375 the full absolute path to the directory. When specifying a tape
376 device, it is preferable that the "non-rewind" variant of the device
381 mediaType = mkOption {
385 The specified name-string names the type of media supported by this
386 device, for example, `DLT7000`. Media type names are
387 arbitrary in that you set them to anything you want, but they must be
388 known to the volume database to keep track of which storage daemons
389 can read which volumes. In general, each different storage type
390 should have a unique Media Type associated with it. The same
391 name-string must appear in the appropriate Storage resource
392 definition in the Director's configuration file.
394 Even though the names you assign are arbitrary (i.e. you choose the
395 name you want), you should take care in specifying them because the
396 Media Type is used to determine which storage device Bacula will
397 select during restore. Thus you should probably use the same Media
398 Type specification for all drives where the Media can be freely
399 interchanged. This is not generally an issue if you have a single
400 Storage daemon, but it is with multiple Storage daemons, especially
401 if they have incompatible media.
403 For example, if you specify a Media Type of `DDS-4`
404 then during the restore, Bacula will be able to choose any Storage
405 Daemon that handles `DDS-4`. If you have an
406 autochanger, you might want to name the Media Type in a way that is
407 unique to the autochanger, unless you wish to possibly use the
408 Volumes in other drives. You should also ensure to have unique Media
409 Type names if the Media is not compatible between drives. This
410 specification is required for all devices.
412 In addition, if you are using disk storage, each Device resource will
413 generally have a different mount point or directory. In order for
414 Bacula to select the correct Device resource, each one must have a
419 extraDeviceConfig = mkOption {
423 Extra configuration to be passed in Device directive.
440 services.bacula-fd = {
445 Whether to enable the Bacula File Daemon.
450 default = "${config.networking.hostName}-fd";
451 defaultText = literalExpression ''"''${config.networking.hostName}-fd"'';
454 The client name that must be used by the Director when connecting.
455 Generally, it is a good idea to use a name related to the machine so
456 that error messages can be easily identified if you have multiple
457 Clients. This directive is required.
465 This specifies the port number on which the Client listens for
466 Director connections. It must agree with the FDPort specified in
467 the Client resource of the Director's configuration file.
471 director = mkOption {
474 This option defines director resources in Bacula File Daemon.
476 type = types.attrsOf (types.submodule (directorOptions "services.bacula-fd"));
480 type = types.submodule (tlsOptions "services.bacula-fd");
483 TLS Options for the File Daemon.
484 Important notice: The backup won't be encrypted.
488 extraClientConfig = mkOption {
492 Extra configuration to be passed in Client directive.
495 Maximum Concurrent Jobs = 20;
496 Heartbeat Interval = 30;
500 extraMessagesConfig = mkOption {
504 Extra configuration to be passed in Messages directive.
512 services.bacula-sd = {
517 Whether to enable Bacula Storage Daemon.
522 default = "${config.networking.hostName}-sd";
523 defaultText = literalExpression ''"''${config.networking.hostName}-sd"'';
526 Specifies the Name of the Storage daemon.
534 Specifies port number on which the Storage daemon listens for
535 Director connections.
539 director = mkOption {
542 This option defines Director resources in Bacula Storage Daemon.
544 type = types.attrsOf (types.submodule (directorOptions "services.bacula-sd"));
550 This option defines Device resources in Bacula Storage Daemon.
552 type = types.attrsOf (types.submodule deviceOptions);
555 autochanger = mkOption {
558 This option defines Autochanger resources in Bacula Storage Daemon.
560 type = types.attrsOf (types.submodule autochangerOptions);
563 extraStorageConfig = mkOption {
567 Extra configuration to be passed in Storage directive.
570 Maximum Concurrent Jobs = 20;
571 Heartbeat Interval = 30;
575 extraMessagesConfig = mkOption {
579 Extra configuration to be passed in Messages directive.
586 type = types.submodule (tlsOptions "services.bacula-sd");
589 TLS Options for the Storage Daemon.
590 Important notice: The backup won't be encrypted.
596 services.bacula-dir = {
601 Whether to enable Bacula Director Daemon.
606 default = "${config.networking.hostName}-dir";
607 defaultText = literalExpression ''"''${config.networking.hostName}-dir"'';
610 The director name used by the system administrator. This directive is
619 Specify the port (a positive integer) on which the Director daemon
620 will listen for Bacula Console connections. This same port number
621 must be specified in the Director resource of the Console
622 configuration file. The default is 9101, so normally this directive
623 need not be specified. This directive should not be used if you
624 specify DirAddresses (N.B plural) directive.
628 password = mkOption {
632 Specifies the password that must be supplied for a Director.
636 extraMessagesConfig = mkOption {
640 Extra configuration to be passed in Messages directive.
647 extraDirectorConfig = mkOption {
651 Extra configuration to be passed in Director directive.
654 Maximum Concurrent Jobs = 20;
655 Heartbeat Interval = 30;
659 extraConfig = mkOption {
663 Extra configuration for Bacula Director Daemon.
671 type = types.submodule (tlsOptions "services.bacula-dir");
674 TLS Options for the Director.
675 Important notice: The backup won't be encrypted.
681 config = mkIf (fd_cfg.enable || sd_cfg.enable || dir_cfg.enable) {
682 systemd.slices.system-bacula = {
683 description = "Bacula Backup System Slice";
686 "https://www.bacula.org/"
690 systemd.services.bacula-fd = mkIf fd_cfg.enable {
691 after = [ "network.target" ];
692 description = "Bacula File Daemon";
693 wantedBy = [ "multi-user.target" ];
694 path = [ pkgs.bacula ];
696 ExecStart = "${pkgs.bacula}/sbin/bacula-fd -f -u root -g bacula -c ${fd_conf}";
697 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
698 LogsDirectory = "bacula";
699 StateDirectory = "bacula";
700 Slice = "system-bacula.slice";
704 systemd.services.bacula-sd = mkIf sd_cfg.enable {
705 after = [ "network.target" ];
706 description = "Bacula Storage Daemon";
707 wantedBy = [ "multi-user.target" ];
708 path = [ pkgs.bacula ];
710 ExecStart = "${pkgs.bacula}/sbin/bacula-sd -f -u bacula -g bacula -c ${sd_conf}";
711 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
712 LogsDirectory = "bacula";
713 StateDirectory = "bacula";
714 Slice = "system-bacula.slice";
718 services.postgresql.enable = lib.mkIf dir_cfg.enable true;
720 systemd.services.bacula-dir = mkIf dir_cfg.enable {
725 description = "Bacula Director Daemon";
726 wantedBy = [ "multi-user.target" ];
727 path = [ pkgs.bacula ];
729 ExecStart = "${pkgs.bacula}/sbin/bacula-dir -f -u bacula -g bacula -c ${dir_conf}";
730 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
731 LogsDirectory = "bacula";
732 StateDirectory = "bacula";
733 Slice = "system-bacula.slice";
736 if ! test -e "${libDir}/db-created"; then
737 ${pkgs.postgresql}/bin/createuser --no-superuser --no-createdb --no-createrole bacula
738 #${pkgs.postgresql}/bin/createdb --owner bacula bacula
741 ${pkgs.bacula}/etc/create_bacula_database postgresql
742 ${pkgs.bacula}/etc/make_bacula_tables postgresql
743 ${pkgs.bacula}/etc/grant_bacula_privileges postgresql
744 touch "${libDir}/db-created"
746 ${pkgs.bacula}/etc/update_bacula_tables postgresql || true
751 environment.systemPackages = [ pkgs.bacula ];
753 users.users.bacula = {
755 uid = config.ids.uids.bacula;
758 description = "Bacula Daemons user";
759 shell = "${pkgs.bash}/bin/bash";
762 users.groups.bacula.gid = config.ids.gids.bacula;