Skip to content

Instantly share code, notes, and snippets.

@aktau
Last active January 15, 2026 23:04
Show Gist options
  • Select an option

  • Save aktau/0efe2322e982c671e28c93a8f0dec6a4 to your computer and use it in GitHub Desktop.

Select an option

Save aktau/0efe2322e982c671e28c93a8f0dec6a4 to your computer and use it in GitHub Desktop.
# Simplest working approach to solve https://www.reddit.com/r/NixOS/comments/1qdf0ut/how_to_override_all_systemd_services_with/
# Usage
# =====
#
# config.systemd.service.<name>.ondemandNetworkNamespace = "vpn"
#
# Description
# ===========
#
# Adds a ondemandNetworkNamespace option to systemd.services. If set, binds the
# systemd service to a "netns-${ondemandNetworkNamespace}.service".
{ config, pkgs, lib, utils, ... }:
let
inherit (lib) types;
in
{
options.systemd.services = lib.mkOption {
type = types.attrsOf (
types.submodule (
{ name, config, ... }:
{
options.ondemandNetworkNamespace = lib.mkOption {
type = types.nullOr types.str;
default = null;
description = ''
If set, this unit will join the "name" network namespace, and
TODO: another unit creating the "name" network namespace is
created.
'';
};
config = lib.mkIf (config.ondemandNetworkNamespace != null) {
after = [ "netns-${config.ondemandNetworkNamespace}.service" ];
bindsTo = [ "netns-${config.ondemandNetworkNamespace}.service" ];
serviceConfig = {
NetworkNamespacePath = "/run/netns/${config.ondemandNetworkNamespace}";
BindReadOnlyPaths = [
"/etc/netns/${config.ondemandNetworkNamespace}/resolv.conf:/etc/resolv.conf:norbind"
];
};
};
}
)
);
};
}
# More complicated approach to solve https://www.reddit.com/r/NixOS/comments/1qdf0ut/how_to_override_all_systemd_services_with/
#
# The difference is that it generates a /etc/systemd/system/${name}.service.d/network-namespace.conf override file.
# Usage
# =====
#
# config.systemd.service.<name>.ondemandNetworkNamespace = "vpn"
#
# Description
# ===========
#
# Adds a ondemandNetworkNamespace option to systemd.services. If set, binds the
# systemd service to a "netns-${ondemandNetworkNamespace}.service".
{ config, pkgs, lib, utils, ... }:
let
inherit (lib) types;
wireguardOpts = { name, ... }: {
options = {
configFile = lib.mkOption {
example = "/secret/wg0.conf";
default = null;
type = with types; nullOr str;
description = "wg-quick .conf file.";
};
};
};
in
{
options.systemd.services = lib.mkOption {
type = types.attrsOf (
types.submodule (
{ name, config, ... }:
{
options.ondemandNetworkNamespace = lib.mkOption {
type = types.nullOr types.str;
default = null;
description = ''
If set, this unit will join the "name" network namespace, and
TODO: another unit creating the "name" network namespace is
created.
'';
};
}
)
);
};
# NOTE: I'm not sure why [lib.concatLists] is necessary here. The inner call
# is [lib.mapAttrsToList] over [config.systemd.services], invoking a function
# that returns a package for every attr in [config.systemd.services].
# Without [lib.concatLists], we get the following error:
#
# error: A definition for option `systemd.packages."[definition 1-entry 1]"' is not of type `package'
#
# Oh well..
config.systemd.packages = lib.concatLists (
lib.mapAttrsToList (
name: cfg:
lib.optional (cfg.ondemandNetworkNamespace != null) (
pkgs.writeTextFile {
name = "network-namespace.conf";
destination = "/etc/systemd/system/${name}.service.d/network-namespace.conf";
text = (utils.systemdUtils.lib.serviceToUnit {
serviceConfig = {
NetworkNamespacePath = "/run/netns/${cfg.ondemandNetworkNamespace}";
BindReadOnlyPaths = [
"/etc/netns/${cfg.ondemandNetworkNamespace}/resolv.conf:/etc/resolv.conf:norbind"
];
};
# The following are necessary to be able to use [serviceToUnit].
# This means we're using internals that will break us. Oh well.
#
# error: attribute 'environment' missing
# at /nix/store/vac8x2i4dlw7j7726fbs7ma1g6k9b7rq-nixos-25.11.3064.64049ca74d63/nixos/nixos/lib/systemd-lib.nix:773:42:
unitConfig = {
After = [ "netns-${cfg.ondemandNetworkNamespace}.service" ];
BindsTo = [ "netns-${cfg.ondemandNetworkNamespace}.service" ];
};
environment = { };
wantedBy = [ ];
}).text;
# ''
# [Service]
# Environment="FOO=bar"
# '';
}
)
) config.systemd.services
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment