From 4093fa1dcb873462efd599dba79fcedd25dfed36 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Wed, 27 May 2026 05:34:05 -0500 Subject: [PATCH] feat(config): INVENTORY_HEALTH_ADDR + INVENTORY_ADMIN_ADDR env overrides (26.16) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Containerised deployments can now repoint the listeners without rewriting the JSON config: docker run \ -e INVENTORY_HEALTH_ADDR=0.0.0.0:18080 \ -e INVENTORY_ADMIN_ADDR=0.0.0.0:19090 \ -e INVENTORY_AUTH_TOKEN=... \ ghcr.io/cryptojones/networkinventoryagent:latest Existing validation still applies — off-loopback bind without an auth token is refused at boot regardless of which surface (file or env) set the address. Also fixes the README env-var table, which never listed the INVENTORY_AUTH_TOKEN / INVENTORY_PEER_TOKEN variables that have been supported since 26.06. Co-Authored-By: Claude Opus 4.7 (1M context) --- ChangeLog.md | 23 +++++++++++++++++++++++ README.md | 4 ++++ internal/config/config.go | 11 +++++++++++ internal/config/config_test.go | 4 ++++ 4 files changed, 42 insertions(+) diff --git a/ChangeLog.md b/ChangeLog.md index c03bf7d..2ac48eb 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -17,6 +17,29 @@ _No unreleased changes._ --- +## 26.16 — 2026-05-27 + +Listener-address environment variable overrides. Containerised +deployments can now repoint the health + admin listeners without +rewriting the JSON config file. + +### Added + +- **`INVENTORY_HEALTH_ADDR`** — overrides `health.addr`. +- **`INVENTORY_ADMIN_ADDR`** — overrides `admin.addr`. + +Existing config validation still applies: an off-loopback bind +without a corresponding `INVENTORY_AUTH_TOKEN` is refused at boot, +regardless of which surface (file or env) supplied the address. + +### Fixed + +- **README env-var table now lists `INVENTORY_AUTH_TOKEN` and + `INVENTORY_PEER_TOKEN`**, which the code has supported since 26.06 + but the docs never advertised. + +--- + ## 26.15 — 2026-05-27 Per-subnet scan profiles (P2-05). Operators can now run aggressive diff --git a/README.md b/README.md index cd5e877..dfe3188 100644 --- a/README.md +++ b/README.md @@ -349,6 +349,10 @@ Duration values in the JSON config accept human-readable strings (`"5m"`, `"30s" | `INVENTORY_DB_PATH` | `database.path` | | `INVENTORY_LOG_LEVEL` | `log.level` | | `INVENTORY_LOG_FORMAT` | `log.format` | +| `INVENTORY_HEALTH_ADDR` | `health.addr` | +| `INVENTORY_ADMIN_ADDR` | `admin.addr` | +| `INVENTORY_AUTH_TOKEN` | `health.auth_token` | +| `INVENTORY_PEER_TOKEN` | `watchdog.peer_token` | ## Health endpoints diff --git a/internal/config/config.go b/internal/config/config.go index 04b89d2..c823c30 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -518,4 +518,15 @@ func applyEnv(cfg *Config) { if v := os.Getenv("INVENTORY_PEER_TOKEN"); v != "" { cfg.Watchdog.PeerToken = v } + // Listener addresses also come from env so containerised deployments + // can repoint without rewriting the JSON file (e.g. + // INVENTORY_HEALTH_ADDR=0.0.0.0:18080 + INVENTORY_AUTH_TOKEN=... in + // the orchestrator). Validation in validate() catches off-loopback + // binds without a token regardless of which surface set the addr. + if v := os.Getenv("INVENTORY_HEALTH_ADDR"); v != "" { + cfg.Health.Addr = v + } + if v := os.Getenv("INVENTORY_ADMIN_ADDR"); v != "" { + cfg.Admin.Addr = v + } } diff --git a/internal/config/config_test.go b/internal/config/config_test.go index abe354d..8011435 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -99,6 +99,8 @@ func TestLoad_EnvOverrides(t *testing.T) { t.Setenv("INVENTORY_DB_PATH", "/env/override.db") t.Setenv("INVENTORY_LOG_LEVEL", "warn") t.Setenv("INVENTORY_LOG_FORMAT", "json") + t.Setenv("INVENTORY_HEALTH_ADDR", "127.0.0.1:18080") + t.Setenv("INVENTORY_ADMIN_ADDR", "127.0.0.1:19090") cfg, err := config.Load("/nonexistent/config.json") require.NoError(t, err) @@ -106,6 +108,8 @@ func TestLoad_EnvOverrides(t *testing.T) { assert.Equal(t, "/env/override.db", cfg.Database.Path) assert.Equal(t, "warn", cfg.Log.Level) assert.Equal(t, "json", cfg.Log.Format) + assert.Equal(t, "127.0.0.1:18080", cfg.Health.Addr) + assert.Equal(t, "127.0.0.1:19090", cfg.Admin.Addr) } func TestLoad_EnvOverridesFile(t *testing.T) {