feat(config): default the dashboard bind to loopback - #39
Merged
Merged
Conversation
The dashboard used to seed server.host with 0.0.0.0, so a fresh install exposed the web UI on every network interface (Wi-Fi, ethernet, VPN, hotspot). ValidateListen then refused the first setup submit until the user configured an auth token or a dashboard password, blocking the wizard on the very first click. The README already told users the production binary "binds 127.0.0.1 by default" — this brings the code into line with what was already documented. Defaults now route through a resolver: 1. ANTARES_HOST wins when non-empty, so installers, systemd units, and one-off invocations can override without editing config. 2. Container heuristic returns 0.0.0.0 when /.dockerenv, /run/.containerenv, or /proc/1/cgroup marks Docker, Podman, containerd, or Kubernetes — otherwise `docker run -p 8787:8787` cannot reach the process. 3. Loopback fallback everywhere else. Existing configs with an explicit server.host keep their value untouched; this only changes what a fresh install writes and what a config with no server.host resolves to. ValidateListen still refuses non-loopback binds without auth, so opting in to LAN exposure still requires the guard's consent. Tests cover the three branches through a swappable containerProbe seam so no container runtime is needed at test time.
Owner
|
Fixed and merged with corrective commit 700c5cd. The original resolver included ANTARES_HOST in Default(), which is written to config.yaml on first boot; a one-off wildcard override therefore became permanent. Default() now seeds only the container/loopback value, and the existing environment overlay applies ANTARES_HOST afterward. Regression tests inspect saved YAML and reload after removing the variable, plus explicit YAML host precedence, whitespace-only values, and container seeding. README now explains that the container-derived seed is stored. Local config/CLI tests and GitHub go, web, and smoke checks passed. Closed through merge with the correction included. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Route
Server.HostinDefault()through a resolver:ANTARES_HOSTenv var wins when non-empty — for installers, systemd units, and one-off invocations./.dockerenv,/run/.containerenv, or/proc/1/cgroupmarkers for docker/podman/containerd/kubepods) returns0.0.0.0sodocker run -p 8787:8787still works.127.0.0.1) everywhere else.Why
A fresh install seeded
server.host: 0.0.0.0, so the dashboard was reachable from every network interface (Wi-Fi, ethernet, VPN, hotspot) the moment the process started.ValidateListenthen refused the first setup submit until the user configured an auth token or a dashboard password — blocking the wizard on the very first click, which is exactly when the user has nothing to configure yet.The README already tells users the production binary "binds
127.0.0.1by default" (see the "Accessing it from another machine" section). This PR brings the code into line with what the docs already promised.Changes
internal/config/defaults.go: adddefaultHost(),inContainer(),detectContainer(), and acontainerProbeseam; routeServer.HostinDefault()through the resolver.internal/config/defaults_test.go: new file, 8 subtests covering precedence (env override, container heuristic, loopback fallback, empty-env-falls-through, env-beats-container) plus a guard thatDefault()still routes through the resolver.README.md: expand the "Accessing it from another machine" section with the container heuristic andANTARES_HOSToverride; keep the existing note that non-loopback binds still require auth.Not breaking
Existing configs with an explicit
server.hostkeep their value — this only affects fresh installs and configs that omit the field.ValidateListenbehavior unchanged: non-loopback binds still requireserver.auth_token, a dashboard password, orserver.auth_disabled: true. Docker deployments unchanged (auto-switch to0.0.0.0inside containers).Validation
GOTOOLCHAIN=go1.26.3 go test ./internal/config/...— 8 new subtests pass, existingruntime_test.gocases (which pass explicitHost:values) stay green.GOTOOLCHAIN=go1.26.3 go vet ./internal/config/...clean.go run ./cmd/antares serve --foregroundon macOS logsaddr=127.0.0.1:8787(wasaddr=0.0.0.0:8787).ANTARES_HOST=0.0.0.0 go run ./cmd/antares serve --foregroundlogsaddr=0.0.0.0:8787— override honored.Follow-up (not in this PR)
Config.Validate()runs inruntimeServices.reload()and the setup save path but not on initial boot. A first run withANTARES_HOST=0.0.0.0and no auth currently starts the listener without tripping the guard — the guard only fires on the next reload or setup save. This gap predates this PR and is not made worse by it (defaults now bias toward loopback, so first-boot LAN exposure requires an explicit opt-in). Fix belongs in a small follow-up that callscfg.Validate()beforeruntimeServices.start.