at 15.09-beta 4.8 kB view raw
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}