1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.tinc;
8
9in
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 };
81 };
82 };
83
84 };
85
86
87 ###### implementation
88
89 config = mkIf (cfg.networks != { }) {
90
91 environment.etc = fold (a: b: a // b) { }
92 (flip mapAttrsToList cfg.networks (network: data:
93 flip mapAttrs' data.hosts (host: text: nameValuePair
94 ("tinc/${network}/hosts/${host}")
95 ({ mode = "0444"; inherit text; })
96 ) // {
97 "tinc/${network}/tinc.conf" = {
98 mode = "0444";
99 text = ''
100 Name = ${if data.name == null then "$HOST" else data.name}
101 DeviceType = ${data.interfaceType}
102 Device = /dev/net/tun
103 Interface = tinc.${network}
104 ${data.extraConfig}
105 '';
106 };
107 }
108 ));
109
110 networking.interfaces = flip mapAttrs' cfg.networks (network: data: nameValuePair
111 ("tinc.${network}")
112 ({
113 virtual = true;
114 virtualType = "${data.interfaceType}";
115 })
116 );
117
118 systemd.services = flip mapAttrs' cfg.networks (network: data: nameValuePair
119 ("tinc.${network}")
120 ({
121 description = "Tinc Daemon - ${network}";
122 wantedBy = [ "network.target" ];
123 after = [ "network-interfaces.target" ];
124 path = [ data.package ];
125 restartTriggers = [ config.environment.etc."tinc/${network}/tinc.conf".source ]
126 ++ mapAttrsToList (host: _ : config.environment.etc."tinc/${network}/hosts/${host}".source) data.hosts;
127 serviceConfig = {
128 Type = "simple";
129 PIDFile = "/run/tinc.${network}.pid";
130 };
131 preStart = ''
132 mkdir -p /etc/tinc/${network}/hosts
133
134 # Determine how we should generate our keys
135 if type tinc >/dev/null 2>&1; then
136 # Tinc 1.1+ uses the tinc helper application for key generation
137
138 # Prefer ED25519 keys (only in 1.1+)
139 [ -f "/etc/tinc/${network}/ed25519_key.priv" ] || tinc -n ${network} generate-ed25519-keys
140
141 # Otherwise use RSA keys
142 [ -f "/etc/tinc/${network}/rsa_key.priv" ] || tinc -n ${network} generate-rsa-keys 4096
143 else
144 # Tinc 1.0 uses the tincd application
145 [ -f "/etc/tinc/${network}/rsa_key.priv" ] || tincd -n ${network} -K 4096
146 fi
147 '';
148 script = ''
149 tincd -D -U tinc.${network} -n ${network} --pidfile /run/tinc.${network}.pid -d ${toString data.debugLevel}
150 '';
151 })
152 );
153
154 users.extraUsers = flip mapAttrs' cfg.networks (network: _:
155 nameValuePair ("tinc.${network}") ({
156 description = "Tinc daemon user for ${network}";
157 isSystemUser = true;
158 })
159 );
160
161 };
162
163}