at 25.11-pre 6.6 kB view raw
1{ 2 options, 3 config, 4 pkgs, 5 lib, 6 ... 7}: 8 9let 10 inherit (lib) mkOption types mkIf; 11 12 opt = options.services.quicktun; 13 cfg = config.services.quicktun; 14in 15{ 16 options = { 17 services.quicktun = mkOption { 18 default = { }; 19 description = '' 20 QuickTun tunnels. 21 22 See <http://wiki.ucis.nl/QuickTun> for more information about available options. 23 ''; 24 type = types.attrsOf ( 25 types.submodule ( 26 { name, ... }: 27 let 28 qtcfg = cfg.${name}; 29 in 30 { 31 options = { 32 tunMode = mkOption { 33 type = with types; coercedTo bool (b: if b then 1 else 0) (ints.between 0 1); 34 default = false; 35 example = true; 36 description = "Whether to operate in tun (IP) or tap (Ethernet) mode."; 37 }; 38 39 remoteAddress = mkOption { 40 type = types.str; 41 default = "0.0.0.0"; 42 example = "tunnel.example.com"; 43 description = '' 44 IP address or hostname of the remote end (use `0.0.0.0` for a floating/dynamic remote endpoint). 45 ''; 46 }; 47 48 localAddress = mkOption { 49 type = with types; nullOr str; 50 default = null; 51 example = "0.0.0.0"; 52 description = "IP address or hostname of the local end."; 53 }; 54 55 localPort = mkOption { 56 type = types.port; 57 default = 2998; 58 description = "Local UDP port."; 59 }; 60 61 remotePort = mkOption { 62 type = types.port; 63 default = qtcfg.localPort; 64 defaultText = lib.literalExpression "config.services.quicktun.<name>.localPort"; 65 description = " remote UDP port"; 66 }; 67 68 remoteFloat = mkOption { 69 type = with types; coercedTo bool (b: if b then 1 else 0) (ints.between 0 1); 70 default = false; 71 example = true; 72 description = '' 73 Whether to allow the remote address and port to change when properly encrypted packets are received. 74 ''; 75 }; 76 77 protocol = mkOption { 78 type = types.enum [ 79 "raw" 80 "nacl0" 81 "nacltai" 82 "salty" 83 ]; 84 default = "nacltai"; 85 description = "Which protocol to use."; 86 }; 87 88 privateKey = mkOption { 89 type = with types; nullOr str; 90 default = null; 91 description = '' 92 Local secret key in hexadecimal form. 93 94 ::: {.warning} 95 This option is deprecated. Please use {var}`services.quicktun.<name>.privateKeyFile` instead. 96 ::: 97 98 ::: {.note} 99 Not needed when {var}`services.quicktun.<name>.protocol` is set to `raw`. 100 ::: 101 ''; 102 }; 103 104 privateKeyFile = mkOption { 105 type = with types; nullOr path; 106 # This is a hack to deprecate `privateKey` without using `mkChangedModuleOption` 107 default = 108 if qtcfg.privateKey == null then null else pkgs.writeText "quickttun-key-${name}" qtcfg.privateKey; 109 defaultText = "null"; 110 description = '' 111 Path to file containing local secret key in binary or hexadecimal form. 112 113 ::: {.note} 114 Not needed when {var}`services.quicktun.<name>.protocol` is set to `raw`. 115 ::: 116 ''; 117 }; 118 119 publicKey = mkOption { 120 type = with types; nullOr str; 121 default = null; 122 description = '' 123 Remote public key in hexadecimal form. 124 125 ::: {.note} 126 Not needed when {var}`services.quicktun.<name>.protocol` is set to `raw`. 127 ::: 128 ''; 129 }; 130 131 timeWindow = mkOption { 132 type = types.ints.unsigned; 133 default = 5; 134 description = '' 135 Allowed time window for first received packet in seconds (positive number allows packets from history) 136 ''; 137 }; 138 139 upScript = mkOption { 140 type = with types; nullOr lines; 141 default = null; 142 description = '' 143 Run specified command or script after the tunnel device has been opened. 144 ''; 145 }; 146 }; 147 } 148 ) 149 ); 150 }; 151 }; 152 153 config = { 154 warnings = lib.pipe cfg [ 155 (lib.mapAttrsToList (name: value: if value.privateKey != null then name else null)) 156 (builtins.filter (n: n != null)) 157 (map (n: " - services.quicktun.${n}.privateKey")) 158 ( 159 services: 160 lib.optional (services != [ ]) '' 161 `services.quicktun.<name>.privateKey` is deprecated. 162 Please use `services.quicktun.<name>.privateKeyFile` instead. 163 164 Offending options: 165 ${lib.concatStringsSep "\n" services} 166 '' 167 ) 168 ]; 169 170 systemd.services = lib.mkMerge ( 171 lib.mapAttrsToList (name: qtcfg: { 172 "quicktun-${name}" = { 173 wantedBy = [ "multi-user.target" ]; 174 after = [ "network.target" ]; 175 environment = { 176 INTERFACE = name; 177 TUN_MODE = toString qtcfg.tunMode; 178 REMOTE_ADDRESS = qtcfg.remoteAddress; 179 LOCAL_ADDRESS = mkIf (qtcfg.localAddress != null) (qtcfg.localAddress); 180 LOCAL_PORT = toString qtcfg.localPort; 181 REMOTE_PORT = toString qtcfg.remotePort; 182 REMOTE_FLOAT = toString qtcfg.remoteFloat; 183 PRIVATE_KEY_FILE = mkIf (qtcfg.privateKeyFile != null) qtcfg.privateKeyFile; 184 PUBLIC_KEY = mkIf (qtcfg.publicKey != null) qtcfg.publicKey; 185 TIME_WINDOW = toString qtcfg.timeWindow; 186 TUN_UP_SCRIPT = mkIf (qtcfg.upScript != null) ( 187 pkgs.writeScript "quicktun-${name}-up.sh" qtcfg.upScript 188 ); 189 SUID = "nobody"; 190 }; 191 serviceConfig = { 192 Type = "simple"; 193 ExecStart = "${pkgs.quicktun}/bin/quicktun.${qtcfg.protocol}"; 194 }; 195 }; 196 }) cfg 197 ); 198 }; 199}