Loading nixos/tests/all-tests.nix +1 −0 Original line number Diff line number Diff line Loading @@ -1477,6 +1477,7 @@ in smokeping = runTest ./smokeping.nix; snapcast = runTest ./snapcast.nix; snapper = runTest ./snapper.nix; snid = runTest ./snid.nix; snipe-it = runTest ./web-apps/snipe-it.nix; snips-sh = runTest ./snips-sh.nix; snmpd = runTest ./snmpd.nix; Loading nixos/tests/snid.nix 0 → 100644 +31 −0 Original line number Diff line number Diff line { lib, ... }: { _class = "nixosTest"; name = "snid"; nodes = { machine = { pkgs, ... }: { system.services.snid = { imports = [ pkgs.snid.services.default ]; snid = { listen = [ "tcp:8443" ]; mode = "tcp"; backendCidrs = [ "127.0.0.0/8" ]; }; }; networking.firewall.allowedTCPPorts = [ 8443 ]; }; }; testScript = '' start_all() machine.wait_for_unit("multi-user.target") machine.wait_for_unit("snid.service") machine.wait_for_open_port(8443) ''; meta.maintainers = with lib.maintainers; [ tomfitzhenry ]; } pkgs/by-name/sn/snid/package.nix +9 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ lib, buildGoModule, fetchFromGitHub, nixosTests, }: buildGoModule (finalAttrs: { Loading @@ -17,6 +18,14 @@ buildGoModule (finalAttrs: { vendorHash = "sha256-cVarG6Tx4yWpZE5BLZsMtLV9LF1lsiFfIXxhYiNjQlY="; passthru = { tests.nixos = nixosTests.snid; services.default = { imports = [ (lib.modules.importApply ./service.nix { }) ]; snid.package = finalAttrs.finalPackage; }; }; meta = { description = "Zero config TLS proxy server that uses SNI"; homepage = "https://github.com/AGWA/snid"; Loading pkgs/by-name/sn/snid/service.nix 0 → 100644 +173 −0 Original line number Diff line number Diff line # Non-module dependencies (`importApply`) { }: # Service module { lib, config, options, ... }: let inherit (lib) concatMap getExe mkOption optional types ; cfg = config.snid; in { # https://nixos.org/manual/nixos/unstable/#modular-services _class = "service"; options = { snid = { package = mkOption { description = "Package to use for snid."; defaultText = "The snid package that provided this module."; type = types.package; }; listen = mkOption { description = '' Addresses to listen on, in go-listener syntax. Examples: `"tcp:443"`, `"tcp:0.0.0.0:443"`, `"tcp:192.0.2.4:443"`. ''; type = types.listOf types.str; example = [ "tcp:0.0.0.0:443" ]; }; mode = mkOption { description = '' Proxy mode. One of `nat46`, `tcp`, or `unix`. ''; type = types.enum [ "nat46" "tcp" "unix" ]; }; defaultHostname = mkOption { description = '' Hostname to use if a client does not include the SNI extension. If null, SNI-less connections will be terminated with a TLS alert. ''; type = types.nullOr types.str; default = null; }; nat46Prefix = mkOption { description = '' IPv6 prefix for the source address when connecting to the backend in NAT46 mode. The client's IPv4 address is placed in the lower 4 bytes. Note: this prefix must be routed to the local host, e.g. ``` ip route add local 64:ff9b:1::/96 dev lo ``` ''; type = types.nullOr types.str; default = null; example = "64:ff9b:1::"; }; backendCidrs = mkOption { description = '' Subnets to which connections may be forwarded. Connections to addresses outside these subnets are rejected. Used in `nat46` and `tcp` modes. ''; type = types.listOf types.str; default = [ ]; example = [ "2001:db8::/64" "192.0.2.0/24" ]; }; backendPort = mkOption { description = '' Port number to connect to on the backend in TCP mode. If null, snid uses the same port as the inbound connection. ''; type = types.nullOr types.port; default = null; }; unixDirectory = mkOption { description = '' Path to the directory containing UNIX domain sockets, used in `unix` mode. ''; type = types.nullOr types.path; default = null; }; proxyProto = mkOption { description = '' Use PROXY protocol v2 to convey the client IP address to the backend. Applicable in `tcp` and `unix` modes. ''; type = types.bool; default = false; }; }; }; config = { assertions = [ { assertion = cfg.mode == "nat46" -> cfg.nat46Prefix != null; message = "snid: `nat46Prefix` must be set when `mode` is `nat46`."; } { assertion = cfg.mode == "nat46" -> cfg.backendCidrs != [ ]; message = "snid: `backendCidrs` must be set when `mode` is `nat46`."; } { assertion = cfg.mode == "tcp" -> cfg.backendCidrs != [ ]; message = "snid: `backendCidrs` must be set when `mode` is `tcp`."; } { assertion = cfg.mode == "unix" -> cfg.unixDirectory != null; message = "snid: `unixDirectory` must be set when `mode` is `unix`."; } ]; process.argv = [ (getExe cfg.package) "-mode" cfg.mode ] ++ concatMap (l: [ "-listen" l ]) cfg.listen ++ concatMap (c: [ "-backend-cidr" c ]) cfg.backendCidrs ++ optional (cfg.defaultHostname != null) "-default-hostname=${cfg.defaultHostname}" ++ optional (cfg.nat46Prefix != null) "-nat46-prefix=${cfg.nat46Prefix}" ++ optional (cfg.backendPort != null) "-backend-port=${toString cfg.backendPort}" ++ optional (cfg.unixDirectory != null) "-unix-directory=${cfg.unixDirectory}" ++ optional cfg.proxyProto "-proxy-proto"; } // lib.optionalAttrs (options ? systemd) { systemd.service = { after = [ "network.target" ]; wants = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Restart = "on-failure"; DynamicUser = true; AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; }; }; }; } Loading
nixos/tests/all-tests.nix +1 −0 Original line number Diff line number Diff line Loading @@ -1477,6 +1477,7 @@ in smokeping = runTest ./smokeping.nix; snapcast = runTest ./snapcast.nix; snapper = runTest ./snapper.nix; snid = runTest ./snid.nix; snipe-it = runTest ./web-apps/snipe-it.nix; snips-sh = runTest ./snips-sh.nix; snmpd = runTest ./snmpd.nix; Loading
nixos/tests/snid.nix 0 → 100644 +31 −0 Original line number Diff line number Diff line { lib, ... }: { _class = "nixosTest"; name = "snid"; nodes = { machine = { pkgs, ... }: { system.services.snid = { imports = [ pkgs.snid.services.default ]; snid = { listen = [ "tcp:8443" ]; mode = "tcp"; backendCidrs = [ "127.0.0.0/8" ]; }; }; networking.firewall.allowedTCPPorts = [ 8443 ]; }; }; testScript = '' start_all() machine.wait_for_unit("multi-user.target") machine.wait_for_unit("snid.service") machine.wait_for_open_port(8443) ''; meta.maintainers = with lib.maintainers; [ tomfitzhenry ]; }
pkgs/by-name/sn/snid/package.nix +9 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ lib, buildGoModule, fetchFromGitHub, nixosTests, }: buildGoModule (finalAttrs: { Loading @@ -17,6 +18,14 @@ buildGoModule (finalAttrs: { vendorHash = "sha256-cVarG6Tx4yWpZE5BLZsMtLV9LF1lsiFfIXxhYiNjQlY="; passthru = { tests.nixos = nixosTests.snid; services.default = { imports = [ (lib.modules.importApply ./service.nix { }) ]; snid.package = finalAttrs.finalPackage; }; }; meta = { description = "Zero config TLS proxy server that uses SNI"; homepage = "https://github.com/AGWA/snid"; Loading
pkgs/by-name/sn/snid/service.nix 0 → 100644 +173 −0 Original line number Diff line number Diff line # Non-module dependencies (`importApply`) { }: # Service module { lib, config, options, ... }: let inherit (lib) concatMap getExe mkOption optional types ; cfg = config.snid; in { # https://nixos.org/manual/nixos/unstable/#modular-services _class = "service"; options = { snid = { package = mkOption { description = "Package to use for snid."; defaultText = "The snid package that provided this module."; type = types.package; }; listen = mkOption { description = '' Addresses to listen on, in go-listener syntax. Examples: `"tcp:443"`, `"tcp:0.0.0.0:443"`, `"tcp:192.0.2.4:443"`. ''; type = types.listOf types.str; example = [ "tcp:0.0.0.0:443" ]; }; mode = mkOption { description = '' Proxy mode. One of `nat46`, `tcp`, or `unix`. ''; type = types.enum [ "nat46" "tcp" "unix" ]; }; defaultHostname = mkOption { description = '' Hostname to use if a client does not include the SNI extension. If null, SNI-less connections will be terminated with a TLS alert. ''; type = types.nullOr types.str; default = null; }; nat46Prefix = mkOption { description = '' IPv6 prefix for the source address when connecting to the backend in NAT46 mode. The client's IPv4 address is placed in the lower 4 bytes. Note: this prefix must be routed to the local host, e.g. ``` ip route add local 64:ff9b:1::/96 dev lo ``` ''; type = types.nullOr types.str; default = null; example = "64:ff9b:1::"; }; backendCidrs = mkOption { description = '' Subnets to which connections may be forwarded. Connections to addresses outside these subnets are rejected. Used in `nat46` and `tcp` modes. ''; type = types.listOf types.str; default = [ ]; example = [ "2001:db8::/64" "192.0.2.0/24" ]; }; backendPort = mkOption { description = '' Port number to connect to on the backend in TCP mode. If null, snid uses the same port as the inbound connection. ''; type = types.nullOr types.port; default = null; }; unixDirectory = mkOption { description = '' Path to the directory containing UNIX domain sockets, used in `unix` mode. ''; type = types.nullOr types.path; default = null; }; proxyProto = mkOption { description = '' Use PROXY protocol v2 to convey the client IP address to the backend. Applicable in `tcp` and `unix` modes. ''; type = types.bool; default = false; }; }; }; config = { assertions = [ { assertion = cfg.mode == "nat46" -> cfg.nat46Prefix != null; message = "snid: `nat46Prefix` must be set when `mode` is `nat46`."; } { assertion = cfg.mode == "nat46" -> cfg.backendCidrs != [ ]; message = "snid: `backendCidrs` must be set when `mode` is `nat46`."; } { assertion = cfg.mode == "tcp" -> cfg.backendCidrs != [ ]; message = "snid: `backendCidrs` must be set when `mode` is `tcp`."; } { assertion = cfg.mode == "unix" -> cfg.unixDirectory != null; message = "snid: `unixDirectory` must be set when `mode` is `unix`."; } ]; process.argv = [ (getExe cfg.package) "-mode" cfg.mode ] ++ concatMap (l: [ "-listen" l ]) cfg.listen ++ concatMap (c: [ "-backend-cidr" c ]) cfg.backendCidrs ++ optional (cfg.defaultHostname != null) "-default-hostname=${cfg.defaultHostname}" ++ optional (cfg.nat46Prefix != null) "-nat46-prefix=${cfg.nat46Prefix}" ++ optional (cfg.backendPort != null) "-backend-port=${toString cfg.backendPort}" ++ optional (cfg.unixDirectory != null) "-unix-directory=${cfg.unixDirectory}" ++ optional cfg.proxyProto "-proxy-proto"; } // lib.optionalAttrs (options ? systemd) { systemd.service = { after = [ "network.target" ]; wants = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Restart = "on-failure"; DynamicUser = true; AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; }; }; }; }