netnsd/nix/module.nix

110 lines
3.3 KiB
Nix

{
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.networking.netnsd;
hasNamespaces = cfg.namespaces != {};
format = pkgs.formats.toml {};
configFile = format.generate "netnsd.toml" {
namespace = mapAttrsToList (_: value: value) cfg.namespaces;
};
in {
options.networking.netnsd = {
package = mkOption {
type = types.package;
description = "package to use";
};
logLevel = mkOption {
type = types.str;
default = "info";
description = "Log level";
};
namespaces = mkOption {
type = types.attrsOf (types.submodule ({name, ...}: {
options = {
name = mkOption {
type = types.str;
default = name;
description = "target port inside the namespace";
};
forward = mkOption {
type = types.listOf (types.submodule ({config, ...}: {
options = {
source = mkOption {
type = types.oneOf [types.port types.str];
default = config.target;
defaultText = "<target>";
description = "source port, address or socket outside the namespace";
};
target = mkOption {
type = types.oneOf [types.port types.str];
description = "target port or address inside the namespace";
};
reverse = mkOption {
type = types.bool;
default = false;
description = "forward from inside the namespace to outside instead";
};
};
}));
description = "ports to forward into the namespace";
default = [];
};
devices = mkOption {
type = types.listOf types.str;
default = [];
description = "devices to move into the namespace";
};
route = mkOption {
type = types.listOf (types.submodule ({config, ...}: {
options = {
device = mkOption {
type = types.str;
description = "device to route the traffic trough";
};
destination = mkOption {
type = types.str;
description = "What traffic to route. Either \"default\" or an ip range in CIDR notation";
};
};
}));
description = "routes to setup inside the namespace";
default = [];
};
};
}));
description = "namespaces to setup";
default = {};
};
};
config = mkIf hasNamespaces {
# symlink instead of passing `configFile` directly to netnsd to allow changing the config without changing the path
environment.etc."netnsd/netnsd.toml".source = configFile;
environment.systemPackages = with pkgs; [cfg.package];
systemd.services.netnsd = {
reloadTriggers = [configFile];
wantedBy = ["multi-user.target"];
before = ["network.target"];
environment = {
RUST_LOG = cfg.logLevel;
};
serviceConfig = {
Restart = "on-failure";
Type = "notify-reload";
ExecStart = "${getExe cfg.package} daemon -c /etc/netnsd/netnsd.toml";
NoNewPrivileges = true;
};
};
};
}