1{ config, lib, pkgs, ... }:
2
3let
4 inherit (lib) mkEnableOption mkIf mkOption optionalString types;
5
6 generic = variant:
7 let
8 cfg = config.services.${variant};
9 pkg = pkgs.${variant};
10 birdBin = if variant == "bird6" then "bird6" else "bird";
11 birdc = if variant == "bird6" then "birdc6" else "birdc";
12 descr =
13 { bird = "1.9.x with IPv4 suport";
14 bird6 = "1.9.x with IPv6 suport";
15 bird2 = "2.x";
16 }.${variant};
17 in {
18 ###### interface
19 options = {
20 services.${variant} = {
21 enable = mkEnableOption "BIRD Internet Routing Daemon (${descr})";
22 config = mkOption {
23 type = types.lines;
24 description = ''
25 BIRD Internet Routing Daemon configuration file.
26 <link xlink:href='http://bird.network.cz/'/>
27 '';
28 };
29 checkConfig = mkOption {
30 type = types.bool;
31 default = true;
32 description = ''
33 Whether the config should be checked at build time.
34 Disabling this might become necessary if the config includes files not present during build time.
35 '';
36 };
37 };
38 };
39
40 ###### implementation
41 config = mkIf cfg.enable {
42 environment.systemPackages = [ pkg ];
43
44 environment.etc."bird/${variant}.conf".source = pkgs.writeTextFile {
45 name = "${variant}.conf";
46 text = cfg.config;
47 checkPhase = optionalString cfg.checkConfig ''
48 ${pkg}/bin/${birdBin} -d -p -c $out
49 '';
50 };
51
52 systemd.services.${variant} = {
53 description = "BIRD Internet Routing Daemon (${descr})";
54 wantedBy = [ "multi-user.target" ];
55 reloadIfChanged = true;
56 restartTriggers = [ config.environment.etc."bird/${variant}.conf".source ];
57 serviceConfig = {
58 Type = "forking";
59 Restart = "on-failure";
60 ExecStart = "${pkg}/bin/${birdBin} -c /etc/bird/${variant}.conf -u ${variant} -g ${variant}";
61 ExecReload = "/bin/sh -c '${pkg}/bin/${birdBin} -c /etc/bird/${variant}.conf -p && ${pkg}/bin/${birdc} configure'";
62 ExecStop = "${pkg}/bin/${birdc} down";
63 CapabilityBoundingSet = [ "CAP_CHOWN" "CAP_FOWNER" "CAP_DAC_OVERRIDE" "CAP_SETUID" "CAP_SETGID"
64 # see bird/sysdep/linux/syspriv.h
65 "CAP_NET_BIND_SERVICE" "CAP_NET_BROADCAST" "CAP_NET_ADMIN" "CAP_NET_RAW" ];
66 ProtectSystem = "full";
67 ProtectHome = "yes";
68 SystemCallFilter="~@cpu-emulation @debug @keyring @module @mount @obsolete @raw-io";
69 MemoryDenyWriteExecute = "yes";
70 };
71 };
72 users = {
73 users.${variant} = {
74 description = "BIRD Internet Routing Daemon user";
75 group = variant;
76 isSystemUser = true;
77 };
78 groups.${variant} = {};
79 };
80 };
81 };
82
83in
84
85{
86 imports = map generic [ "bird" "bird6" "bird2" ];
87}