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) {