diff --git a/nixos/modules/services/networking/networkd-dispatcher.nix b/nixos/modules/services/networking/networkd-dispatcher.nix index d13ca23368c5..c5319ca7b88a 100644 --- a/nixos/modules/services/networking/networkd-dispatcher.nix +++ b/nixos/modules/services/networking/networkd-dispatcher.nix @@ -3,8 +3,11 @@ with lib; let + cfg = config.services.networkd-dispatcher; + in { + options = { services.networkd-dispatcher = { @@ -14,14 +17,49 @@ in { for usage. ''); - scriptDir = mkOption { - type = types.path; - default = "/var/lib/networkd-dispatcher"; - description = mdDoc '' - This directory is used for keeping various scripts read and run by - networkd-dispatcher. See [https://gitlab.com/craftyguy/networkd-dispatcher](upstream instructions) - for directory structure and script usage. + rules = mkOption { + default = {}; + example = lib.literalExpression '' + { "restart-tor" = { + onState = ["routable" "off"]; + script = ''' + #!''${pkgs.runtimeShell} + if [[ $IFACE == "wlan0" && $AdministrativeState == "configured" ]]; then + echo "Restarting Tor ..." + systemctl restart tor + fi + exit 0 + '''; + }; + }; ''; + description = lib.mdDoc '' + Declarative configuration of networkd-dispatcher rules. See + [https://gitlab.com/craftyguy/networkd-dispatcher](upstream instructions) + for an introduction and example scripts. + ''; + type = types.attrsOf (types.submodule { + options = { + onState = mkOption { + type = types.listOf (types.enum [ + "routable" "dormant" "no-carrier" "off" "carrier" "degraded" + "configuring" "configured" + ]); + default = null; + description = lib.mdDoc '' + List of names of the systemd-networkd operational states which + should trigger the script. See + for a description of the specific state type. + ''; + }; + script = mkOption { + type = types.lines; + description = lib.mdDoc '' + Shell commands executed on specified operational states. + ''; + }; + }; + }); }; }; @@ -30,34 +68,31 @@ in { config = mkIf cfg.enable { systemd = { - packages = [ pkgs.networkd-dispatcher ]; services.networkd-dispatcher = { wantedBy = [ "multi-user.target" ]; # Override existing ExecStart definition - serviceConfig.ExecStart = [ + serviceConfig.ExecStart = let + scriptDir = pkgs.symlinkJoin { + name = "networkd-dispatcher-script-dir"; + paths = lib.mapAttrsToList (name: cfg: + (map(state: + pkgs.writeTextFile { + inherit name; + text = cfg.script; + destination = "/${state}.d/${name}"; + executable = true; + } + ) cfg.onState) + ) cfg.rules; + }; + in [ "" - "${pkgs.networkd-dispatcher}/bin/networkd-dispatcher -v --script-dir ${cfg.scriptDir} $networkd_dispatcher_args" + "${pkgs.networkd-dispatcher}/bin/networkd-dispatcher -v --script-dir ${scriptDir} $networkd_dispatcher_args" ]; }; - - # Directory structure required according to upstream instructions - # https://gitlab.com/craftyguy/networkd-dispatcher - tmpfiles.rules = [ - "d '${cfg.scriptDir}' 0750 root root - -" - "d '${cfg.scriptDir}/routable.d' 0750 root root - -" - "d '${cfg.scriptDir}/dormant.d' 0750 root root - -" - "d '${cfg.scriptDir}/no-carrier.d' 0750 root root - -" - "d '${cfg.scriptDir}/off.d' 0750 root root - -" - "d '${cfg.scriptDir}/carrier.d' 0750 root root - -" - "d '${cfg.scriptDir}/degraded.d' 0750 root root - -" - "d '${cfg.scriptDir}/configuring.d' 0750 root root - -" - "d '${cfg.scriptDir}/configured.d' 0750 root root - -" - ]; - }; - }; } diff --git a/pkgs/tools/networking/networkd-dispatcher/default.nix b/pkgs/tools/networking/networkd-dispatcher/default.nix index b8812cb678de..161772ed4819 100644 --- a/pkgs/tools/networking/networkd-dispatcher/default.nix +++ b/pkgs/tools/networking/networkd-dispatcher/default.nix @@ -19,6 +19,12 @@ stdenv.mkDerivation rec { hash = "sha256-yO9/HlUkaQmW/n9N3vboHw//YMzBjxIHA2zAxgZNEv0="; }; + patches = [ + # Support rule files in NixOS store paths. Required for the networkd-dispatcher + # module to work + ./support_nix_store_path.patch + ]; + postPatch = '' # Fix paths in systemd unit file substituteInPlace networkd-dispatcher.service \ diff --git a/pkgs/tools/networking/networkd-dispatcher/support_nix_store_path.patch b/pkgs/tools/networking/networkd-dispatcher/support_nix_store_path.patch new file mode 100644 index 000000000000..6d32548f1883 --- /dev/null +++ b/pkgs/tools/networking/networkd-dispatcher/support_nix_store_path.patch @@ -0,0 +1,13 @@ +diff --git a/networkd-dispatcher b/networkd-dispatcher +index ef877ce..8c341f2 100755 +--- a/networkd-dispatcher ++++ b/networkd-dispatcher +@@ -171,6 +171,8 @@ def check_perms(path, mode=0o755, uid=0, gid=0): + + if not os.path.exists(path): + raise FileNotFoundError ++ if re.search('^/nix/store/.*', str(path)): ++ return True + st = os.stat(path, follow_symlinks=False) + st_mode = st.st_mode & 0x00FFF + if st.st_uid == uid and st.st_gid == gid and st_mode == mode: