Last active
January 15, 2026 23:04
-
-
Save aktau/0efe2322e982c671e28c93a8f0dec6a4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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" | |
| ]; | |
| }; | |
| }; | |
| } | |
| ) | |
| ); | |
| }; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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