1# NixOS module for hans, ip over icmp daemon
2{
3 config,
4 lib,
5 pkgs,
6 ...
7}:
8let
9 cfg = config.services.hans;
10
11 hansUser = "hans";
12
13in
14{
15
16 ### configuration
17
18 options = {
19
20 services.hans = {
21 clients = lib.mkOption {
22 default = { };
23 description = ''
24 Each attribute of this option defines a systemd service that
25 runs hans. Many or none may be defined.
26 The name of each service is
27 `hans-«name»`
28 where «name» is the name of the
29 corresponding attribute name.
30 '';
31 example = lib.literalExpression ''
32 {
33 foo = {
34 server = "192.0.2.1";
35 extraConfig = "-v";
36 }
37 }
38 '';
39 type = lib.types.attrsOf (
40 lib.types.submodule ({
41 options = {
42 server = lib.mkOption {
43 type = lib.types.str;
44 default = "";
45 description = "IP address of server running hans";
46 example = "192.0.2.1";
47 };
48
49 extraConfig = lib.mkOption {
50 type = lib.types.str;
51 default = "";
52 description = "Additional command line parameters";
53 example = "-v";
54 };
55
56 passwordFile = lib.mkOption {
57 type = lib.types.str;
58 default = "";
59 description = "File that contains password";
60 };
61
62 };
63 })
64 );
65 };
66
67 server = {
68 enable = lib.mkOption {
69 type = lib.types.bool;
70 default = false;
71 description = "enable hans server";
72 };
73
74 ip = lib.mkOption {
75 type = lib.types.str;
76 default = "";
77 description = "The assigned ip range";
78 example = "198.51.100.0";
79 };
80
81 respondToSystemPings = lib.mkOption {
82 type = lib.types.bool;
83 default = false;
84 description = "Force hans respond to ordinary pings";
85 };
86
87 extraConfig = lib.mkOption {
88 type = lib.types.str;
89 default = "";
90 description = "Additional command line parameters";
91 example = "-v";
92 };
93
94 passwordFile = lib.mkOption {
95 type = lib.types.str;
96 default = "";
97 description = "File that contains password";
98 };
99 };
100
101 };
102 };
103
104 ### implementation
105
106 config = lib.mkIf (cfg.server.enable || cfg.clients != { }) {
107 boot.kernel.sysctl = lib.optionalAttrs cfg.server.respondToSystemPings {
108 "net.ipv4.icmp_echo_ignore_all" = 1;
109 };
110
111 boot.kernelModules = [ "tun" ];
112
113 systemd.services =
114 let
115 createHansClientService = name: cfg: {
116 description = "hans client - ${name}";
117 after = [ "network.target" ];
118 wantedBy = [ "multi-user.target" ];
119 script = "${pkgs.hans}/bin/hans -f -u ${hansUser} ${cfg.extraConfig} -c ${cfg.server} ${
120 lib.optionalString (cfg.passwordFile != "") "-p $(cat \"${cfg.passwordFile}\")"
121 }";
122 serviceConfig = {
123 RestartSec = "30s";
124 Restart = "always";
125 };
126 };
127 in
128 lib.listToAttrs (
129 lib.mapAttrsToList (
130 name: value: lib.nameValuePair "hans-${name}" (createHansClientService name value)
131 ) cfg.clients
132 )
133 // {
134 hans = lib.mkIf (cfg.server.enable) {
135 description = "hans, ip over icmp server daemon";
136 after = [ "network.target" ];
137 wantedBy = [ "multi-user.target" ];
138 script = "${pkgs.hans}/bin/hans -f -u ${hansUser} ${cfg.server.extraConfig} -s ${cfg.server.ip} ${lib.optionalString cfg.server.respondToSystemPings "-r"} ${
139 lib.optionalString (cfg.server.passwordFile != "") "-p $(cat \"${cfg.server.passwordFile}\")"
140 }";
141 };
142 };
143
144 users.users.${hansUser} = {
145 description = "Hans daemon user";
146 isSystemUser = true;
147 };
148 };
149
150 meta.maintainers = [ ];
151}