{ config, lib, pkgs, ... }: with lib; let cfg = config.nix-nos.routing; routeType = types.submodule { options = { destination = mkOption { type = types.str; description = "Destination network in CIDR notation"; example = "192.168.100.0/24"; }; gateway = mkOption { type = types.nullOr types.str; default = null; description = "Gateway IP address (null for blackhole routes)"; example = "192.168.1.1"; }; interface = mkOption { type = types.nullOr types.str; default = null; description = "Outbound interface name"; example = "eth0"; }; metric = mkOption { type = types.nullOr types.int; default = null; description = "Route metric/preference"; }; }; }; in { options.nix-nos.routing = { staticRoutes = mkOption { type = types.listOf routeType; default = []; description = "Static route configurations"; example = literalExpression '' [ { destination = "10.0.0.0/8"; gateway = "192.168.1.1"; interface = "eth0"; } { destination = "192.0.2.0/24"; gateway = null; # blackhole route } ] ''; }; }; config = mkIf (config.nix-nos.enable && cfg.staticRoutes != []) { # Add static routes using NixOS networking.localCommands networking.localCommands = concatMapStringsSep "\n" (route: let routeCmd = "${pkgs.iproute2}/bin/ip route add ${route.destination}"; viaClause = optionalString (route.gateway != null) " via ${route.gateway}"; devClause = optionalString (route.interface != null) " dev ${route.interface}"; metricClause = optionalString (route.metric != null) " metric ${toString route.metric}"; blackholeClause = optionalString (route.gateway == null && route.interface == null) " blackhole"; in "${routeCmd}${viaClause}${devClause}${metricClause}${blackholeClause} || true" ) cfg.staticRoutes; }; }