Skip to content

GitHub goal delivery: restore explicit non-loopback Beacon bind mode #316

Closed

Description

@johnnygreco

Goal

Restore a supported code-level path for Beacon to bind to a non-loopback interface so direct Tailnet URLs such as http://100.88.255.7:4600/ can work again when explicitly configured, without changing the secure loopback default.

Source Of Truth

Governing sources, in order, when instructions conflict:

  1. Active user goal and explicit user corrections: the direct Tailscale-IP dashboard workflow used to work and should be restored via a code-level fix.
  2. This progress tracker.
  3. The active implementation issue or PR scope.
  4. Repo docs and historical behavior from the multi-machine period.
  5. Local skill instructions and repo conventions.

Material conflict recorded: current production docs say to keep Beacon bound to loopback and expose it through a proxy/VPN layer. The chosen precedence is to keep that as the default/recommended path, while adding an explicit opt-in non-loopback bind mode for trusted private networks such as Tailscale.

Shared Context

Beacon currently defaults to server.host = "127.0.0.1" and rejects non-loopback hosts unless [server] allow_non_loopback = true is configured. The server listener is still built from cfg.Server.Host and cfg.Server.Port in internal/beaconcli/cmd_serve.go, so binding to a specific Tailnet/private IP or to 0.0.0.0 restores direct access through the machine's Tailscale IP when explicitly configured. Backward compatibility is not required generally, but the user's explicit requirement is to restore this direct Tailnet access workflow through a deliberate configuration path.

Definition of Done

  • Beacon still defaults to loopback-only binding.
  • A documented, explicit config option permits non-loopback server.host values such as a specific Tailnet/private IP or 0.0.0.0 for trusted private-network use.
  • Config validation rejects non-loopback binds unless the explicit opt-in is enabled.
  • beacon up can start with a non-loopback bind when opted in, and still fails early when not opted in.
  • Tests cover default rejection, opt-in acceptance, serve-level behavior, and health diagnostics for exact/wildcard non-loopback binds.
  • Production docs explain the opt-in, the Tailscale use case, wildcard-interface risk, API/MCP mutation-path risk, and the security tradeoff.
  • Release/publish is out of scope. README updates are out of scope unless the implementation changes onboarding behavior. Production docs are in scope.

Validation Strategy

Commands every implementation issue should run before PR review:

  • format: make fmt-check
  • generated files: make generate-check
  • focused tests: go test ./internal/config ./internal/beaconcli
  • broad tests: make test
  • lint: make lint
  • local install: make install-local INSTALL_DIR="$HOME/.local/bin"

Risks

  • Security regression: accidentally making non-loopback binding the default. Mitigation: default remains loopback and tests assert explicit opt-in is required.
  • Confusing operational guidance: docs could imply broad binding is generally preferred. Mitigation: keep loopback/proxy as the recommendation and frame non-loopback as private-network opt-in.
  • Host/header behavior: since the obsolete loopback Host guard was removed, direct Tailnet IP and hostname requests should not need special Host rewriting. Mutation guard behavior remains same-origin based.
  • Local dev server churn: after merge, rebuild and restart the persistent review server per AGENTS.md.

Issue Checklist

Integration Notes

Implemented as one cohesive PR touching config structs/defaults/validation, focused tests, serve startup tests, health diagnostics, and production docs. Removed multi-machine auth/control-plane/ingest surface was not reintroduced.

Current State

Final Status

Merged #318 on 2026-06-24. Beacon now supports [server] allow_non_loopback = true as an explicit opt-in for non-loopback dashboard binds while preserving loopback-only defaults. Local validation passed after review fixes: make fmt-check, make generate-check, go test ./internal/config ./internal/beaconcli, make test, make lint, make install-local INSTALL_DIR="$HOME/.local/bin", and git diff --check. GitHub CI passed on the final PR head, including build, dependency-review, format, frontend, generated, govulncheck, lint, npm-audit, playwright-accessibility, playwright-dashboard, and test.

Activity

  1. johnnygreco commented on Jun 24, 2026

    @johnnygreco
    OwnerAuthor

    Final local verification after merge:\n- Reinstalled merged main with make install-local INSTALL_DIR="/Users/donnie/.local/bin".\n- Restarted the persistent review server in tmux session beacon-up from /Users/donnie/.local/bin/beacon up.\n- Verified curl -fsS http://localhost:4600/ succeeds.\n- beacon status reports the server running at 127.0.0.1:4600 with pid 93545.\n\nOperational note: this machine currently has no default ~/.beacon/beacon.toml, so the review server remains on the secure loopback default. To enable direct Tailnet-IP access, configure [server] host to a trusted private address, or 0.0.0.0 with firewall/ACL care, and set allow_non_loopback = true.

  2. johnnygreco commented on Jun 24, 2026

    @johnnygreco
    OwnerAuthor

    Goal complete: #318 merged, #317 closed, review record posted, CI green, tracker final status recorded, and the local dev server restarted from the merged binary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions