vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / backup / bacula.nix
blob0851b5b0bf14f6624c212beac3b5f3fb53f3f1a8
1 { config, lib, pkgs, ... }:
4 # TODO: test configuration when building nixexpr (use -t parameter)
5 # TODO: support sqlite3 (it's deprecate?) and mysql
8 let
9   inherit (lib)
10     concatStringsSep
11     literalExpression
12     mapAttrsToList
13     mkIf
14     mkOption
15     optional
16     optionalString
17     types
18     ;
19   libDir = "/var/lib/bacula";
21   yes_no = bool: if bool then "yes" else "no";
22   tls_conf = tls_cfg: optionalString tls_cfg.enable (
23     concatStringsSep
24       "\n"
25       (
26       ["TLS Enable = yes;"]
27       ++ optional (tls_cfg.require != null) "TLS Require = ${yes_no tls_cfg.require};"
28       ++ optional (tls_cfg.certificate != null) ''TLS Certificate = "${tls_cfg.certificate}";''
29       ++ [''TLS Key = "${tls_cfg.key}";'']
30       ++ optional (tls_cfg.verifyPeer != null) "TLS Verify Peer = ${yes_no tls_cfg.verifyPeer};"
31       ++ optional (tls_cfg.allowedCN != [ ]) "TLS Allowed CN = ${concatStringsSep " " (tls_cfg.allowedCN)};"
32       ++ optional (tls_cfg.caCertificateFile != null) ''TLS CA Certificate File = "${tls_cfg.caCertificateFile}";''
33       )
34   );
36   fd_cfg = config.services.bacula-fd;
37   fd_conf = pkgs.writeText "bacula-fd.conf"
38     ''
39       Client {
40         Name = "${fd_cfg.name}";
41         FDPort = ${toString fd_cfg.port};
42         WorkingDirectory = ${libDir};
43         Pid Directory = /run;
44         ${fd_cfg.extraClientConfig}
45         ${tls_conf fd_cfg.tls}
46       }
48       ${concatStringsSep "\n" (mapAttrsToList (name: value: ''
49       Director {
50         Name = "${name}";
51         Password = ${value.password};
52         Monitor = ${value.monitor};
53         ${tls_conf value.tls}
54       }
55       '') fd_cfg.director)}
57       Messages {
58         Name = Standard;
59         syslog = all, !skipped, !restored
60         ${fd_cfg.extraMessagesConfig}
61       }
62     '';
64   sd_cfg = config.services.bacula-sd;
65   sd_conf = pkgs.writeText "bacula-sd.conf"
66     ''
67       Storage {
68         Name = "${sd_cfg.name}";
69         SDPort = ${toString sd_cfg.port};
70         WorkingDirectory = ${libDir};
71         Pid Directory = /run;
72         ${sd_cfg.extraStorageConfig}
73         ${tls_conf sd_cfg.tls}
74       }
76       ${concatStringsSep "\n" (mapAttrsToList (name: value: ''
77       Autochanger {
78         Name = "${name}";
79         Device = ${concatStringsSep ", " (map (a: "\"${a}\"") value.devices)};
80         Changer Device =  ${value.changerDevice};
81         Changer Command = ${value.changerCommand};
82         ${value.extraAutochangerConfig}
83       }
84       '') sd_cfg.autochanger)}
86       ${concatStringsSep "\n" (mapAttrsToList (name: value: ''
87       Device {
88         Name = "${name}";
89         Archive Device = ${value.archiveDevice};
90         Media Type = ${value.mediaType};
91         ${value.extraDeviceConfig}
92       }
93       '') sd_cfg.device)}
95       ${concatStringsSep "\n" (mapAttrsToList (name: value: ''
96       Director {
97         Name = "${name}";
98         Password = ${value.password};
99         Monitor = ${value.monitor};
100         ${tls_conf value.tls}
101       }
102       '') sd_cfg.director)}
104       Messages {
105         Name = Standard;
106         syslog = all, !skipped, !restored
107         ${sd_cfg.extraMessagesConfig}
108       }
109     '';
111   dir_cfg = config.services.bacula-dir;
112   dir_conf = pkgs.writeText "bacula-dir.conf"
113     ''
114     Director {
115       Name = "${dir_cfg.name}";
116       Password = ${dir_cfg.password};
117       DirPort = ${toString dir_cfg.port};
118       Working Directory = ${libDir};
119       Pid Directory = /run/;
120       QueryFile = ${pkgs.bacula}/etc/query.sql;
121       ${tls_conf dir_cfg.tls}
122       ${dir_cfg.extraDirectorConfig}
123     }
125     Catalog {
126       Name = PostgreSQL;
127       dbname = bacula;
128       user = bacula;
129     }
131     Messages {
132       Name = Standard;
133       syslog = all, !skipped, !restored
134       ${dir_cfg.extraMessagesConfig}
135     }
137     ${dir_cfg.extraConfig}
138     '';
140   linkOption = name: destination: "[${name}](#opt-${builtins.replaceStrings [ "<" ">"] ["_" "_"] destination})";
141   tlsLink = destination: submodulePath: linkOption "${submodulePath}.${destination}" "${submodulePath}.${destination}";
143   tlsOptions = submodulePath: {...}:
144   {
145     options = {
146       enable = mkOption {
147         type = types.bool;
148         default = false;
149         description = ''
150           Specifies if TLS should be enabled.
151           If this set to `false` TLS will be completely disabled, even if ${tlsLink "tls.require" submodulePath} is true.
152         '';
153       };
154       require = mkOption {
155         type = types.nullOr types.bool;
156         default = null;
157         description = ''
158           Require TLS or TLS-PSK encryption.
159           This directive is ignored unless one of ${tlsLink "tls.enable" submodulePath} is true or TLS PSK Enable is set to `yes`.
160           If TLS is not required while TLS or TLS-PSK are enabled, then the Bacula component
161           will connect with other components either with or without TLS or TLS-PSK
163           If ${tlsLink "tls.enable" submodulePath} or TLS-PSK is enabled and TLS is required, then the Bacula
164           component will refuse any connection request that does not use TLS.
165         '';
166       };
167       certificate = mkOption {
168         type = types.nullOr types.path;
169         default = null;
170         description = ''
171           The full path to the PEM encoded TLS certificate.
172           It will be used as either a client or server certificate,
173           depending on the connection direction.
174           This directive is required in a server context, but it may
175           not be specified in a client context if ${tlsLink "tls.verifyPeer" submodulePath} is
176           `false` in the corresponding server context.
177         '';
178       };
179       key = mkOption {
180         type = types.path;
181         description = ''
182           The path of a PEM encoded TLS private key.
183           It must correspond to the TLS certificate.
184         '';
185       };
186       verifyPeer = mkOption {
187         type = types.nullOr types.bool;
188         default = null;
189         description = ''
190           Verify peer certificate.
191           Instructs server to request and verify the client's X.509 certificate.
192           Any client certificate signed by a known-CA will be accepted.
193           Additionally, the client's X509 certificate Common Name must meet the value of the Address directive.
194           If ${tlsLink "tls.allowedCN" submodulePath} is used,
195           the client's x509 certificate Common Name must also correspond to
196           one of the CN specified in the ${tlsLink "tls.allowedCN" submodulePath} directive.
197           This directive is valid only for a server and not in client context.
199           Standard from Bacula is `true`.
200         '';
201       };
202       allowedCN = mkOption {
203         type = types.listOf types.str;
204         default = [ ];
205         description = ''
206           Common name attribute of allowed peer certificates.
207           This directive is valid for a server and in a client context.
208           If this directive is specified, the peer certificate will be verified against this list.
209           In the case this directive is configured on a server side, the allowed
210           CN list will not be checked if ${tlsLink "tls.verifyPeer" submodulePath} is false.
211         '';
212       };
213       caCertificateFile = mkOption {
214         type = types.nullOr types.path;
215         default = null;
216         description = ''
217           The path specifying a PEM encoded TLS CA certificate(s).
218           Multiple certificates are permitted in the file.
219           One of TLS CA Certificate File or TLS CA Certificate Dir are required in a server context, unless
220           ${tlsLink "tls.verifyPeer" submodulePath} is false, and are always required in a client context.
221         '';
222       };
223     };
224   };
226   directorOptions = submodulePath:{...}:
227   {
228     options = {
229       password = mkOption {
230         type = types.str;
231         # TODO: required?
232         description = ''
233           Specifies the password that must be supplied for the default Bacula
234           Console to be authorized. The same password must appear in the
235           Director resource of the Console configuration file. For added
236           security, the password is never passed across the network but instead
237           a challenge response hash code created with the password. This
238           directive is required. If you have either /dev/random or bc on your
239           machine, Bacula will generate a random password during the
240           configuration process, otherwise it will be left blank and you must
241           manually supply it.
243           The password is plain text. It is not generated through any special
244           process but as noted above, it is better to use random text for
245           security reasons.
246         '';
247       };
249       monitor = mkOption {
250         type = types.enum [ "no" "yes" ];
251         default = "no";
252         example = "yes";
253         description = ''
254           If Monitor is set to `no`, this director will have
255           full access to this Storage daemon. If Monitor is set to
256           `yes`, this director will only be able to fetch the
257           current status of this Storage daemon.
259           Please note that if this director is being used by a Monitor, we
260           highly recommend to set this directive to yes to avoid serious
261           security problems.
262         '';
263       };
265       tls = mkOption {
266         type = types.submodule (tlsOptions "${submodulePath}.director.<name>");
267         description = ''
268           TLS Options for the Director in this Configuration.
269         '';
270       };
271     };
272   };
274   autochangerOptions = {...}:
275   {
276     options = {
277       changerDevice = mkOption {
278         type = types.str;
279         description = ''
280           The specified name-string must be the generic SCSI device name of the
281           autochanger that corresponds to the normal read/write Archive Device
282           specified in the Device resource. This generic SCSI device name
283           should be specified if you have an autochanger or if you have a
284           standard tape drive and want to use the Alert Command (see below).
285           For example, on Linux systems, for an Archive Device name of
286           `/dev/nst0`, you would specify
287           `/dev/sg0` for the Changer Device name.  Depending
288           on your exact configuration, and the number of autochangers or the
289           type of autochanger, what you specify here can vary. This directive
290           is optional. See the Using AutochangersAutochangersChapter chapter of
291           this manual for more details of using this and the following
292           autochanger directives.
293           '';
294       };
296       changerCommand = mkOption {
297         type = types.str;
298         description = ''
299           The name-string specifies an external program to be called that will
300           automatically change volumes as required by Bacula. Normally, this
301           directive will be specified only in the AutoChanger resource, which
302           is then used for all devices. However, you may also specify the
303           different Changer Command in each Device resource. Most frequently,
304           you will specify the Bacula supplied mtx-changer script as follows:
306           `"/path/mtx-changer %c %o %S %a %d"`
308           and you will install the mtx on your system (found in the depkgs
309           release). An example of this command is in the default bacula-sd.conf
310           file. For more details on the substitution characters that may be
311           specified to configure your autochanger please see the
312           AutochangersAutochangersChapter chapter of this manual. For FreeBSD
313           users, you might want to see one of the several chio scripts in
314           examples/autochangers.
315           '';
316         default = "/etc/bacula/mtx-changer %c %o %S %a %d";
317       };
319       devices = mkOption {
320         description = "";
321         type = types.listOf types.str;
322       };
324       extraAutochangerConfig = mkOption {
325         default = "";
326         type = types.lines;
327         description = ''
328           Extra configuration to be passed in Autochanger directive.
329         '';
330         example = ''
332         '';
333       };
334     };
335   };
338   deviceOptions = {...}:
339   {
340     options = {
341       archiveDevice = mkOption {
342         # TODO: required?
343         type = types.str;
344         description = ''
345           The specified name-string gives the system file name of the storage
346           device managed by this storage daemon. This will usually be the
347           device file name of a removable storage device (tape drive), for
348           example `/dev/nst0` or
349           `/dev/rmt/0mbn`. For a DVD-writer, it will be for
350           example `/dev/hdc`. It may also be a directory name
351           if you are archiving to disk storage. In this case, you must supply
352           the full absolute path to the directory. When specifying a tape
353           device, it is preferable that the "non-rewind" variant of the device
354           file name be given.
355         '';
356       };
358       mediaType = mkOption {
359         # TODO: required?
360         type = types.str;
361         description = ''
362           The specified name-string names the type of media supported by this
363           device, for example, `DLT7000`. Media type names are
364           arbitrary in that you set them to anything you want, but they must be
365           known to the volume database to keep track of which storage daemons
366           can read which volumes. In general, each different storage type
367           should have a unique Media Type associated with it. The same
368           name-string must appear in the appropriate Storage resource
369           definition in the Director's configuration file.
371           Even though the names you assign are arbitrary (i.e. you choose the
372           name you want), you should take care in specifying them because the
373           Media Type is used to determine which storage device Bacula will
374           select during restore. Thus you should probably use the same Media
375           Type specification for all drives where the Media can be freely
376           interchanged. This is not generally an issue if you have a single
377           Storage daemon, but it is with multiple Storage daemons, especially
378           if they have incompatible media.
380           For example, if you specify a Media Type of `DDS-4`
381           then during the restore, Bacula will be able to choose any Storage
382           Daemon that handles `DDS-4`. If you have an
383           autochanger, you might want to name the Media Type in a way that is
384           unique to the autochanger, unless you wish to possibly use the
385           Volumes in other drives. You should also ensure to have unique Media
386           Type names if the Media is not compatible between drives. This
387           specification is required for all devices.
389           In addition, if you are using disk storage, each Device resource will
390           generally have a different mount point or directory. In order for
391           Bacula to select the correct Device resource, each one must have a
392           unique Media Type.
393         '';
394       };
396       extraDeviceConfig = mkOption {
397         default = "";
398         type = types.lines;
399         description = ''
400           Extra configuration to be passed in Device directive.
401         '';
402         example = ''
403           LabelMedia = yes
404           Random Access = no
405           AutomaticMount = no
406           RemovableMedia = no
407           MaximumOpenWait = 60
408           AlwaysOpen = no
409         '';
410       };
411     };
412   };
414 in {
415   options = {
416     services.bacula-fd = {
417       enable = mkOption {
418         type = types.bool;
419         default = false;
420         description = ''
421           Whether to enable the Bacula File Daemon.
422         '';
423       };
425       name = mkOption {
426         default = "${config.networking.hostName}-fd";
427         defaultText = literalExpression ''"''${config.networking.hostName}-fd"'';
428         type = types.str;
429         description = ''
430           The client name that must be used by the Director when connecting.
431           Generally, it is a good idea to use a name related to the machine so
432           that error messages can be easily identified if you have multiple
433           Clients. This directive is required.
434         '';
435       };
437       port = mkOption {
438         default = 9102;
439         type = types.port;
440         description = ''
441           This specifies the port number on which the Client listens for
442           Director connections. It must agree with the FDPort specified in
443           the Client resource of the Director's configuration file.
444         '';
445       };
447       director = mkOption {
448         default = {};
449         description = ''
450           This option defines director resources in Bacula File Daemon.
451         '';
452         type = types.attrsOf (types.submodule (directorOptions "services.bacula-fd"));
453       };
456       tls = mkOption {
457         type = types.submodule (tlsOptions "services.bacula-fd");
458         default = { };
459         description = ''
460           TLS Options for the File Daemon.
461           Important notice: The backup won't be encrypted.
462         '';
463        };
465       extraClientConfig = mkOption {
466         default = "";
467         type = types.lines;
468         description = ''
469           Extra configuration to be passed in Client directive.
470         '';
471         example = ''
472           Maximum Concurrent Jobs = 20;
473           Heartbeat Interval = 30;
474         '';
475       };
477       extraMessagesConfig = mkOption {
478         default = "";
479         type = types.lines;
480         description = ''
481           Extra configuration to be passed in Messages directive.
482         '';
483         example = ''
484           console = all
485         '';
486       };
487     };
489     services.bacula-sd = {
490       enable = mkOption {
491         type = types.bool;
492         default = false;
493         description = ''
494           Whether to enable Bacula Storage Daemon.
495         '';
496       };
498       name = mkOption {
499         default = "${config.networking.hostName}-sd";
500         defaultText = literalExpression ''"''${config.networking.hostName}-sd"'';
501         type = types.str;
502         description = ''
503           Specifies the Name of the Storage daemon.
504         '';
505       };
507       port = mkOption {
508         default = 9103;
509         type = types.port;
510         description = ''
511           Specifies port number on which the Storage daemon listens for
512           Director connections.
513         '';
514       };
516       director = mkOption {
517         default = {};
518         description = ''
519           This option defines Director resources in Bacula Storage Daemon.
520         '';
521         type = types.attrsOf (types.submodule (directorOptions "services.bacula-sd"));
522       };
524       device = mkOption {
525         default = {};
526         description = ''
527           This option defines Device resources in Bacula Storage Daemon.
528         '';
529         type = types.attrsOf (types.submodule deviceOptions);
530       };
532       autochanger = mkOption {
533         default = {};
534         description = ''
535           This option defines Autochanger resources in Bacula Storage Daemon.
536         '';
537         type = types.attrsOf (types.submodule autochangerOptions);
538       };
540       extraStorageConfig = mkOption {
541         default = "";
542         type = types.lines;
543         description = ''
544           Extra configuration to be passed in Storage directive.
545         '';
546         example = ''
547           Maximum Concurrent Jobs = 20;
548           Heartbeat Interval = 30;
549         '';
550       };
552       extraMessagesConfig = mkOption {
553         default = "";
554         type = types.lines;
555         description = ''
556           Extra configuration to be passed in Messages directive.
557         '';
558         example = ''
559           console = all
560         '';
561       };
562       tls = mkOption {
563         type = types.submodule (tlsOptions "services.bacula-sd");
564         default = { };
565         description = ''
566           TLS Options for the Storage Daemon.
567           Important notice: The backup won't be encrypted.
568         '';
569        };
571     };
573     services.bacula-dir = {
574       enable = mkOption {
575         type = types.bool;
576         default = false;
577         description = ''
578           Whether to enable Bacula Director Daemon.
579         '';
580       };
582       name = mkOption {
583         default = "${config.networking.hostName}-dir";
584         defaultText = literalExpression ''"''${config.networking.hostName}-dir"'';
585         type = types.str;
586         description = ''
587           The director name used by the system administrator. This directive is
588           required.
589         '';
590       };
592       port = mkOption {
593         default = 9101;
594         type = types.port;
595         description = ''
596           Specify the port (a positive integer) on which the Director daemon
597           will listen for Bacula Console connections. This same port number
598           must be specified in the Director resource of the Console
599           configuration file. The default is 9101, so normally this directive
600           need not be specified. This directive should not be used if you
601           specify DirAddresses (N.B plural) directive.
602         '';
603       };
605       password = mkOption {
606         # TODO: required?
607         type = types.str;
608         description = ''
609            Specifies the password that must be supplied for a Director.
610         '';
611       };
613       extraMessagesConfig = mkOption {
614         default = "";
615         type = types.lines;
616         description = ''
617           Extra configuration to be passed in Messages directive.
618         '';
619         example = ''
620           console = all
621         '';
622       };
624       extraDirectorConfig = mkOption {
625         default = "";
626         type = types.lines;
627         description = ''
628           Extra configuration to be passed in Director directive.
629         '';
630         example = ''
631           Maximum Concurrent Jobs = 20;
632           Heartbeat Interval = 30;
633         '';
634       };
636       extraConfig = mkOption {
637         default = "";
638         type = types.lines;
639         description = ''
640           Extra configuration for Bacula Director Daemon.
641         '';
642         example = ''
643           TODO
644         '';
645       };
647       tls = mkOption {
648         type = types.submodule (tlsOptions "services.bacula-dir");
649         default = { };
650         description = ''
651           TLS Options for the Director.
652           Important notice: The backup won't be encrypted.
653         '';
654        };
655     };
656   };
658   config = mkIf (fd_cfg.enable || sd_cfg.enable || dir_cfg.enable) {
659     systemd.slices.system-bacula = {
660       description = "Bacula Backup System Slice";
661       documentation = [ "man:bacula(8)" "https://www.bacula.org/" ];
662     };
664     systemd.services.bacula-fd = mkIf fd_cfg.enable {
665       after = [ "network.target" ];
666       description = "Bacula File Daemon";
667       wantedBy = [ "multi-user.target" ];
668       path = [ pkgs.bacula ];
669       serviceConfig = {
670         ExecStart = "${pkgs.bacula}/sbin/bacula-fd -f -u root -g bacula -c ${fd_conf}";
671         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
672         LogsDirectory = "bacula";
673         StateDirectory = "bacula";
674         Slice = "system-bacula.slice";
675       };
676     };
678     systemd.services.bacula-sd = mkIf sd_cfg.enable {
679       after = [ "network.target" ];
680       description = "Bacula Storage Daemon";
681       wantedBy = [ "multi-user.target" ];
682       path = [ pkgs.bacula ];
683       serviceConfig = {
684         ExecStart = "${pkgs.bacula}/sbin/bacula-sd -f -u bacula -g bacula -c ${sd_conf}";
685         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
686         LogsDirectory = "bacula";
687         StateDirectory = "bacula";
688         Slice = "system-bacula.slice";
689       };
690     };
692     services.postgresql.enable = lib.mkIf dir_cfg.enable true;
694     systemd.services.bacula-dir = mkIf dir_cfg.enable {
695       after = [ "network.target" "postgresql.service" ];
696       description = "Bacula Director Daemon";
697       wantedBy = [ "multi-user.target" ];
698       path = [ pkgs.bacula ];
699       serviceConfig = {
700         ExecStart = "${pkgs.bacula}/sbin/bacula-dir -f -u bacula -g bacula -c ${dir_conf}";
701         ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
702         LogsDirectory = "bacula";
703         StateDirectory = "bacula";
704         Slice = "system-bacula.slice";
705       };
706       preStart = ''
707         if ! test -e "${libDir}/db-created"; then
708             ${pkgs.postgresql}/bin/createuser --no-superuser --no-createdb --no-createrole bacula
709             #${pkgs.postgresql}/bin/createdb --owner bacula bacula
711             # populate DB
712             ${pkgs.bacula}/etc/create_bacula_database postgresql
713             ${pkgs.bacula}/etc/make_bacula_tables postgresql
714             ${pkgs.bacula}/etc/grant_bacula_privileges postgresql
715             touch "${libDir}/db-created"
716         else
717             ${pkgs.bacula}/etc/update_bacula_tables postgresql || true
718         fi
719       '';
720     };
722     environment.systemPackages = [ pkgs.bacula ];
724     users.users.bacula = {
725       group = "bacula";
726       uid = config.ids.uids.bacula;
727       home = "${libDir}";
728       createHome = true;
729       description = "Bacula Daemons user";
730       shell = "${pkgs.bash}/bin/bash";
731     };
733     users.groups.bacula.gid = config.ids.gids.bacula;
734   };