diff options
Diffstat (limited to 'custom/tinc/def.nix')
-rw-r--r-- | custom/tinc/def.nix | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/custom/tinc/def.nix b/custom/tinc/def.nix new file mode 100644 index 00000000..e191168f --- /dev/null +++ b/custom/tinc/def.nix | |||
@@ -0,0 +1,175 @@ | |||
1 | { config, lib, pkgs, ... }: | ||
2 | |||
3 | with lib; | ||
4 | |||
5 | let | ||
6 | |||
7 | cfg = config.services.tinc; | ||
8 | |||
9 | in | ||
10 | |||
11 | { | ||
12 | |||
13 | ###### interface | ||
14 | |||
15 | options = { | ||
16 | |||
17 | services.tinc = { | ||
18 | |||
19 | networks = mkOption { | ||
20 | default = { }; | ||
21 | type = types.loaOf types.optionSet; | ||
22 | description = '' | ||
23 | Defines the tinc networks which will be started. | ||
24 | Each network invokes a different daemon. | ||
25 | ''; | ||
26 | options = { | ||
27 | |||
28 | extraConfig = mkOption { | ||
29 | default = ""; | ||
30 | type = types.lines; | ||
31 | description = '' | ||
32 | Extra lines to add to the tinc service configuration file. | ||
33 | ''; | ||
34 | }; | ||
35 | |||
36 | name = mkOption { | ||
37 | default = null; | ||
38 | type = types.nullOr types.str; | ||
39 | description = '' | ||
40 | The name of the node which is used as an identifier when communicating | ||
41 | with the remote nodes in the mesh. If null then the hostname of the system | ||
42 | is used. | ||
43 | ''; | ||
44 | }; | ||
45 | |||
46 | debugLevel = mkOption { | ||
47 | default = 0; | ||
48 | type = types.addCheck types.int (l: l >= 0 && l <= 5); | ||
49 | description = '' | ||
50 | The amount of debugging information to add to the log. 0 means little | ||
51 | logging while 5 is the most logging. <command>man tincd</command> for | ||
52 | more details. | ||
53 | ''; | ||
54 | }; | ||
55 | |||
56 | hosts = mkOption { | ||
57 | default = { }; | ||
58 | type = types.loaOf types.lines; | ||
59 | description = '' | ||
60 | The name of the host in the network as well as the configuration for that host. | ||
61 | This name should only contain alphanumerics and underscores. | ||
62 | ''; | ||
63 | }; | ||
64 | |||
65 | interfaceType = mkOption { | ||
66 | default = "tun"; | ||
67 | type = types.addCheck types.str (n: n == "tun" || n == "tap"); | ||
68 | description = '' | ||
69 | The type of virtual interface used for the network connection | ||
70 | ''; | ||
71 | }; | ||
72 | |||
73 | package = mkOption { | ||
74 | default = pkgs.tinc_pre; | ||
75 | description = '' | ||
76 | The package to use for the tinc daemon's binary. | ||
77 | ''; | ||
78 | }; | ||
79 | |||
80 | scripts = mkOption { | ||
81 | default = { }; | ||
82 | type = types.loaOf (types.nullOr types.str); | ||
83 | description = '' | ||
84 | Hook scripts | ||
85 | ''; | ||
86 | }; | ||
87 | |||
88 | }; | ||
89 | }; | ||
90 | }; | ||
91 | |||
92 | }; | ||
93 | |||
94 | |||
95 | ###### implementation | ||
96 | |||
97 | config = mkIf (cfg.networks != { }) { | ||
98 | |||
99 | environment.etc = fold (a: b: a // b) { } | ||
100 | (flip mapAttrsToList cfg.networks (network: data: | ||
101 | flip mapAttrs' data.hosts (host: text: nameValuePair | ||
102 | ("tinc/${network}/hosts/${host}") | ||
103 | ({ inherit text; }) | ||
104 | ) // (flip mapAttrs' data.scripts (scriptName: text: nameValuePair | ||
105 | ("tinc/${network}/${scriptName}") | ||
106 | ({ mode = "0555"; inherit text; }) | ||
107 | )) // { | ||
108 | "tinc/${network}/tinc.conf" = { | ||
109 | text = '' | ||
110 | Name = ${if data.name == null then "$HOST" else data.name} | ||
111 | DeviceType = ${data.interfaceType} | ||
112 | Device = /dev/net/tun | ||
113 | Interface = tinc.${network} | ||
114 | ${data.extraConfig} | ||
115 | ''; | ||
116 | }; | ||
117 | } | ||
118 | )); | ||
119 | |||
120 | networking.interfaces = flip mapAttrs' cfg.networks (network: data: nameValuePair | ||
121 | ("tinc.${network}") | ||
122 | ({ | ||
123 | virtual = true; | ||
124 | virtualType = "${data.interfaceType}"; | ||
125 | }) | ||
126 | ); | ||
127 | |||
128 | systemd.services = flip mapAttrs' cfg.networks (network: data: nameValuePair | ||
129 | ("tinc.${network}") | ||
130 | ({ | ||
131 | description = "Tinc Daemon - ${network}"; | ||
132 | wantedBy = [ "network.target" ]; | ||
133 | after = [ "network-interfaces.target" ]; | ||
134 | path = [ data.package ]; | ||
135 | restartTriggers = [ config.environment.etc."tinc/${network}/tinc.conf".source ] | ||
136 | ++ mapAttrsToList (host: _ : config.environment.etc."tinc/${network}/hosts/${host}".source) data.hosts; | ||
137 | serviceConfig = { | ||
138 | Type = "simple"; | ||
139 | PIDFile = "/run/tinc.${network}.pid"; | ||
140 | }; | ||
141 | preStart = '' | ||
142 | ${pkgs.openresolv}/bin/resolvconf -d tinc.${network} || true | ||
143 | ''; | ||
144 | # preStart = '' | ||
145 | # mkdir -p /etc/tinc/${network}/hosts | ||
146 | |||
147 | # # Determine how we should generate our keys | ||
148 | # if type tinc >/dev/null 2>&1; then | ||
149 | # # Tinc 1.1+ uses the tinc helper application for key generation | ||
150 | |||
151 | # # Prefer ED25519 keys (only in 1.1+) | ||
152 | # [ -f "/etc/tinc/${network}/ed25519_key.priv" ] || tinc -n ${network} generate-ed25519-keys | ||
153 | |||
154 | # # Otherwise use RSA keys | ||
155 | # [ -f "/etc/tinc/${network}/rsa_key.priv" ] || tinc -n ${network} generate-rsa-keys 4096 | ||
156 | # else | ||
157 | # # Tinc 1.0 uses the tincd application | ||
158 | # [ -f "/etc/tinc/${network}/rsa_key.priv" ] || tincd -n ${network} -K 4096 | ||
159 | # fi | ||
160 | # ''; | ||
161 | script = '' | ||
162 | tincd -D -U tinc.${network} -n ${network} --pidfile /run/tinc.${network}.pid -d ${toString data.debugLevel} | ||
163 | ''; | ||
164 | }) | ||
165 | ); | ||
166 | |||
167 | users.extraUsers = flip mapAttrs' cfg.networks (network: _: | ||
168 | nameValuePair ("tinc.${network}") ({ | ||
169 | description = "Tinc daemon user for ${network}"; | ||
170 | }) | ||
171 | ); | ||
172 | |||
173 | }; | ||
174 | |||
175 | } | ||