{ config, lib, pkgs, ... }: with lib; let cfg = config.nix-nos.bgp; # Generate GoBGP configuration gobgpConfig = pkgs.writeText "gobgpd.conf" (builtins.toJSON { global = { config = { as = cfg.asn; router-id = cfg.routerId; }; }; neighbors = map (peer: { config = { neighbor-address = peer.address; peer-as = peer.asn; description = if peer.description != "" then peer.description else "BGP peer ${peer.address}"; }; }) cfg.peers; defined-sets = { prefix-sets = [ { prefix-set-name = "nix-nos-announcements"; prefix-list = map (ann: { ip-prefix = ann.prefix; }) cfg.announcements; } ]; }; policy-definitions = [ { name = "export-announcements"; statements = [ { conditions = { match-prefix-set = { prefix-set = "nix-nos-announcements"; }; }; actions = { route-disposition = "accept-route"; }; } ]; } ]; }); in { config = mkIf (config.nix-nos.enable && cfg.enable && cfg.backend == "gobgp") { # Install GoBGP package environment.systemPackages = [ pkgs.gobgp pkgs.gobgpd ]; # GoBGP systemd service systemd.services.gobgpd = { description = "GoBGP Routing Daemon"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "simple"; ExecStart = "${pkgs.gobgpd}/bin/gobgpd -f ${gobgpConfig}"; Restart = "on-failure"; RestartSec = "5s"; }; }; # Enable IP forwarding for BGP boot.kernel.sysctl = { "net.ipv4.ip_forward" = 1; }; # Add announcements as static routes networking.localCommands = mkIf (cfg.announcements != []) '' ${concatMapStringsSep "\n" (ann: let parts = splitString "/" ann.prefix; ip = elemAt parts 0; in "${pkgs.iproute2}/bin/ip route add ${ann.prefix} ${if ann.nexthop != null then "via ${ann.nexthop}" else "blackhole"}" ) cfg.announcements} ''; }; }