-{ pkgs, lib, config, ... }:
+{ pkgs, lib, config, options, ... }:
with lib;
let
cfg = config.services.netns;
+ inherit (config) networking;
# Escape as required by: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
escapeUnitName = name:
lib.concatMapStrings (s: if lib.isList s then "-" else s)
(builtins.split "[^a-zA-Z0-9_.\\-]+" name);
+ systemd = import (pkgs.path + "/nixos/modules/system/boot/systemd-unit-options.nix") { inherit config lib; };
in
{
options.services.netns = {
namespaces = mkOption {
description = "netns namespaces to create";
- type = types.attrsOf (types.submodule ({ name, ... }: {
+ type = types.attrsOf (types.submodule {
options = {
nftables = mkOption {
type = types.lines;
- default = "";
+ default = networking.nftables.ruleset;
description = ''
Nftables ruleset.
'';
};
- sysctl = mkOption {
- type = with types; attrsOf (nullOr (oneOf [bool str int]));
- default = {};
- description = ''
- Kernel sysctl.
- '';
+ sysctl = options.boot.kernel.sysctl // {
+ default = config.boot.kernel.sysctl;
};
service = mkOption {
+ # Avoid error: The option `services.netns.namespaces.${netns}.service.startLimitIntervalSec' is used but not defined.
+ #type = types.submodule [ { options = builtins.removeAttrs systemd.serviceOptions ["startLimitIntervalSec"]; } ];
type = types.attrs;
default = {};
description = ''
'';
};
};
- }));
+ });
default = {};
};
};
config = {
systemd.services = mapAttrs' (name: c:
nameValuePair "netns-${escapeUnitName name}" (mkMerge [
- { description = "${name} network namespace";
+ { description = mkForce "${name} network namespace";
before = [ "network.target" ];
serviceConfig = {
- Type = "oneshot";
+ Type = mkForce "oneshot";
RemainAfterExit = true;
PrivateNetwork = true;
- ExecStart = "${pkgs.iproute}/bin/ip netns add ${escapeShellArg name}";
- ExecStartPost = optional config.networking.nftables.enable
- "${pkgs.iproute}/bin/ip netns exec ${escapeShellArg name} ${pkgs.writeScript "nftables-ruleset" ''
- #!${pkgs.nftables}/bin/nft -f
- flush ruleset
- ${c.nftables}
- ''}";
- ExecStop = "${pkgs.iproute}/bin/ip netns del ${escapeShellArg name}";
+ ExecStart = mkForce (pkgs.writeShellScript "netns-start" ''
+ test -e /var/run/netns/${escapeShellArg name} ||
+ ${pkgs.iproute}/bin/ip netns add ${escapeShellArg name}
+ '');
+ ExecStartPost =
+ # Use --ignore because some keys may no longer exist in that new namespace,
+ # like net.ipv6.conf.eth0.addr_gen_mode or net.core.rmem_max
+ [''${pkgs.iproute}/bin/ip netns exec ${escapeShellArg name} ${pkgs.procps}/bin/sysctl --ignore -p ${pkgs.writeScript "sysctl"
+ (concatStrings (mapAttrsToList (n: v: optionalString (v != null) "${n}=${if v == false then "0" else toString v}\n") c.sysctl))}
+ ''] ++
+ optional networking.nftables.enable ''
+ ${pkgs.iproute}/bin/ip netns exec ${escapeShellArg name} ${pkgs.writeScript "nftables-ruleset" ''
+ #!${pkgs.nftables}/bin/nft -f
+ flush ruleset
+ ${c.nftables}
+ ''}
+ '';
+ ExecStop = mkForce "${pkgs.iproute}/bin/ip netns del ${escapeShellArg name}";
};
}
- #cfg.service
c.service
- ])) cfg.namespaces;
+ ]
+ )) cfg.namespaces;
meta.maintainers = with lib.maintainers; [ julm ];
};
}