wstunnel: reformat with nixfmt
This commit is contained in:
parent
6cb5757dce
commit
6cac9e409c
@ -1,7 +1,8 @@
|
|||||||
{ config
|
{
|
||||||
, lib
|
config,
|
||||||
, pkgs
|
lib,
|
||||||
, ...
|
pkgs,
|
||||||
|
...
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
@ -29,10 +30,9 @@ let
|
|||||||
|
|
||||||
package = lib.mkPackageOption pkgs "wstunnel" { };
|
package = lib.mkPackageOption pkgs "wstunnel" { };
|
||||||
|
|
||||||
autoStart =
|
autoStart = lib.mkEnableOption "starting this wstunnel instance automatically" // {
|
||||||
lib.mkEnableOption "starting this wstunnel instance automatically" // {
|
default = true;
|
||||||
default = true;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
extraArgs = lib.mkOption {
|
extraArgs = lib.mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
@ -75,192 +75,198 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
serverSubmodule = { config, ... }: {
|
serverSubmodule =
|
||||||
options = commonOptions // {
|
{ config, ... }:
|
||||||
listen = lib.mkOption {
|
{
|
||||||
description = ''
|
options = commonOptions // {
|
||||||
Address and port to listen on.
|
listen = lib.mkOption {
|
||||||
Setting the port to a value below 1024 will also give the process
|
description = ''
|
||||||
the required `CAP_NET_BIND_SERVICE` capability.
|
Address and port to listen on.
|
||||||
'';
|
Setting the port to a value below 1024 will also give the process
|
||||||
type = lib.types.submodule hostPortSubmodule;
|
the required `CAP_NET_BIND_SERVICE` capability.
|
||||||
default = {
|
'';
|
||||||
host = "0.0.0.0";
|
type = lib.types.submodule hostPortSubmodule;
|
||||||
port = if config.enableHTTPS then 443 else 80;
|
default = {
|
||||||
};
|
|
||||||
defaultText = lib.literalExpression ''
|
|
||||||
{
|
|
||||||
host = "0.0.0.0";
|
host = "0.0.0.0";
|
||||||
port = if enableHTTPS then 443 else 80;
|
port = if config.enableHTTPS then 443 else 80;
|
||||||
}
|
};
|
||||||
'';
|
defaultText = lib.literalExpression ''
|
||||||
};
|
{
|
||||||
|
host = "0.0.0.0";
|
||||||
|
port = if enableHTTPS then 443 else 80;
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
restrictTo = lib.mkOption {
|
restrictTo = lib.mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
Accepted traffic will be forwarded only to this service.
|
Accepted traffic will be forwarded only to this service.
|
||||||
'';
|
'';
|
||||||
type = lib.types.listOf (lib.types.submodule hostPortSubmodule);
|
type = lib.types.listOf (lib.types.submodule hostPortSubmodule);
|
||||||
default = [ ];
|
default = [ ];
|
||||||
example = [{
|
example = [
|
||||||
host = "127.0.0.1";
|
{
|
||||||
port = 51820;
|
host = "127.0.0.1";
|
||||||
}];
|
port = 51820;
|
||||||
};
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
enableHTTPS = lib.mkOption {
|
enableHTTPS = lib.mkOption {
|
||||||
description = "Use HTTPS for the tunnel server.";
|
description = "Use HTTPS for the tunnel server.";
|
||||||
type = lib.types.bool;
|
type = lib.types.bool;
|
||||||
default = true;
|
default = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
tlsCertificate = lib.mkOption {
|
tlsCertificate = lib.mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
TLS certificate to use instead of the hardcoded one in case of HTTPS connections.
|
TLS certificate to use instead of the hardcoded one in case of HTTPS connections.
|
||||||
Use together with `tlsKey`.
|
Use together with `tlsKey`.
|
||||||
'';
|
'';
|
||||||
type = lib.types.nullOr lib.types.path;
|
type = lib.types.nullOr lib.types.path;
|
||||||
default = null;
|
default = null;
|
||||||
example = "/var/lib/secrets/cert.pem";
|
example = "/var/lib/secrets/cert.pem";
|
||||||
};
|
};
|
||||||
|
|
||||||
tlsKey = lib.mkOption {
|
tlsKey = lib.mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
TLS key to use instead of the hardcoded on in case of HTTPS connections.
|
TLS key to use instead of the hardcoded on in case of HTTPS connections.
|
||||||
Use together with `tlsCertificate`.
|
Use together with `tlsCertificate`.
|
||||||
'';
|
'';
|
||||||
type = lib.types.nullOr lib.types.path;
|
type = lib.types.nullOr lib.types.path;
|
||||||
default = null;
|
default = null;
|
||||||
example = "/var/lib/secrets/key.pem";
|
example = "/var/lib/secrets/key.pem";
|
||||||
};
|
};
|
||||||
|
|
||||||
useACMEHost = lib.mkOption {
|
useACMEHost = lib.mkOption {
|
||||||
description = ''
|
description = ''
|
||||||
Use a certificate generated by the NixOS ACME module for the given host.
|
Use a certificate generated by the NixOS ACME module for the given host.
|
||||||
Note that this will not generate a new certificate - you will need to do so with `security.acme.certs`.
|
Note that this will not generate a new certificate - you will need to do so with `security.acme.certs`.
|
||||||
'';
|
'';
|
||||||
type = lib.types.nullOr lib.types.str;
|
type = lib.types.nullOr lib.types.str;
|
||||||
default = null;
|
default = null;
|
||||||
example = "example.com";
|
example = "example.com";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
clientSubmodule = { config, ... }: {
|
clientSubmodule =
|
||||||
options = commonOptions // {
|
{ config, ... }:
|
||||||
connectTo = lib.mkOption {
|
{
|
||||||
description = "Server address and port to connect to.";
|
options = commonOptions // {
|
||||||
type = lib.types.str;
|
connectTo = lib.mkOption {
|
||||||
example = "https://wstunnel.server.com:8443";
|
description = "Server address and port to connect to.";
|
||||||
};
|
type = lib.types.str;
|
||||||
|
example = "https://wstunnel.server.com:8443";
|
||||||
localToRemote = lib.mkOption {
|
};
|
||||||
description = ''Listen on local and forwards traffic from remote.'';
|
|
||||||
type = lib.types.listOf (lib.types.str);
|
localToRemote = lib.mkOption {
|
||||||
default = [ ];
|
description = ''Listen on local and forwards traffic from remote.'';
|
||||||
example = [
|
type = lib.types.listOf (lib.types.str);
|
||||||
"tcp://1212:google.com:443"
|
default = [ ];
|
||||||
"unix:///tmp/wstunnel.sock:g.com:443"
|
example = [
|
||||||
];
|
"tcp://1212:google.com:443"
|
||||||
};
|
"unix:///tmp/wstunnel.sock:g.com:443"
|
||||||
|
];
|
||||||
remoteToLocal = lib.mkOption {
|
};
|
||||||
description = "Listen on remote and forwards traffic from local. Only tcp is supported";
|
|
||||||
type = lib.types.listOf lib.types.str;
|
remoteToLocal = lib.mkOption {
|
||||||
default = [ ];
|
description = "Listen on remote and forwards traffic from local. Only tcp is supported";
|
||||||
example = [
|
type = lib.types.listOf lib.types.str;
|
||||||
"tcp://1212:google.com:443"
|
default = [ ];
|
||||||
"unix://wstunnel.sock:g.com:443"
|
example = [
|
||||||
];
|
"tcp://1212:google.com:443"
|
||||||
};
|
"unix://wstunnel.sock:g.com:443"
|
||||||
|
];
|
||||||
addNetBind = lib.mkEnableOption "Whether add CAP_NET_BIND_SERVICE to the tunnel service, this should be enabled if you want to bind port < 1024";
|
};
|
||||||
|
|
||||||
httpProxy = lib.mkOption {
|
addNetBind = lib.mkEnableOption "Whether add CAP_NET_BIND_SERVICE to the tunnel service, this should be enabled if you want to bind port < 1024";
|
||||||
description = ''
|
|
||||||
Proxy to use to connect to the wstunnel server (`USER:PASS@HOST:PORT`).
|
httpProxy = lib.mkOption {
|
||||||
|
description = ''
|
||||||
::: {.warning}
|
Proxy to use to connect to the wstunnel server (`USER:PASS@HOST:PORT`).
|
||||||
Passwords specified here will be world-readable in the Nix store!
|
|
||||||
To pass a password to the service, point the `environmentFile` option
|
::: {.warning}
|
||||||
to a file containing `PROXY_PASSWORD=<your-password-here>` and set
|
Passwords specified here will be world-readable in the Nix store!
|
||||||
this option to `<user>:$PROXY_PASSWORD@<host>:<port>`.
|
To pass a password to the service, point the `environmentFile` option
|
||||||
Note however that this will also locally leak the passwords at
|
to a file containing `PROXY_PASSWORD=<your-password-here>` and set
|
||||||
runtime via e.g. /proc/<pid>/cmdline.
|
this option to `<user>:$PROXY_PASSWORD@<host>:<port>`.
|
||||||
:::
|
Note however that this will also locally leak the passwords at
|
||||||
'';
|
runtime via e.g. /proc/<pid>/cmdline.
|
||||||
type = lib.types.nullOr lib.types.str;
|
:::
|
||||||
default = null;
|
'';
|
||||||
};
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = null;
|
||||||
soMark = lib.mkOption {
|
};
|
||||||
description = ''
|
|
||||||
Mark network packets with the SO_MARK sockoption with the specified value.
|
soMark = lib.mkOption {
|
||||||
Setting this option will also enable the required `CAP_NET_ADMIN` capability
|
description = ''
|
||||||
for the systemd service.
|
Mark network packets with the SO_MARK sockoption with the specified value.
|
||||||
'';
|
Setting this option will also enable the required `CAP_NET_ADMIN` capability
|
||||||
type = lib.types.nullOr lib.types.ints.unsigned;
|
for the systemd service.
|
||||||
default = null;
|
'';
|
||||||
};
|
type = lib.types.nullOr lib.types.ints.unsigned;
|
||||||
|
default = null;
|
||||||
upgradePathPrefix = lib.mkOption {
|
};
|
||||||
description = ''
|
|
||||||
Use a specific HTTP path prefix that will show up in the upgrade
|
upgradePathPrefix = lib.mkOption {
|
||||||
request to the `wstunnel` server.
|
description = ''
|
||||||
Useful when running `wstunnel` behind a reverse proxy.
|
Use a specific HTTP path prefix that will show up in the upgrade
|
||||||
'';
|
request to the `wstunnel` server.
|
||||||
type = lib.types.nullOr lib.types.str;
|
Useful when running `wstunnel` behind a reverse proxy.
|
||||||
default = null;
|
'';
|
||||||
example = "wstunnel";
|
type = lib.types.nullOr lib.types.str;
|
||||||
};
|
default = null;
|
||||||
|
example = "wstunnel";
|
||||||
tlsSNI = lib.mkOption {
|
};
|
||||||
description = "Use this as the SNI while connecting via TLS. Useful for circumventing hostname-based firewalls.";
|
|
||||||
type = lib.types.nullOr lib.types.str;
|
tlsSNI = lib.mkOption {
|
||||||
default = null;
|
description = "Use this as the SNI while connecting via TLS. Useful for circumventing hostname-based firewalls.";
|
||||||
};
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = null;
|
||||||
tlsVerifyCertificate = lib.mkOption {
|
};
|
||||||
description = "Whether to verify the TLS certificate of the server. It might be useful to set this to `false` when working with the `tlsSNI` option.";
|
|
||||||
type = lib.types.bool;
|
tlsVerifyCertificate = lib.mkOption {
|
||||||
default = true;
|
description = "Whether to verify the TLS certificate of the server. It might be useful to set this to `false` when working with the `tlsSNI` option.";
|
||||||
};
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
# The original argument name `websocketPingFrequency` is a misnomer, as the frequency is the inverse of the interval.
|
};
|
||||||
websocketPingInterval = lib.mkOption {
|
|
||||||
description = "Frequency at which the client will send websocket ping to the server.";
|
# The original argument name `websocketPingFrequency` is a misnomer, as the frequency is the inverse of the interval.
|
||||||
type = lib.types.nullOr lib.types.ints.unsigned;
|
websocketPingInterval = lib.mkOption {
|
||||||
default = null;
|
description = "Frequency at which the client will send websocket ping to the server.";
|
||||||
};
|
type = lib.types.nullOr lib.types.ints.unsigned;
|
||||||
|
default = null;
|
||||||
upgradeCredentials = lib.mkOption {
|
};
|
||||||
description = ''
|
|
||||||
Use these credentials to authenticate during the HTTP upgrade request
|
upgradeCredentials = lib.mkOption {
|
||||||
(Basic authorization type, `USER:[PASS]`).
|
description = ''
|
||||||
|
Use these credentials to authenticate during the HTTP upgrade request
|
||||||
::: {.warning}
|
(Basic authorization type, `USER:[PASS]`).
|
||||||
Passwords specified here will be world-readable in the Nix store!
|
|
||||||
To pass a password to the service, point the `environmentFile` option
|
::: {.warning}
|
||||||
to a file containing `HTTP_PASSWORD=<your-password-here>` and set this
|
Passwords specified here will be world-readable in the Nix store!
|
||||||
option to `<user>:$HTTP_PASSWORD`.
|
To pass a password to the service, point the `environmentFile` option
|
||||||
Note however that this will also locally leak the passwords at runtime
|
to a file containing `HTTP_PASSWORD=<your-password-here>` and set this
|
||||||
via e.g. /proc/<pid>/cmdline.
|
option to `<user>:$HTTP_PASSWORD`.
|
||||||
:::
|
Note however that this will also locally leak the passwords at runtime
|
||||||
'';
|
via e.g. /proc/<pid>/cmdline.
|
||||||
type = lib.types.nullOr lib.types.str;
|
:::
|
||||||
default = null;
|
'';
|
||||||
};
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = null;
|
||||||
customHeaders = lib.mkOption {
|
};
|
||||||
description = "Custom HTTP headers to send during the upgrade request.";
|
|
||||||
type = lib.types.attrsOf lib.types.str;
|
customHeaders = lib.mkOption {
|
||||||
default = { };
|
description = "Custom HTTP headers to send during the upgrade request.";
|
||||||
example = {
|
type = lib.types.attrsOf lib.types.str;
|
||||||
"X-Some-Header" = "some-value";
|
default = { };
|
||||||
|
example = {
|
||||||
|
"X-Some-Header" = "some-value";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
generateServerUnit = name: serverCfg: {
|
generateServerUnit = name: serverCfg: {
|
||||||
name = "wstunnel-server-${name}";
|
name = "wstunnel-server-${name}";
|
||||||
@ -270,22 +276,25 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
description = "wstunnel server - ${name}";
|
description = "wstunnel server - ${name}";
|
||||||
requires = [ "network.target" "network-online.target" ];
|
requires = [
|
||||||
after = [ "network.target" "network-online.target" ];
|
"network.target"
|
||||||
|
"network-online.target"
|
||||||
|
];
|
||||||
|
after = [
|
||||||
|
"network.target"
|
||||||
|
"network-online.target"
|
||||||
|
];
|
||||||
wantedBy = lib.optional serverCfg.autoStart "multi-user.target";
|
wantedBy = lib.optional serverCfg.autoStart "multi-user.target";
|
||||||
|
|
||||||
environment.RUST_LOG = serverCfg.loggingLevel;
|
environment.RUST_LOG = serverCfg.loggingLevel;
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "exec";
|
Type = "exec";
|
||||||
EnvironmentFile =
|
EnvironmentFile = lib.optional (serverCfg.environmentFile != null) serverCfg.environmentFile;
|
||||||
lib.optional (serverCfg.environmentFile != null) serverCfg.environmentFile;
|
|
||||||
DynamicUser = true;
|
DynamicUser = true;
|
||||||
SupplementaryGroups =
|
SupplementaryGroups = lib.optional (serverCfg.useACMEHost != null) certConfig.group;
|
||||||
lib.optional (serverCfg.useACMEHost != null) certConfig.group;
|
|
||||||
PrivateTmp = true;
|
PrivateTmp = true;
|
||||||
AmbientCapabilities =
|
AmbientCapabilities = lib.optionals (serverCfg.listen.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
|
||||||
lib.optionals (serverCfg.listen.port < 1024) [ "CAP_NET_BIND_SERVICE" ];
|
|
||||||
NoNewPrivileges = true;
|
NoNewPrivileges = true;
|
||||||
RestrictNamespaces = "uts ipc pid user cgroup";
|
RestrictNamespaces = "uts ipc pid user cgroup";
|
||||||
ProtectSystem = "strict";
|
ProtectSystem = "strict";
|
||||||
@ -305,19 +314,16 @@ let
|
|||||||
script = with serverCfg; ''
|
script = with serverCfg; ''
|
||||||
${lib.getExe package} \
|
${lib.getExe package} \
|
||||||
server \
|
server \
|
||||||
${lib.cli.toGNUCommandLineShell { } (
|
${
|
||||||
lib.recursiveUpdate
|
lib.cli.toGNUCommandLineShell { } (
|
||||||
{
|
lib.recursiveUpdate {
|
||||||
restrict-to = map hostPortToString restrictTo;
|
restrict-to = map hostPortToString restrictTo;
|
||||||
tls-certificate = if useACMEHost != null
|
tls-certificate =
|
||||||
then "${certConfig.directory}/fullchain.pem"
|
if useACMEHost != null then "${certConfig.directory}/fullchain.pem" else "${tlsCertificate}";
|
||||||
else "${tlsCertificate}";
|
tls-private-key = if useACMEHost != null then "${certConfig.directory}/key.pem" else "${tlsKey}";
|
||||||
tls-private-key = if useACMEHost != null
|
} extraArgs
|
||||||
then "${certConfig.directory}/key.pem"
|
)
|
||||||
else "${tlsKey}";
|
} \
|
||||||
}
|
|
||||||
extraArgs
|
|
||||||
)} \
|
|
||||||
${lib.escapeShellArg "${if enableHTTPS then "wss" else "ws"}://${hostPortToString listen}"}
|
${lib.escapeShellArg "${if enableHTTPS then "wss" else "ws"}://${hostPortToString listen}"}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -327,21 +333,26 @@ let
|
|||||||
name = "wstunnel-client-${name}";
|
name = "wstunnel-client-${name}";
|
||||||
value = {
|
value = {
|
||||||
description = "wstunnel client - ${name}";
|
description = "wstunnel client - ${name}";
|
||||||
requires = [ "network.target" "network-online.target" ];
|
requires = [
|
||||||
after = [ "network.target" "network-online.target" ];
|
"network.target"
|
||||||
|
"network-online.target"
|
||||||
|
];
|
||||||
|
after = [
|
||||||
|
"network.target"
|
||||||
|
"network-online.target"
|
||||||
|
];
|
||||||
wantedBy = lib.optional clientCfg.autoStart "multi-user.target";
|
wantedBy = lib.optional clientCfg.autoStart "multi-user.target";
|
||||||
|
|
||||||
environment.RUST_LOG = clientCfg.loggingLevel;
|
environment.RUST_LOG = clientCfg.loggingLevel;
|
||||||
|
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
Type = "exec";
|
Type = "exec";
|
||||||
EnvironmentFile =
|
EnvironmentFile = lib.optional (clientCfg.environmentFile != null) clientCfg.environmentFile;
|
||||||
lib.optional (clientCfg.environmentFile != null) clientCfg.environmentFile;
|
|
||||||
DynamicUser = true;
|
DynamicUser = true;
|
||||||
PrivateTmp = true;
|
PrivateTmp = true;
|
||||||
AmbientCapabilities =
|
AmbientCapabilities =
|
||||||
(lib.optionals clientCfg.addNetBind [ "CAP_NET_BIND_SERVICE" ]) ++
|
(lib.optionals clientCfg.addNetBind [ "CAP_NET_BIND_SERVICE" ])
|
||||||
(lib.optionals (clientCfg.soMark != null) [ "CAP_NET_ADMIN" ]);
|
++ (lib.optionals (clientCfg.soMark != null) [ "CAP_NET_ADMIN" ]);
|
||||||
NoNewPrivileges = true;
|
NoNewPrivileges = true;
|
||||||
RestrictNamespaces = "uts ipc pid user cgroup";
|
RestrictNamespaces = "uts ipc pid user cgroup";
|
||||||
ProtectSystem = "strict";
|
ProtectSystem = "strict";
|
||||||
@ -361,22 +372,22 @@ let
|
|||||||
script = with clientCfg; ''
|
script = with clientCfg; ''
|
||||||
${lib.getExe package} \
|
${lib.getExe package} \
|
||||||
client \
|
client \
|
||||||
${lib.cli.toGNUCommandLineShell { } (
|
${
|
||||||
lib.recursiveUpdate
|
lib.cli.toGNUCommandLineShell { } (
|
||||||
{
|
lib.recursiveUpdate {
|
||||||
local-to-remote = localToRemote;
|
local-to-remote = localToRemote;
|
||||||
remote-to-local = remoteToLocal;
|
remote-to-local = remoteToLocal;
|
||||||
http-headers = lib.mapAttrsToList (n: v: "${n}:${v}") customHeaders;
|
http-headers = lib.mapAttrsToList (n: v: "${n}:${v}") customHeaders;
|
||||||
http-proxy = httpProxy;
|
http-proxy = httpProxy;
|
||||||
socket-so-mark = soMark;
|
socket-so-mark = soMark;
|
||||||
http-upgrade-path-prefix = upgradePathPrefix;
|
http-upgrade-path-prefix = upgradePathPrefix;
|
||||||
tls-sni-override = tlsSNI;
|
tls-sni-override = tlsSNI;
|
||||||
tls-verify-certificate = tlsVerifyCertificate;
|
tls-verify-certificate = tlsVerifyCertificate;
|
||||||
websocket-ping-frequency-sec = websocketPingInterval;
|
websocket-ping-frequency-sec = websocketPingInterval;
|
||||||
http-upgrade-credentials = upgradeCredentials;
|
http-upgrade-credentials = upgradeCredentials;
|
||||||
}
|
} extraArgs
|
||||||
extraArgs
|
)
|
||||||
)} \
|
} \
|
||||||
${lib.escapeShellArg connectTo}
|
${lib.escapeShellArg connectTo}
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -399,10 +410,12 @@ in
|
|||||||
enableHTTPS = true;
|
enableHTTPS = true;
|
||||||
tlsCertificate = "/var/lib/secrets/fullchain.pem";
|
tlsCertificate = "/var/lib/secrets/fullchain.pem";
|
||||||
tlsKey = "/var/lib/secrets/key.pem";
|
tlsKey = "/var/lib/secrets/key.pem";
|
||||||
restrictTo = [{
|
restrictTo = [
|
||||||
host = "127.0.0.1";
|
{
|
||||||
port = 51820;
|
host = "127.0.0.1";
|
||||||
}];
|
port = 51820;
|
||||||
|
}
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -429,40 +442,39 @@ in
|
|||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
systemd.services =
|
systemd.services =
|
||||||
(lib.mapAttrs' generateServerUnit (lib.filterAttrs (n: v: v.enable) cfg.servers)) //
|
(lib.mapAttrs' generateServerUnit (lib.filterAttrs (n: v: v.enable) cfg.servers))
|
||||||
(lib.mapAttrs' generateClientUnit (lib.filterAttrs (n: v: v.enable) cfg.clients));
|
// (lib.mapAttrs' generateClientUnit (lib.filterAttrs (n: v: v.enable) cfg.clients));
|
||||||
|
|
||||||
assertions =
|
assertions =
|
||||||
(lib.mapAttrsToList
|
(lib.mapAttrsToList (name: serverCfg: {
|
||||||
(name: serverCfg: {
|
assertion = !(serverCfg.useACMEHost != null && serverCfg.tlsCertificate != null);
|
||||||
assertion =
|
message = ''
|
||||||
!(serverCfg.useACMEHost != null && serverCfg.tlsCertificate != null);
|
Options services.wstunnel.servers."${name}".useACMEHost and services.wstunnel.servers."${name}".{tlsCertificate, tlsKey} are mutually exclusive.
|
||||||
message = ''
|
'';
|
||||||
Options services.wstunnel.servers."${name}".useACMEHost and services.wstunnel.servers."${name}".{tlsCertificate, tlsKey} are mutually exclusive.
|
}) cfg.servers)
|
||||||
'';
|
++
|
||||||
})
|
|
||||||
cfg.servers) ++
|
|
||||||
|
|
||||||
(lib.mapAttrsToList
|
(lib.mapAttrsToList (name: serverCfg: {
|
||||||
(name: serverCfg: {
|
|
||||||
assertion =
|
assertion =
|
||||||
(serverCfg.tlsCertificate == null && serverCfg.tlsKey == null) ||
|
(serverCfg.tlsCertificate == null && serverCfg.tlsKey == null)
|
||||||
(serverCfg.tlsCertificate != null && serverCfg.tlsKey != null);
|
|| (serverCfg.tlsCertificate != null && serverCfg.tlsKey != null);
|
||||||
message = ''
|
message = ''
|
||||||
services.wstunnel.servers."${name}".tlsCertificate and services.wstunnel.servers."${name}".tlsKey need to be set together.
|
services.wstunnel.servers."${name}".tlsCertificate and services.wstunnel.servers."${name}".tlsKey need to be set together.
|
||||||
'';
|
'';
|
||||||
})
|
}) cfg.servers)
|
||||||
cfg.servers) ++
|
++
|
||||||
|
|
||||||
(lib.mapAttrsToList
|
(lib.mapAttrsToList (name: clientCfg: {
|
||||||
(name: clientCfg: {
|
|
||||||
assertion = !(clientCfg.localToRemote == [ ] && clientCfg.remoteToLocal == [ ]);
|
assertion = !(clientCfg.localToRemote == [ ] && clientCfg.remoteToLocal == [ ]);
|
||||||
message = ''
|
message = ''
|
||||||
Either one of services.wstunnel.clients."${name}".localToRemote or services.wstunnel.clients."${name}".remoteToLocal must be set.
|
Either one of services.wstunnel.clients."${name}".localToRemote or services.wstunnel.clients."${name}".remoteToLocal must be set.
|
||||||
'';
|
'';
|
||||||
})
|
}) cfg.clients);
|
||||||
cfg.clients);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
meta.maintainers = with lib.maintainers; [ alyaeanyx rvdp neverbehave ];
|
meta.maintainers = with lib.maintainers; [
|
||||||
|
alyaeanyx
|
||||||
|
rvdp
|
||||||
|
neverbehave
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -60,37 +60,34 @@ in
|
|||||||
clients.my-client = {
|
clients.my-client = {
|
||||||
autoStart = false;
|
autoStart = false;
|
||||||
connectTo = "wss://${domain}:443";
|
connectTo = "wss://${domain}:443";
|
||||||
localToRemote = [
|
localToRemote = [ "tcp://8080:localhost:2080" ];
|
||||||
"tcp://8080:localhost:2080"
|
remoteToLocal = [ "tcp://2081:localhost:8081" ];
|
||||||
];
|
|
||||||
remoteToLocal = [
|
|
||||||
"tcp://2081:localhost:8081"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
testScript = /* python */ ''
|
testScript = # python
|
||||||
start_all()
|
''
|
||||||
server.wait_for_unit("wstunnel-server-my-server.service")
|
start_all()
|
||||||
client.wait_for_open_port(443, "10.0.0.1")
|
server.wait_for_unit("wstunnel-server-my-server.service")
|
||||||
|
client.wait_for_open_port(443, "10.0.0.1")
|
||||||
|
|
||||||
client.systemctl("start wstunnel-client-my-client.service")
|
client.systemctl("start wstunnel-client-my-client.service")
|
||||||
client.wait_for_unit("wstunnel-client-my-client.service")
|
client.wait_for_unit("wstunnel-client-my-client.service")
|
||||||
|
|
||||||
with subtest("connection from client to server"):
|
with subtest("connection from client to server"):
|
||||||
server.succeed("nc -l 2080 >/tmp/msg &")
|
server.succeed("nc -l 2080 >/tmp/msg &")
|
||||||
client.sleep(1)
|
client.sleep(1)
|
||||||
client.succeed('nc -w1 localhost 8080 <<<"Hello from client"')
|
client.succeed('nc -w1 localhost 8080 <<<"Hello from client"')
|
||||||
server.succeed('grep "Hello from client" /tmp/msg')
|
server.succeed('grep "Hello from client" /tmp/msg')
|
||||||
|
|
||||||
with subtest("connection from server to client"):
|
with subtest("connection from server to client"):
|
||||||
client.succeed("nc -l 8081 >/tmp/msg &")
|
client.succeed("nc -l 8081 >/tmp/msg &")
|
||||||
server.sleep(1)
|
server.sleep(1)
|
||||||
server.succeed('nc -w1 localhost 2081 <<<"Hello from server"')
|
server.succeed('nc -w1 localhost 2081 <<<"Hello from server"')
|
||||||
client.succeed('grep "Hello from server" /tmp/msg')
|
client.succeed('grep "Hello from server" /tmp/msg')
|
||||||
|
|
||||||
client.systemctl("stop wstunnel-client-my-client.service")
|
client.systemctl("stop wstunnel-client-my-client.service")
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
{ lib
|
{
|
||||||
, fetchFromGitHub
|
lib,
|
||||||
, rustPlatform
|
fetchFromGitHub,
|
||||||
, testers
|
rustPlatform,
|
||||||
, wstunnel
|
testers,
|
||||||
, nixosTests
|
wstunnel,
|
||||||
|
nixosTests,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
@ -38,7 +39,10 @@ rustPlatform.buildRustPackage {
|
|||||||
homepage = "https://github.com/erebe/wstunnel";
|
homepage = "https://github.com/erebe/wstunnel";
|
||||||
changelog = "https://github.com/erebe/wstunnel/releases/tag/v${version}";
|
changelog = "https://github.com/erebe/wstunnel/releases/tag/v${version}";
|
||||||
license = lib.licenses.bsd3;
|
license = lib.licenses.bsd3;
|
||||||
maintainers = with lib.maintainers; [ rvdp neverbehave ];
|
maintainers = with lib.maintainers; [
|
||||||
|
rvdp
|
||||||
|
neverbehave
|
||||||
|
];
|
||||||
mainProgram = "wstunnel";
|
mainProgram = "wstunnel";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user