1 { config, lib, pkgs, ... }:
20 mainCfg = config.services.ghostunnel;
22 module = { config, name, ... }:
28 Address and port to listen on (can be HOST:PORT, unix:PATH).
35 Address to forward connections to (can be HOST:PORT or unix:PATH).
42 Path to keystore (combined PEM with cert/key, or PKCS12 keystore).
44 NB: storepass is not supported because it would expose credentials via `/proc/*/cmdline`.
46 Specify this or `cert` and `key`.
48 type = types.nullOr types.str;
54 Path to certificate (PEM with certificate chain).
56 Not required if `keystore` is set.
58 type = types.nullOr types.str;
64 Path to certificate private key (PEM with private key).
66 Not required if `keystore` is set.
68 type = types.nullOr types.str;
74 Path to CA bundle file (PEM/X509). Uses system trust store if `null`.
76 type = types.nullOr types.str;
79 disableAuthentication = mkOption {
81 Disable client authentication, no client certificate will be required.
89 If true, allow all clients, do not check client cert subject.
97 Allow client if common name appears in the list.
99 type = types.listOf types.str;
105 Allow client if organizational unit name appears in the list.
107 type = types.listOf types.str;
111 allowDNS = mkOption {
113 Allow client if DNS subject alternative name appears in the list.
115 type = types.listOf types.str;
119 allowURI = mkOption {
121 Allow client if URI subject alternative name appears in the list.
123 type = types.listOf types.str;
127 extraArguments = mkOption {
128 description = "Extra arguments to pass to `ghostunnel server`";
129 type = types.separatedString " ";
133 unsafeTarget = mkOption {
135 If set, does not limit target to localhost, 127.0.0.1, [::1], or UNIX sockets.
137 This is meant to protect against accidental unencrypted traffic on
144 # Definitions to apply at the root of the NixOS configuration.
150 # Clients should not be authenticated with the public root certificates
151 # (afaict, it doesn't make sense), so we only provide that default when
152 # client cert auth is disabled.
153 config.cacert = mkIf config.disableAuthentication (mkDefault null);
158 services.ghostunnel.servers.${name}: At least one access control flag is required.
160 - services.ghostunnel.servers.${name}.disableAuthentication
161 - services.ghostunnel.servers.${name}.allowAll
162 - services.ghostunnel.servers.${name}.allowCN
163 - services.ghostunnel.servers.${name}.allowOU
164 - services.ghostunnel.servers.${name}.allowDNS
165 - services.ghostunnel.servers.${name}.allowURI
167 assertion = config.disableAuthentication
169 || config.allowCN != []
170 || config.allowOU != []
171 || config.allowDNS != []
172 || config.allowURI != []
177 systemd.services."ghostunnel-server-${name}" = {
178 after = [ "network.target" ];
179 wants = [ "network.target" ];
180 wantedBy = [ "multi-user.target" ];
183 AmbientCapabilities = ["CAP_NET_BIND_SERVICE"];
185 LoadCredential = optional (config.keystore != null) "keystore:${config.keystore}"
186 ++ optional (config.cert != null) "cert:${config.cert}"
187 ++ optional (config.key != null) "key:${config.key}"
188 ++ optional (config.cacert != null) "cacert:${config.cacert}";
190 script = concatStringsSep " " (
191 [ "${mainCfg.package}/bin/ghostunnel" ]
192 ++ optional (config.keystore != null) "--keystore=$CREDENTIALS_DIRECTORY/keystore"
193 ++ optional (config.cert != null) "--cert=$CREDENTIALS_DIRECTORY/cert"
194 ++ optional (config.key != null) "--key=$CREDENTIALS_DIRECTORY/key"
195 ++ optional (config.cacert != null) "--cacert=$CREDENTIALS_DIRECTORY/cacert"
198 "--listen ${config.listen}"
199 "--target ${config.target}"
200 ] ++ optional config.allowAll "--allow-all"
201 ++ map (v: "--allow-cn=${escapeShellArg v}") config.allowCN
202 ++ map (v: "--allow-ou=${escapeShellArg v}") config.allowOU
203 ++ map (v: "--allow-dns=${escapeShellArg v}") config.allowDNS
204 ++ map (v: "--allow-uri=${escapeShellArg v}") config.allowURI
205 ++ optional config.disableAuthentication "--disable-authentication"
206 ++ optional config.unsafeTarget "--unsafe-target"
207 ++ [ config.extraArguments ]
217 services.ghostunnel.enable = mkEnableOption "ghostunnel";
219 services.ghostunnel.package = mkPackageOption pkgs "ghostunnel" { };
221 services.ghostunnel.servers = mkOption {
223 Server mode ghostunnels (TLS listener -> plain TCP/UNIX target)
225 type = types.attrsOf (types.submodule module);
230 config = mkIf mainCfg.enable {
231 assertions = lib.mkMerge (map (v: v.atRoot.assertions) (attrValues mainCfg.servers));
232 systemd = lib.mkMerge (map (v: v.atRoot.systemd) (attrValues mainCfg.servers));
235 meta.maintainers = with lib.maintainers; [