1 { pkgs, lib, config, options, ... }:
4 cfg = config.services.netns;
5 inherit (config) networking;
6 # Escape as required by: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
8 lib.concatMapStrings (s: if lib.isList s then "-" else s)
9 (builtins.split "[^a-zA-Z0-9_.\\-]+" name);
10 systemd = import (pkgs.path + "/nixos/modules/system/boot/systemd-unit-options.nix") { inherit config lib; };
13 options.services.netns = {
14 namespaces = mkOption {
15 description = "netns namespaces to create";
16 type = types.attrsOf (types.submodule {
20 default = networking.nftables.ruleset;
25 sysctl = options.boot.kernel.sysctl // {
26 default = config.boot.kernel.sysctl;
29 # Avoid error: The option `services.netns.namespaces.${netns}.service.startLimitIntervalSec' is used but not defined.
30 #type = types.submodule [ { options = builtins.removeAttrs systemd.serviceOptions ["startLimitIntervalSec"]; } ];
34 Systemd configuration specific to this netns service.
43 systemd.services = mapAttrs' (name: c:
44 nameValuePair "netns-${escapeUnitName name}" (mkMerge [
45 { description = mkForce "${name} network namespace";
46 before = [ "network.target" ];
48 Type = mkForce "oneshot";
49 RemainAfterExit = true;
50 PrivateNetwork = true;
51 ExecStart = mkForce (pkgs.writeShellScript "netns-start" ''
52 test -e /var/run/netns/${escapeShellArg name} ||
53 ${pkgs.iproute}/bin/ip netns add ${escapeShellArg name}
56 # Use --ignore because some keys may no longer exist in that new namespace,
57 # like net.ipv6.conf.eth0.addr_gen_mode or net.core.rmem_max
58 [''${pkgs.iproute}/bin/ip netns exec ${escapeShellArg name} ${pkgs.procps}/bin/sysctl --ignore -p ${pkgs.writeScript "sysctl"
59 (concatStrings (mapAttrsToList (n: v: optionalString (v != null) "${n}=${if v == false then "0" else toString v}\n") c.sysctl))}
61 optional networking.nftables.enable ''
62 ${pkgs.iproute}/bin/ip netns exec ${escapeShellArg name} ${pkgs.writeScript "nftables-ruleset" ''
63 #!${pkgs.nftables}/bin/nft -f
68 ExecStop = mkForce "${pkgs.iproute}/bin/ip netns del ${escapeShellArg name}";
74 meta.maintainers = with lib.maintainers; [ julm ];