1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8with lib;
9
10let
11
12 cfg = config.services.networkd-dispatcher;
13
14in
15{
16
17 options = {
18 services.networkd-dispatcher = {
19
20 enable = mkEnableOption ''
21 Networkd-dispatcher service for systemd-networkd connection status
22 change. See [upstream instructions](https://gitlab.com/craftyguy/networkd-dispatcher)
23 for usage
24 '';
25
26 rules = mkOption {
27 default = { };
28 example = lib.literalExpression ''
29 { "restart-tor" = {
30 onState = ["routable" "off"];
31 script = '''
32 #!''${pkgs.runtimeShell}
33 if [[ $IFACE == "wlan0" && $AdministrativeState == "configured" ]]; then
34 echo "Restarting Tor ..."
35 systemctl restart tor
36 fi
37 exit 0
38 ''';
39 };
40 };
41 '';
42 description = ''
43 Declarative configuration of networkd-dispatcher rules. See
44 [upstream instructions](https://gitlab.com/craftyguy/networkd-dispatcher)
45 for an introduction and example scripts.
46 '';
47 type = types.attrsOf (
48 types.submodule {
49 options = {
50 onState = mkOption {
51 type = types.listOf (
52 types.enum [
53 "routable"
54 "dormant"
55 "no-carrier"
56 "off"
57 "carrier"
58 "degraded"
59 "configuring"
60 "configured"
61 "enslaved"
62 ]
63 );
64 default = null;
65 description = ''
66 List of names of the systemd-networkd operational states which
67 should trigger the script. See {manpage}`networkctl(1)`
68 for a description of the specific state type.
69 '';
70 };
71 script = mkOption {
72 type = types.lines;
73 description = ''
74 Shell commands executed on specified operational states.
75 '';
76 };
77 };
78 }
79 );
80 };
81
82 extraArgs = mkOption {
83 type = types.listOf types.str;
84 default = [ ];
85 description = ''
86 Extra arguments to pass to the networkd-dispatcher command.
87 '';
88 apply = escapeShellArgs;
89 };
90
91 };
92 };
93
94 config = mkIf cfg.enable {
95
96 systemd = {
97 packages = [ pkgs.networkd-dispatcher ];
98 services.networkd-dispatcher = {
99 wantedBy = [ "multi-user.target" ];
100 environment.networkd_dispatcher_args = cfg.extraArgs;
101 };
102 };
103
104 services.networkd-dispatcher.extraArgs =
105 let
106 scriptDir = pkgs.runCommand "networkd-dispatcher-script-dir" { } (
107 ''
108 mkdir $out
109 ''
110 + (lib.concatStrings (
111 lib.mapAttrsToList (
112 name: cfg:
113 (lib.concatStrings (
114 map (state: ''
115 mkdir -p $out/${state}.d
116 ln -s ${
117 lib.getExe (
118 pkgs.writeShellApplication {
119 inherit name;
120 text = cfg.script;
121 }
122 )
123 } $out/${state}.d/${name}
124 '') cfg.onState
125 ))
126 ) cfg.rules
127 ))
128 );
129 in
130 [
131 "--verbose"
132 "--script-dir"
133 "${scriptDir}"
134 ];
135
136 };
137}