at 22.05-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 = '' 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 = '' 139 If Monitor is set to <literal>no</literal>, this director will have 140 full access to this Storage daemon. If Monitor is set to 141 <literal>yes</literal>, 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 = '' 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 <literal>/dev/nst0</literal>, you would specify 165 <literal>/dev/sg0</literal> 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 = '' 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 <literal>"/path/mtx-changer %c %o %S %a %d"</literal> 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 = ""; 199 type = types.listOf types.str; 200 }; 201 202 extraAutochangerConfig = mkOption { 203 default = ""; 204 type = types.lines; 205 description = '' 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 = '' 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 <literal>/dev/nst0</literal> or 227 <literal>/dev/rmt/0mbn</literal>. For a DVD-writer, it will be for 228 example <literal>/dev/hdc</literal>. 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 = '' 240 The specified name-string names the type of media supported by this 241 device, for example, <literal>DLT7000</literal>. 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 <literal>DDS-4</literal> 259 then during the restore, Bacula will be able to choose any Storage 260 Daemon that handles <literal>DDS-4</literal>. 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 = '' 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 = '' 299 Whether to enable the Bacula File Daemon. 300 ''; 301 }; 302 303 name = mkOption { 304 default = "${config.networking.hostName}-fd"; 305 type = types.str; 306 description = '' 307 The client name that must be used by the Director when connecting. 308 Generally, it is a good idea to use a name related to the machine so 309 that error messages can be easily identified if you have multiple 310 Clients. This directive is required. 311 ''; 312 }; 313 314 port = mkOption { 315 default = 9102; 316 type = types.int; 317 description = '' 318 This specifies the port number on which the Client listens for 319 Director connections. It must agree with the FDPort specified in 320 the Client resource of the Director's configuration file. 321 ''; 322 }; 323 324 director = mkOption { 325 default = {}; 326 description = '' 327 This option defines director resources in Bacula File Daemon. 328 ''; 329 type = with types; attrsOf (submodule directorOptions); 330 }; 331 332 extraClientConfig = mkOption { 333 default = ""; 334 type = types.lines; 335 description = '' 336 Extra configuration to be passed in Client directive. 337 ''; 338 example = '' 339 Maximum Concurrent Jobs = 20; 340 Heartbeat Interval = 30; 341 ''; 342 }; 343 344 extraMessagesConfig = mkOption { 345 default = ""; 346 type = types.lines; 347 description = '' 348 Extra configuration to be passed in Messages directive. 349 ''; 350 example = '' 351 console = all 352 ''; 353 }; 354 }; 355 356 services.bacula-sd = { 357 enable = mkOption { 358 type = types.bool; 359 default = false; 360 description = '' 361 Whether to enable Bacula Storage Daemon. 362 ''; 363 }; 364 365 name = mkOption { 366 default = "${config.networking.hostName}-sd"; 367 type = types.str; 368 description = '' 369 Specifies the Name of the Storage daemon. 370 ''; 371 }; 372 373 port = mkOption { 374 default = 9103; 375 type = types.int; 376 description = '' 377 Specifies port number on which the Storage daemon listens for 378 Director connections. 379 ''; 380 }; 381 382 director = mkOption { 383 default = {}; 384 description = '' 385 This option defines Director resources in Bacula Storage Daemon. 386 ''; 387 type = with types; attrsOf (submodule directorOptions); 388 }; 389 390 device = mkOption { 391 default = {}; 392 description = '' 393 This option defines Device resources in Bacula Storage Daemon. 394 ''; 395 type = with types; attrsOf (submodule deviceOptions); 396 }; 397 398 autochanger = mkOption { 399 default = {}; 400 description = '' 401 This option defines Autochanger resources in Bacula Storage Daemon. 402 ''; 403 type = with types; attrsOf (submodule autochangerOptions); 404 }; 405 406 extraStorageConfig = mkOption { 407 default = ""; 408 type = types.lines; 409 description = '' 410 Extra configuration to be passed in Storage directive. 411 ''; 412 example = '' 413 Maximum Concurrent Jobs = 20; 414 Heartbeat Interval = 30; 415 ''; 416 }; 417 418 extraMessagesConfig = mkOption { 419 default = ""; 420 type = types.lines; 421 description = '' 422 Extra configuration to be passed in Messages directive. 423 ''; 424 example = '' 425 console = all 426 ''; 427 }; 428 429 }; 430 431 services.bacula-dir = { 432 enable = mkOption { 433 type = types.bool; 434 default = false; 435 description = '' 436 Whether to enable Bacula Director Daemon. 437 ''; 438 }; 439 440 name = mkOption { 441 default = "${config.networking.hostName}-dir"; 442 type = types.str; 443 description = '' 444 The director name used by the system administrator. This directive is 445 required. 446 ''; 447 }; 448 449 port = mkOption { 450 default = 9101; 451 type = types.int; 452 description = '' 453 Specify the port (a positive integer) on which the Director daemon 454 will listen for Bacula Console connections. This same port number 455 must be specified in the Director resource of the Console 456 configuration file. The default is 9101, so normally this directive 457 need not be specified. This directive should not be used if you 458 specify DirAddresses (N.B plural) directive. 459 ''; 460 }; 461 462 password = mkOption { 463 # TODO: required? 464 type = types.str; 465 description = '' 466 Specifies the password that must be supplied for a Director. 467 ''; 468 }; 469 470 extraMessagesConfig = mkOption { 471 default = ""; 472 type = types.lines; 473 description = '' 474 Extra configuration to be passed in Messages directive. 475 ''; 476 example = '' 477 console = all 478 ''; 479 }; 480 481 extraDirectorConfig = mkOption { 482 default = ""; 483 type = types.lines; 484 description = '' 485 Extra configuration to be passed in Director directive. 486 ''; 487 example = '' 488 Maximum Concurrent Jobs = 20; 489 Heartbeat Interval = 30; 490 ''; 491 }; 492 493 extraConfig = mkOption { 494 default = ""; 495 type = types.lines; 496 description = '' 497 Extra configuration for Bacula Director Daemon. 498 ''; 499 example = '' 500 TODO 501 ''; 502 }; 503 }; 504 }; 505 506 config = mkIf (fd_cfg.enable || sd_cfg.enable || dir_cfg.enable) { 507 systemd.services.bacula-fd = mkIf fd_cfg.enable { 508 after = [ "network.target" ]; 509 description = "Bacula File Daemon"; 510 wantedBy = [ "multi-user.target" ]; 511 path = [ pkgs.bacula ]; 512 serviceConfig = { 513 ExecStart = "${pkgs.bacula}/sbin/bacula-fd -f -u root -g bacula -c ${fd_conf}"; 514 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 515 LogsDirectory = "bacula"; 516 StateDirectory = "bacula"; 517 }; 518 }; 519 520 systemd.services.bacula-sd = mkIf sd_cfg.enable { 521 after = [ "network.target" ]; 522 description = "Bacula Storage Daemon"; 523 wantedBy = [ "multi-user.target" ]; 524 path = [ pkgs.bacula ]; 525 serviceConfig = { 526 ExecStart = "${pkgs.bacula}/sbin/bacula-sd -f -u bacula -g bacula -c ${sd_conf}"; 527 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 528 LogsDirectory = "bacula"; 529 StateDirectory = "bacula"; 530 }; 531 }; 532 533 services.postgresql.enable = dir_cfg.enable == true; 534 535 systemd.services.bacula-dir = mkIf dir_cfg.enable { 536 after = [ "network.target" "postgresql.service" ]; 537 description = "Bacula Director Daemon"; 538 wantedBy = [ "multi-user.target" ]; 539 path = [ pkgs.bacula ]; 540 serviceConfig = { 541 ExecStart = "${pkgs.bacula}/sbin/bacula-dir -f -u bacula -g bacula -c ${dir_conf}"; 542 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 543 LogsDirectory = "bacula"; 544 StateDirectory = "bacula"; 545 }; 546 preStart = '' 547 if ! test -e "${libDir}/db-created"; then 548 ${pkgs.postgresql}/bin/createuser --no-superuser --no-createdb --no-createrole bacula 549 #${pkgs.postgresql}/bin/createdb --owner bacula bacula 550 551 # populate DB 552 ${pkgs.bacula}/etc/create_bacula_database postgresql 553 ${pkgs.bacula}/etc/make_bacula_tables postgresql 554 ${pkgs.bacula}/etc/grant_bacula_privileges postgresql 555 touch "${libDir}/db-created" 556 else 557 ${pkgs.bacula}/etc/update_bacula_tables postgresql || true 558 fi 559 ''; 560 }; 561 562 environment.systemPackages = [ pkgs.bacula ]; 563 564 users.users.bacula = { 565 group = "bacula"; 566 uid = config.ids.uids.bacula; 567 home = "${libDir}"; 568 createHome = true; 569 description = "Bacula Daemons user"; 570 shell = "${pkgs.bash}/bin/bash"; 571 }; 572 573 users.groups.bacula.gid = config.ids.gids.bacula; 574 }; 575}