at 23.11-pre 19 kB view raw
1{ config, lib, pkgs, ... }: 2 3 4# TODO: test configuration when building nixexpr (use -t parameter) 5# TODO: support sqlite3 (it's deprecate?) and mysql 6 7with lib; 8 9let 10 libDir = "/var/lib/bacula"; 11 12 fd_cfg = config.services.bacula-fd; 13 fd_conf = pkgs.writeText "bacula-fd.conf" 14 '' 15 Client { 16 Name = "${fd_cfg.name}"; 17 FDPort = ${toString fd_cfg.port}; 18 WorkingDirectory = "${libDir}"; 19 Pid Directory = "/run"; 20 ${fd_cfg.extraClientConfig} 21 } 22 23 ${concatStringsSep "\n" (mapAttrsToList (name: value: '' 24 Director { 25 Name = "${name}"; 26 Password = "${value.password}"; 27 Monitor = "${value.monitor}"; 28 } 29 '') fd_cfg.director)} 30 31 Messages { 32 Name = Standard; 33 syslog = all, !skipped, !restored 34 ${fd_cfg.extraMessagesConfig} 35 } 36 ''; 37 38 sd_cfg = config.services.bacula-sd; 39 sd_conf = pkgs.writeText "bacula-sd.conf" 40 '' 41 Storage { 42 Name = "${sd_cfg.name}"; 43 SDPort = ${toString sd_cfg.port}; 44 WorkingDirectory = "${libDir}"; 45 Pid Directory = "/run"; 46 ${sd_cfg.extraStorageConfig} 47 } 48 49 ${concatStringsSep "\n" (mapAttrsToList (name: value: '' 50 Autochanger { 51 Name = "${name}"; 52 Device = ${concatStringsSep ", " (map (a: "\"${a}\"") value.devices)}; 53 Changer Device = "${value.changerDevice}"; 54 Changer Command = "${value.changerCommand}"; 55 ${value.extraAutochangerConfig} 56 } 57 '') sd_cfg.autochanger)} 58 59 ${concatStringsSep "\n" (mapAttrsToList (name: value: '' 60 Device { 61 Name = "${name}"; 62 Archive Device = "${value.archiveDevice}"; 63 Media Type = "${value.mediaType}"; 64 ${value.extraDeviceConfig} 65 } 66 '') sd_cfg.device)} 67 68 ${concatStringsSep "\n" (mapAttrsToList (name: value: '' 69 Director { 70 Name = "${name}"; 71 Password = "${value.password}"; 72 Monitor = "${value.monitor}"; 73 } 74 '') sd_cfg.director)} 75 76 Messages { 77 Name = Standard; 78 syslog = all, !skipped, !restored 79 ${sd_cfg.extraMessagesConfig} 80 } 81 ''; 82 83 dir_cfg = config.services.bacula-dir; 84 dir_conf = pkgs.writeText "bacula-dir.conf" 85 '' 86 Director { 87 Name = "${dir_cfg.name}"; 88 Password = "${dir_cfg.password}"; 89 DirPort = ${toString dir_cfg.port}; 90 Working Directory = "${libDir}"; 91 Pid Directory = "/run/"; 92 QueryFile = "${pkgs.bacula}/etc/query.sql"; 93 ${dir_cfg.extraDirectorConfig} 94 } 95 96 Catalog { 97 Name = "PostgreSQL"; 98 dbname = "bacula"; 99 user = "bacula"; 100 } 101 102 Messages { 103 Name = Standard; 104 syslog = all, !skipped, !restored 105 ${dir_cfg.extraMessagesConfig} 106 } 107 108 ${dir_cfg.extraConfig} 109 ''; 110 111 directorOptions = {...}: 112 { 113 options = { 114 password = mkOption { 115 type = types.str; 116 # TODO: required? 117 description = lib.mdDoc '' 118 Specifies the password that must be supplied for the default Bacula 119 Console to be authorized. The same password must appear in the 120 Director resource of the Console configuration file. For added 121 security, the password is never passed across the network but instead 122 a challenge response hash code created with the password. This 123 directive is required. If you have either /dev/random or bc on your 124 machine, Bacula will generate a random password during the 125 configuration process, otherwise it will be left blank and you must 126 manually supply it. 127 128 The password is plain text. It is not generated through any special 129 process but as noted above, it is better to use random text for 130 security reasons. 131 ''; 132 }; 133 134 monitor = mkOption { 135 type = types.enum [ "no" "yes" ]; 136 default = "no"; 137 example = "yes"; 138 description = lib.mdDoc '' 139 If Monitor is set to `no`, this director will have 140 full access to this Storage daemon. If Monitor is set to 141 `yes`, this director will only be able to fetch the 142 current status of this Storage daemon. 143 144 Please note that if this director is being used by a Monitor, we 145 highly recommend to set this directive to yes to avoid serious 146 security problems. 147 ''; 148 }; 149 }; 150 }; 151 152 autochangerOptions = {...}: 153 { 154 options = { 155 changerDevice = mkOption { 156 type = types.str; 157 description = lib.mdDoc '' 158 The specified name-string must be the generic SCSI device name of the 159 autochanger that corresponds to the normal read/write Archive Device 160 specified in the Device resource. This generic SCSI device name 161 should be specified if you have an autochanger or if you have a 162 standard tape drive and want to use the Alert Command (see below). 163 For example, on Linux systems, for an Archive Device name of 164 `/dev/nst0`, you would specify 165 `/dev/sg0` for the Changer Device name. Depending 166 on your exact configuration, and the number of autochangers or the 167 type of autochanger, what you specify here can vary. This directive 168 is optional. See the Using AutochangersAutochangersChapter chapter of 169 this manual for more details of using this and the following 170 autochanger directives. 171 ''; 172 }; 173 174 changerCommand = mkOption { 175 type = types.str; 176 description = lib.mdDoc '' 177 The name-string specifies an external program to be called that will 178 automatically change volumes as required by Bacula. Normally, this 179 directive will be specified only in the AutoChanger resource, which 180 is then used for all devices. However, you may also specify the 181 different Changer Command in each Device resource. Most frequently, 182 you will specify the Bacula supplied mtx-changer script as follows: 183 184 `"/path/mtx-changer %c %o %S %a %d"` 185 186 and you will install the mtx on your system (found in the depkgs 187 release). An example of this command is in the default bacula-sd.conf 188 file. For more details on the substitution characters that may be 189 specified to configure your autochanger please see the 190 AutochangersAutochangersChapter chapter of this manual. For FreeBSD 191 users, you might want to see one of the several chio scripts in 192 examples/autochangers. 193 ''; 194 default = "/etc/bacula/mtx-changer %c %o %S %a %d"; 195 }; 196 197 devices = mkOption { 198 description = lib.mdDoc ""; 199 type = types.listOf types.str; 200 }; 201 202 extraAutochangerConfig = mkOption { 203 default = ""; 204 type = types.lines; 205 description = lib.mdDoc '' 206 Extra configuration to be passed in Autochanger directive. 207 ''; 208 example = '' 209 210 ''; 211 }; 212 }; 213 }; 214 215 216 deviceOptions = {...}: 217 { 218 options = { 219 archiveDevice = mkOption { 220 # TODO: required? 221 type = types.str; 222 description = lib.mdDoc '' 223 The specified name-string gives the system file name of the storage 224 device managed by this storage daemon. This will usually be the 225 device file name of a removable storage device (tape drive), for 226 example `/dev/nst0` or 227 `/dev/rmt/0mbn`. For a DVD-writer, it will be for 228 example `/dev/hdc`. It may also be a directory name 229 if you are archiving to disk storage. In this case, you must supply 230 the full absolute path to the directory. When specifying a tape 231 device, it is preferable that the "non-rewind" variant of the device 232 file name be given. 233 ''; 234 }; 235 236 mediaType = mkOption { 237 # TODO: required? 238 type = types.str; 239 description = lib.mdDoc '' 240 The specified name-string names the type of media supported by this 241 device, for example, `DLT7000`. Media type names are 242 arbitrary in that you set them to anything you want, but they must be 243 known to the volume database to keep track of which storage daemons 244 can read which volumes. In general, each different storage type 245 should have a unique Media Type associated with it. The same 246 name-string must appear in the appropriate Storage resource 247 definition in the Director's configuration file. 248 249 Even though the names you assign are arbitrary (i.e. you choose the 250 name you want), you should take care in specifying them because the 251 Media Type is used to determine which storage device Bacula will 252 select during restore. Thus you should probably use the same Media 253 Type specification for all drives where the Media can be freely 254 interchanged. This is not generally an issue if you have a single 255 Storage daemon, but it is with multiple Storage daemons, especially 256 if they have incompatible media. 257 258 For example, if you specify a Media Type of `DDS-4` 259 then during the restore, Bacula will be able to choose any Storage 260 Daemon that handles `DDS-4`. If you have an 261 autochanger, you might want to name the Media Type in a way that is 262 unique to the autochanger, unless you wish to possibly use the 263 Volumes in other drives. You should also ensure to have unique Media 264 Type names if the Media is not compatible between drives. This 265 specification is required for all devices. 266 267 In addition, if you are using disk storage, each Device resource will 268 generally have a different mount point or directory. In order for 269 Bacula to select the correct Device resource, each one must have a 270 unique Media Type. 271 ''; 272 }; 273 274 extraDeviceConfig = mkOption { 275 default = ""; 276 type = types.lines; 277 description = lib.mdDoc '' 278 Extra configuration to be passed in Device directive. 279 ''; 280 example = '' 281 LabelMedia = yes 282 Random Access = no 283 AutomaticMount = no 284 RemovableMedia = no 285 MaximumOpenWait = 60 286 AlwaysOpen = no 287 ''; 288 }; 289 }; 290 }; 291 292in { 293 options = { 294 services.bacula-fd = { 295 enable = mkOption { 296 type = types.bool; 297 default = false; 298 description = lib.mdDoc '' 299 Whether to enable the Bacula File Daemon. 300 ''; 301 }; 302 303 name = mkOption { 304 default = "${config.networking.hostName}-fd"; 305 defaultText = literalExpression ''"''${config.networking.hostName}-fd"''; 306 type = types.str; 307 description = lib.mdDoc '' 308 The client name that must be used by the Director when connecting. 309 Generally, it is a good idea to use a name related to the machine so 310 that error messages can be easily identified if you have multiple 311 Clients. This directive is required. 312 ''; 313 }; 314 315 port = mkOption { 316 default = 9102; 317 type = types.port; 318 description = lib.mdDoc '' 319 This specifies the port number on which the Client listens for 320 Director connections. It must agree with the FDPort specified in 321 the Client resource of the Director's configuration file. 322 ''; 323 }; 324 325 director = mkOption { 326 default = {}; 327 description = lib.mdDoc '' 328 This option defines director resources in Bacula File Daemon. 329 ''; 330 type = with types; attrsOf (submodule directorOptions); 331 }; 332 333 extraClientConfig = mkOption { 334 default = ""; 335 type = types.lines; 336 description = lib.mdDoc '' 337 Extra configuration to be passed in Client directive. 338 ''; 339 example = '' 340 Maximum Concurrent Jobs = 20; 341 Heartbeat Interval = 30; 342 ''; 343 }; 344 345 extraMessagesConfig = mkOption { 346 default = ""; 347 type = types.lines; 348 description = lib.mdDoc '' 349 Extra configuration to be passed in Messages directive. 350 ''; 351 example = '' 352 console = all 353 ''; 354 }; 355 }; 356 357 services.bacula-sd = { 358 enable = mkOption { 359 type = types.bool; 360 default = false; 361 description = lib.mdDoc '' 362 Whether to enable Bacula Storage Daemon. 363 ''; 364 }; 365 366 name = mkOption { 367 default = "${config.networking.hostName}-sd"; 368 defaultText = literalExpression ''"''${config.networking.hostName}-sd"''; 369 type = types.str; 370 description = lib.mdDoc '' 371 Specifies the Name of the Storage daemon. 372 ''; 373 }; 374 375 port = mkOption { 376 default = 9103; 377 type = types.port; 378 description = lib.mdDoc '' 379 Specifies port number on which the Storage daemon listens for 380 Director connections. 381 ''; 382 }; 383 384 director = mkOption { 385 default = {}; 386 description = lib.mdDoc '' 387 This option defines Director resources in Bacula Storage Daemon. 388 ''; 389 type = with types; attrsOf (submodule directorOptions); 390 }; 391 392 device = mkOption { 393 default = {}; 394 description = lib.mdDoc '' 395 This option defines Device resources in Bacula Storage Daemon. 396 ''; 397 type = with types; attrsOf (submodule deviceOptions); 398 }; 399 400 autochanger = mkOption { 401 default = {}; 402 description = lib.mdDoc '' 403 This option defines Autochanger resources in Bacula Storage Daemon. 404 ''; 405 type = with types; attrsOf (submodule autochangerOptions); 406 }; 407 408 extraStorageConfig = mkOption { 409 default = ""; 410 type = types.lines; 411 description = lib.mdDoc '' 412 Extra configuration to be passed in Storage directive. 413 ''; 414 example = '' 415 Maximum Concurrent Jobs = 20; 416 Heartbeat Interval = 30; 417 ''; 418 }; 419 420 extraMessagesConfig = mkOption { 421 default = ""; 422 type = types.lines; 423 description = lib.mdDoc '' 424 Extra configuration to be passed in Messages directive. 425 ''; 426 example = '' 427 console = all 428 ''; 429 }; 430 431 }; 432 433 services.bacula-dir = { 434 enable = mkOption { 435 type = types.bool; 436 default = false; 437 description = lib.mdDoc '' 438 Whether to enable Bacula Director Daemon. 439 ''; 440 }; 441 442 name = mkOption { 443 default = "${config.networking.hostName}-dir"; 444 defaultText = literalExpression ''"''${config.networking.hostName}-dir"''; 445 type = types.str; 446 description = lib.mdDoc '' 447 The director name used by the system administrator. This directive is 448 required. 449 ''; 450 }; 451 452 port = mkOption { 453 default = 9101; 454 type = types.port; 455 description = lib.mdDoc '' 456 Specify the port (a positive integer) on which the Director daemon 457 will listen for Bacula Console connections. This same port number 458 must be specified in the Director resource of the Console 459 configuration file. The default is 9101, so normally this directive 460 need not be specified. This directive should not be used if you 461 specify DirAddresses (N.B plural) directive. 462 ''; 463 }; 464 465 password = mkOption { 466 # TODO: required? 467 type = types.str; 468 description = lib.mdDoc '' 469 Specifies the password that must be supplied for a Director. 470 ''; 471 }; 472 473 extraMessagesConfig = mkOption { 474 default = ""; 475 type = types.lines; 476 description = lib.mdDoc '' 477 Extra configuration to be passed in Messages directive. 478 ''; 479 example = '' 480 console = all 481 ''; 482 }; 483 484 extraDirectorConfig = mkOption { 485 default = ""; 486 type = types.lines; 487 description = lib.mdDoc '' 488 Extra configuration to be passed in Director directive. 489 ''; 490 example = '' 491 Maximum Concurrent Jobs = 20; 492 Heartbeat Interval = 30; 493 ''; 494 }; 495 496 extraConfig = mkOption { 497 default = ""; 498 type = types.lines; 499 description = lib.mdDoc '' 500 Extra configuration for Bacula Director Daemon. 501 ''; 502 example = '' 503 TODO 504 ''; 505 }; 506 }; 507 }; 508 509 config = mkIf (fd_cfg.enable || sd_cfg.enable || dir_cfg.enable) { 510 systemd.services.bacula-fd = mkIf fd_cfg.enable { 511 after = [ "network.target" ]; 512 description = "Bacula File Daemon"; 513 wantedBy = [ "multi-user.target" ]; 514 path = [ pkgs.bacula ]; 515 serviceConfig = { 516 ExecStart = "${pkgs.bacula}/sbin/bacula-fd -f -u root -g bacula -c ${fd_conf}"; 517 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 518 LogsDirectory = "bacula"; 519 StateDirectory = "bacula"; 520 }; 521 }; 522 523 systemd.services.bacula-sd = mkIf sd_cfg.enable { 524 after = [ "network.target" ]; 525 description = "Bacula Storage Daemon"; 526 wantedBy = [ "multi-user.target" ]; 527 path = [ pkgs.bacula ]; 528 serviceConfig = { 529 ExecStart = "${pkgs.bacula}/sbin/bacula-sd -f -u bacula -g bacula -c ${sd_conf}"; 530 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 531 LogsDirectory = "bacula"; 532 StateDirectory = "bacula"; 533 }; 534 }; 535 536 services.postgresql.enable = dir_cfg.enable == true; 537 538 systemd.services.bacula-dir = mkIf dir_cfg.enable { 539 after = [ "network.target" "postgresql.service" ]; 540 description = "Bacula Director Daemon"; 541 wantedBy = [ "multi-user.target" ]; 542 path = [ pkgs.bacula ]; 543 serviceConfig = { 544 ExecStart = "${pkgs.bacula}/sbin/bacula-dir -f -u bacula -g bacula -c ${dir_conf}"; 545 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 546 LogsDirectory = "bacula"; 547 StateDirectory = "bacula"; 548 }; 549 preStart = '' 550 if ! test -e "${libDir}/db-created"; then 551 ${pkgs.postgresql}/bin/createuser --no-superuser --no-createdb --no-createrole bacula 552 #${pkgs.postgresql}/bin/createdb --owner bacula bacula 553 554 # populate DB 555 ${pkgs.bacula}/etc/create_bacula_database postgresql 556 ${pkgs.bacula}/etc/make_bacula_tables postgresql 557 ${pkgs.bacula}/etc/grant_bacula_privileges postgresql 558 touch "${libDir}/db-created" 559 else 560 ${pkgs.bacula}/etc/update_bacula_tables postgresql || true 561 fi 562 ''; 563 }; 564 565 environment.systemPackages = [ pkgs.bacula ]; 566 567 users.users.bacula = { 568 group = "bacula"; 569 uid = config.ids.uids.bacula; 570 home = "${libDir}"; 571 createHome = true; 572 description = "Bacula Daemons user"; 573 shell = "${pkgs.bash}/bin/bash"; 574 }; 575 576 users.groups.bacula.gid = config.ids.gids.bacula; 577 }; 578}