at 25.11-pre 8.2 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8let 9 10 cfg = config.services.frr; 11 12 daemons = [ 13 "bgpd" 14 "ospfd" 15 "ospf6d" 16 "ripd" 17 "ripngd" 18 "isisd" 19 "pimd" 20 "pim6d" 21 "ldpd" 22 "nhrpd" 23 "eigrpd" 24 "babeld" 25 "sharpd" 26 "pbrd" 27 "bfdd" 28 "fabricd" 29 "vrrpd" 30 "pathd" 31 ]; 32 33 daemonDefaultOptions = { 34 zebra = "-A 127.0.0.1 -s 90000000"; 35 mgmtd = "-A 127.0.0.1"; 36 bgpd = "-A 127.0.0.1"; 37 ospfd = "-A 127.0.0.1"; 38 ospf6d = "-A ::1"; 39 ripd = "-A 127.0.0.1"; 40 ripngd = "-A ::1"; 41 isisd = "-A 127.0.0.1"; 42 pimd = "-A 127.0.0.1"; 43 pim6d = "-A ::1"; 44 ldpd = "-A 127.0.0.1"; 45 nhrpd = "-A 127.0.0.1"; 46 eigrpd = "-A 127.0.0.1"; 47 babeld = "-A 127.0.0.1"; 48 sharpd = "-A 127.0.0.1"; 49 pbrd = "-A 127.0.0.1"; 50 staticd = "-A 127.0.0.1"; 51 bfdd = "-A 127.0.0.1"; 52 fabricd = "-A 127.0.0.1"; 53 vrrpd = "-A 127.0.0.1"; 54 pathd = "-A 127.0.0.1"; 55 }; 56 57 renamedServices = [ 58 "bgp" 59 "ospf" 60 "ospf6" 61 "rip" 62 "ripng" 63 "isis" 64 "pim" 65 "ldp" 66 "nhrp" 67 "eigrp" 68 "babel" 69 "sharp" 70 "pbr" 71 "bfd" 72 "fabric" 73 ]; 74 75 obsoleteServices = renamedServices ++ [ 76 "static" 77 "mgmt" 78 "zebra" 79 ]; 80 81 allDaemons = builtins.attrNames daemonDefaultOptions; 82 83 isEnabled = service: cfg.${service}.enable; 84 85 daemonLine = d: "${d}=${if isEnabled d then "yes" else "no"}"; 86 87 configFile = 88 if cfg.configFile != null then 89 cfg.configFile 90 else 91 pkgs.writeText "frr.conf" '' 92 ! FRR configuration 93 ! 94 hostname ${config.networking.hostName} 95 log syslog 96 service password-encryption 97 service integrated-vtysh-config 98 ! 99 ${cfg.config} 100 ! 101 end 102 ''; 103 104 serviceOptions = 105 service: 106 { 107 options = lib.mkOption { 108 type = lib.types.listOf lib.types.str; 109 default = [ daemonDefaultOptions.${service} ]; 110 description = '' 111 Options for the FRR ${service} daemon. 112 ''; 113 }; 114 extraOptions = lib.mkOption { 115 type = lib.types.listOf lib.types.str; 116 default = [ ]; 117 description = '' 118 Extra options to be appended to the FRR ${service} daemon options. 119 ''; 120 }; 121 } 122 // ( 123 if (builtins.elem service daemons) then { enable = lib.mkEnableOption "FRR ${service}"; } else { } 124 ); 125 126in 127 128{ 129 130 ###### interface 131 imports = 132 [ 133 { 134 options.services.frr = { 135 configFile = lib.mkOption { 136 type = lib.types.nullOr lib.types.path; 137 default = null; 138 example = "/etc/frr/frr.conf"; 139 description = '' 140 Configuration file to use for FRR. 141 By default the NixOS generated files are used. 142 ''; 143 }; 144 config = lib.mkOption { 145 type = lib.types.lines; 146 default = ""; 147 example = '' 148 router rip 149 network 10.0.0.0/8 150 router ospf 151 network 10.0.0.0/8 area 0 152 router bgp 65001 153 neighbor 10.0.0.1 remote-as 65001 154 ''; 155 description = '' 156 FRR configuration statements. 157 ''; 158 }; 159 openFilesLimit = lib.mkOption { 160 type = lib.types.ints.unsigned; 161 default = 1024; 162 description = '' 163 This is the maximum number of FD's that will be available. Use a 164 reasonable value for your setup if you are expecting a large number 165 of peers in say BGP. 166 ''; 167 }; 168 }; 169 } 170 { options.services.frr = (lib.genAttrs allDaemons serviceOptions); } 171 (lib.mkRemovedOptionModule [ "services" "frr" "zebra" "enable" ] "FRR zebra is always enabled") 172 ] 173 ++ (map ( 174 d: lib.mkRenamedOptionModule [ "services" "frr" d "enable" ] [ "services" "frr" "${d}d" "enable" ] 175 ) renamedServices) 176 ++ (map 177 ( 178 d: 179 lib.mkRenamedOptionModule 180 [ "services" "frr" d "extraOptions" ] 181 [ "services" "frr" "${d}d" "extraOptions" ] 182 ) 183 ( 184 renamedServices 185 ++ [ 186 "static" 187 "mgmt" 188 ] 189 ) 190 ) 191 ++ (map (d: lib.mkRemovedOptionModule [ "services" "frr" d "enable" ] "FRR ${d}d is always enabled") 192 [ 193 "static" 194 "mgmt" 195 ] 196 ) 197 ++ (map ( 198 d: 199 lib.mkRemovedOptionModule [ 200 "services" 201 "frr" 202 d 203 "config" 204 ] "FRR switched to integrated-vtysh-config, please use services.frr.config" 205 ) obsoleteServices) 206 ++ (map ( 207 d: 208 lib.mkRemovedOptionModule [ "services" "frr" d "configFile" ] 209 "FRR switched to integrated-vtysh-config, please use services.frr.config or services.frr.configFile" 210 ) obsoleteServices) 211 ++ (map ( 212 d: 213 lib.mkRemovedOptionModule [ 214 "services" 215 "frr" 216 d 217 "vtyListenAddress" 218 ] "Please change -A option in services.frr.${d}.options instead" 219 ) obsoleteServices) 220 ++ (map ( 221 d: 222 lib.mkRemovedOptionModule [ "services" "frr" d "vtyListenPort" ] 223 "Please use `-P «vtyListenPort»` option with services.frr.${d}.extraOptions instead, or change services.frr.${d}.options accordingly" 224 ) obsoleteServices); 225 226 ###### implementation 227 228 config = 229 let 230 daemonList = lib.concatStringsSep "\n" (map daemonLine daemons); 231 daemonOptionLine = 232 d: "${d}_options=\"${lib.concatStringsSep " " (cfg.${d}.options ++ cfg.${d}.extraOptions)}\""; 233 daemonOptions = lib.concatStringsSep "\n" (map daemonOptionLine allDaemons); 234 in 235 lib.mkIf (lib.any isEnabled daemons || cfg.configFile != null || cfg.config != "") { 236 237 environment.systemPackages = [ 238 pkgs.frr # for the vtysh tool 239 ]; 240 241 users.users.frr = { 242 description = "FRR daemon user"; 243 isSystemUser = true; 244 group = "frr"; 245 }; 246 247 users.groups = { 248 frr = { }; 249 # Members of the frrvty group can use vtysh to inspect the FRR daemons 250 frrvty = { 251 members = [ "frr" ]; 252 }; 253 }; 254 255 environment.etc = { 256 "frr/frr.conf".source = configFile; 257 "frr/vtysh.conf".text = '' 258 service integrated-vtysh-config 259 ''; 260 "frr/daemons".text = '' 261 # This file tells the frr package which daemons to start. 262 # 263 # The watchfrr, zebra and staticd daemons are always started. 264 # 265 # This part is auto-generated from services.frr.<daemon>.enable config 266 ${daemonList} 267 268 # If this option is set the /etc/init.d/frr script automatically loads 269 # the config via "vtysh -b" when the servers are started. 270 # 271 vtysh_enable=yes 272 273 # This part is auto-generated from services.frr.<daemon>.options or 274 # services.frr.<daemon>.extraOptions 275 ${daemonOptions} 276 ''; 277 }; 278 279 systemd.tmpfiles.rules = [ "d /run/frr 0755 frr frr -" ]; 280 281 systemd.services.frr = { 282 description = "FRRouting"; 283 documentation = [ "https://frrouting.readthedocs.io/en/latest/setup.html" ]; 284 wants = [ "network.target" ]; 285 after = [ 286 "network-pre.target" 287 "systemd-sysctl.service" 288 ]; 289 before = [ "network.target" ]; 290 wantedBy = [ "multi-user.target" ]; 291 startLimitIntervalSec = 180; 292 reloadIfChanged = true; 293 restartTriggers = [ 294 configFile 295 daemonList 296 ]; 297 serviceConfig = { 298 Nice = -5; 299 Type = "forking"; 300 NotifyAccess = "all"; 301 StartLimitBurst = "3"; 302 TimeoutSec = 120; 303 WatchdogSec = 60; 304 RestartSec = 5; 305 Restart = "always"; 306 LimitNOFILE = cfg.openFilesLimit; 307 PIDFile = "/run/frr/watchfrr.pid"; 308 ExecStart = "${pkgs.frr}/libexec/frr/frrinit.sh start"; 309 ExecStop = "${pkgs.frr}/libexec/frr/frrinit.sh stop"; 310 ExecReload = "${pkgs.frr}/libexec/frr/frrinit.sh reload"; 311 }; 312 }; 313 }; 314 315 meta.maintainers = with lib.maintainers; [ woffs ]; 316}