From 70c688cb1f1d3c5a367246a7b59af1523824a274 Mon Sep 17 00:00:00 2001 From: Fabiana Cecin Date: Mon, 20 Apr 2026 12:14:20 -0300 Subject: [PATCH] feat: override ports with values supplied via env vars --- README.md | 17 ++++ tests/factory/test_waku_conf.nim | 99 ++++++++++++++++++- .../conf_builder/waku_conf_builder.nim | 55 ++++++++++- 3 files changed, 169 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8833ae131..37400fe13 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,23 @@ make test/tests/common/test_enr_builder.nim ### Testing against `js-waku` Refer to [js-waku repo](https://github.com/waku-org/js-waku/tree/master/packages/tests) for instructions. +## Port override environment variables + +Every listening port can be overridden with an environment variable. When the +variable is set to a valid `uint16`, it takes precedence over both the default +and any supplied configuration for that port. + +| Port config | Env variable | +| ----------------------- | -------------------------------- | +| `--tcp-port` | `LOGOS_DELIVERY_P2P_TCP_PORT` | +| `--discv5-udp-port` | `LOGOS_DELIVERY_DISCV5_UDP_PORT` | +| `--rest-port` | `LOGOS_DELIVERY_REST_PORT` | +| `--metrics-server-port` | `LOGOS_DELIVERY_METRICS_PORT` | +| `--websocket-port` | `LOGOS_DELIVERY_WEBSOCKET_PORT` | + +The override just replaces the configured port value, so any subsequent transform +such as `--ports-shift` still applies on top. + ## Formatting Nim files are expected to be formatted using the [`nph`](https://github.com/arnetheduck/nph) version present in `vendor/nph`. diff --git a/tests/factory/test_waku_conf.nim b/tests/factory/test_waku_conf.nim index eeacf791b..000766c79 100644 --- a/tests/factory/test_waku_conf.nim +++ b/tests/factory/test_waku_conf.nim @@ -4,7 +4,7 @@ import libp2p/crypto/[crypto, secp], libp2p/multiaddress, nimcrypto/utils, - std/[options, random, sequtils], + std/[net, options, os, random, sequtils], results, testutils/unittests import @@ -346,3 +346,100 @@ suite "Waku Conf Builder - rate limits": ## Then assert res.isOk(), $res.error + +suite "Waku Conf Builder - env port overrides": + proc clearPortEnv() = + for name in [ + EnvP2pTcpPort, EnvDiscv5UdpPort, EnvRestPort, EnvMetricsPort, + EnvWebSocketPort, + ]: + delEnv(name) + + test "non-numeric env is ignored": + clearPortEnv() + putEnv(EnvP2pTcpPort, "notanumber") + defer: + delEnv(EnvP2pTcpPort) + + var builder = WakuConfBuilder.init() + builder.withClusterId(1) + builder.withP2pTcpPort(60000.uint16) + + let conf = builder.build().expect("build should succeed") + + check conf.endpointConf.p2pTcpPort == 60000.Port + + test "out-of-range env is ignored": + clearPortEnv() + putEnv(EnvP2pTcpPort, "999999") + defer: + delEnv(EnvP2pTcpPort) + + var builder = WakuConfBuilder.init() + builder.withClusterId(1) + builder.withP2pTcpPort(60000.uint16) + + let conf = builder.build().expect("build should succeed") + + check conf.endpointConf.p2pTcpPort == 60000.Port + + test "env=0 is accepted": + clearPortEnv() + putEnv(EnvP2pTcpPort, "0") + defer: + delEnv(EnvP2pTcpPort) + + var builder = WakuConfBuilder.init() + builder.withClusterId(1) + builder.withP2pTcpPort(60000.uint16) + + let conf = builder.build().expect("build should succeed") + + check conf.endpointConf.p2pTcpPort == 0.Port + + test "env overrides every configured port": + clearPortEnv() + putEnv(EnvP2pTcpPort, "60001") + putEnv(EnvDiscv5UdpPort, "60002") + putEnv(EnvRestPort, "60003") + putEnv(EnvMetricsPort, "60004") + putEnv(EnvWebSocketPort, "60005") + defer: + clearPortEnv() + + var builder = WakuConfBuilder.init() + builder.withP2pTcpPort(50000.uint16) + builder.discv5Conf.withEnabled(true) + builder.discv5Conf.withUdpPort(50001.uint) + builder.restServerConf.withEnabled(true) + builder.restServerConf.withListenAddress(parseIpAddress("127.0.0.1")) + builder.restServerConf.withPort(50002.uint16) + builder.restServerConf.withRelayCacheCapacity(0.uint32) + builder.metricsServerConf.withEnabled(true) + builder.metricsServerConf.withHttpPort(50003.uint16) + builder.webSocketConf.withEnabled(true) + builder.webSocketConf.withWebSocketPort(50004.uint16) + + let conf = builder.build().expect("build should succeed") + + check conf.endpointConf.p2pTcpPort == 60001.Port + check conf.discv5Conf.get().udpPort == 60002.Port + check conf.restServerConf.get().port == 60003.Port + check conf.metricsServerConf.get().httpPort == 60004.Port + check conf.webSocketConf.get().port == 60005.Port + + test "env override preserves portsShift": + clearPortEnv() + putEnv(EnvP2pTcpPort, "61234") + defer: + delEnv(EnvP2pTcpPort) + + var builder = WakuConfBuilder.init() + builder.withClusterId(1) + builder.withP2pTcpPort(60000.uint16) + builder.withPortsShift(5.uint16) + + let conf = builder.build().expect("build should succeed") + + check conf.endpointConf.p2pTcpPort == 61234.Port + check conf.portsShift == 5.uint16 diff --git a/waku/factory/conf_builder/waku_conf_builder.nim b/waku/factory/conf_builder/waku_conf_builder.nim index 78dbd9eb9..81053a691 100644 --- a/waku/factory/conf_builder/waku_conf_builder.nim +++ b/waku/factory/conf_builder/waku_conf_builder.nim @@ -1,7 +1,7 @@ import libp2p/crypto/crypto, libp2p/multiaddress, - std/[net, options, sequtils], + std/[net, options, os, sequtils, strutils], stint, chronicles, chronos, @@ -34,6 +34,14 @@ logScope: const DefaultMaxConnections* = 150 +## Port override env-var names. +const + EnvP2pTcpPort* = "LOGOS_DELIVERY_P2P_TCP_PORT" + EnvDiscv5UdpPort* = "LOGOS_DELIVERY_DISCV5_UDP_PORT" + EnvRestPort* = "LOGOS_DELIVERY_REST_PORT" + EnvMetricsPort* = "LOGOS_DELIVERY_METRICS_PORT" + EnvWebSocketPort* = "LOGOS_DELIVERY_WEBSOCKET_PORT" + type MaxMessageSizeKind* = enum mmskNone mmskStr @@ -309,6 +317,50 @@ proc buildShardingConf( let upperShard = uint16(numShardsInCluster - 1) (shardingConf, bSubscribeShards.get(toSeq(0.uint16 .. upperShard))) +proc envOverridePort(envName: string): Option[Port] = + let raw = os.getEnv(envName, "").strip() + + if raw.len == 0: + return none(Port) + + let parsed = + try: + parseInt(raw) + except ValueError: + warn "env port override is not a number, ignoring", + envVar = envName, value = raw + return none(Port) + + if parsed < 0 or parsed > uint16.high.int: + warn "env port override is out of uint16 range, ignoring", + envVar = envName, value = raw + return none(Port) + + info "applying env port override", envVar = envName, port = parsed + return some(Port(parsed.uint16)) + +proc applyEnvironmentOverrides(b: var WakuConfBuilder) = + ## Applies env-var overrides to the builder. + let p2p = envOverridePort(EnvP2pTcpPort) + if p2p.isSome(): + b.withP2pTcpPort(p2p.get()) + + let discv5 = envOverridePort(EnvDiscv5UdpPort) + if discv5.isSome(): + b.discv5Conf.withUdpPort(discv5.get()) + + let rest = envOverridePort(EnvRestPort) + if rest.isSome(): + b.restServerConf.withPort(rest.get()) + + let metrics = envOverridePort(EnvMetricsPort) + if metrics.isSome(): + b.metricsServerConf.withHttpPort(metrics.get()) + + let ws = envOverridePort(EnvWebSocketPort) + if ws.isSome(): + b.webSocketConf.withWebSocketPort(ws.get()) + proc applyNetworkConf(builder: var WakuConfBuilder) = # Apply network conf, overrides most values passed individually # If you want to tweak values, don't use networkConf @@ -441,6 +493,7 @@ proc build*( ## default when it is opinionated. applyNetworkConf(builder) + applyEnvironmentOverrides(builder) let relay = if builder.relay.isSome():