{ config, lib, pkgs, ... }: let inherit (lib) mkOption mkIf mkMerge types getExe' flip mapAttrs' flatten mapAttrsToList nameValuePair concatMapStringsSep mkEnableOption ; cfg = config.networking.netnsIf; in { options.networking.netnsIf = { assignments = mkOption { description = '' Assign network interfaces to a network namespaces by MAC address. ''; type = types.attrsOf (types.listOf types.str); default = {}; }; }; config = mkIf (cfg.assignments != {}) { systemd.services = mkMerge [ { "netns@" = { description = "Ensure the %I network namespace exists"; serviceConfig = { Type = "oneshot"; }; scriptArgs = "%I"; script = '' set -eo pipefail _network_namespace="$1" if ! [ -n "$(${getExe' pkgs.iproute2 "ip"} netns list | grep "$_network_namespace")" ] ; then ${getExe' pkgs.iproute2 "ip"} netns add "$_network_namespace" fi ''; }; } (flip mapAttrs' cfg.assignments (n: _: nameValuePair "netns-${n}-if@" { description = "Move %I interface to namespace"; requires = ["netns@${n}.service"]; after = ["netns@${n}.service"]; scriptArgs = "%I"; script = '' set -eo pipefail _kernel_name="$(basename "$1")" ${getExe' pkgs.iproute2 "ip"} link set "$_kernel_name" netns "${n}" ''; })) ]; services.udev.extraRules = flip (concatMapStringsSep "\n") (flatten (mapAttrsToList (n: v: map (x: { interface = x; namespace = n; }) v) cfg.assignments)) ({ interface, namespace, }: '' SUBSYSTEM=="net", ACTION=="add", DEVPATH!="/devices/virtual/*", ATTR{address}=="${interface}", TAG+="systemd", ENV{SYSTEMD_WANTS}="netns-${namespace}-if@.service" ''); }; }