Skip to content

fix(pilotctl): default beacon to the production address, honor PILOT_BEACON#419

Merged
TeoSlayer merged 1 commit into
pilot-protocol:mainfrom
pstayets:fix/init-beacon-default
Jul 24, 2026
Merged

fix(pilotctl): default beacon to the production address, honor PILOT_BEACON#419
TeoSlayer merged 1 commit into
pilot-protocol:mainfrom
pstayets:fix/init-beacon-default

Conversation

@pstayets

Copy link
Copy Markdown
Contributor

Symptom

The documented bootstrap flow:

pilotctl init --hostname my-agent
pilotctl daemon start

writes a dead beacon (127.0.0.1:9001) into ~/.pilot/config.json while writing the production registry (34.71.57.205:9000) into the same file. A node bootstrapped this way registers fine but cannot traverse NAT — its beacon points at localhost where nothing is listening.

The three code locations (all verified on current main)

  1. cmdInit (cmd/pilotctl/main.go:2014):

    registryAddr := flagString(flags, "registry", "34.71.57.205:9000")
    beaconAddr := flagString(flags, "beacon", "127.0.0.1:9001")

    Registry defaults to production; beacon defaults to localhost — and gets persisted to config.json, poisoning every later daemon start.

  2. buildDaemonArgs (cmd/pilotctl/main.go:2645-2652): when config lacks a beacon it injected "127.0.0.1:9001", and it never consulted PILOT_BEACON — while the registry path a few lines above resolves flag > config > env > hardcoded default (the else branch calls getRegistry(), which checks $PILOT_REGISTRY). The beacon had no env leg at all.

  3. The daemon binary's own default IS the production beacon (cmd/daemon/main.go:53-58: beaconDefault := "34.71.57.205:9001", with $PILOT_BEACON support) — but buildDaemonArgs always passes an explicit --beacon, so the daemon's correct default is unreachable through the documented start path.

Notably, pilotctl's own shipped help already documents the intended behavior — daemon start --help says --beacon <addr> beacon address (default: $PILOT_BEACON or 34.71.57.205:9001) and config --help says beacon beacon address (overrides $PILOT_BEACON). This change makes the code match its own help.

Fix (minimal, 19 lines)

  • cmdInit beacon fallback: 127.0.0.1:900134.71.57.205:9001 (mirroring the registry default one line above).
  • New getBeacon() helper mirroring getRegistry() line for line (env → config → production default), and buildDaemonArgs's else branch now calls it — giving beacon the exact same precedence the registry has: flag > config > PILOT_BEACON > hardcoded production default.

The new default matches both the daemon binary's own compiled default (cmd/daemon/main.go:53) and the address the pilot-protocol/release installer uses (PILOT_BEACON:-34.71.57.205:9001).

Blast-radius analysis

  • Grep of the whole repo for 127.0.0.1:9001 / 9001 (including tests): every 127.0.0.1:9001 hit outside the two changed lines is a local test registry listen address (registry.New("127.0.0.1:9001") / NewWithStore(...) in tests/zz_*_test.go) or an explicit SetBeaconAddr/beacon-selection fixture in pkg/daemon tests — none reaches cmdInit/buildDaemonArgs fallbacks. The cmd/pilotctl lifecycle tests (zz_lifecycle_test.go, zz_commands_test.go) exercise beacon via explicit --beacon flags or config values (b.x:9001, cfg.example:9001) and never assert the old fallback. TestBuildDaemonArgsDefaults only asserts that a --beacon flag is present, not its value.
  • Installer users unaffected: both install.sh in this repo (writes "beacon": "${BEACON}" with default registry.pilotprotocol.network:9001 into config.json and passes -beacon in the launchd/systemd units) and install.sh in pilot-protocol/release (default 34.71.57.205:9001, same explicit-write pattern) always persist an explicit beacon, so the fallback never fires for them.
  • Local-dev is preserved: anyone intentionally running a local beacon still has the same three escape hatches the registry has — --beacon 127.0.0.1:9001, pilotctl config --set beacon=..., or (new, previously missing) PILOT_BEACON.

Verification

Built locally with Go 1.26.3: gofmt -l clean, go build ./cmd/... succeeds, go test ./cmd/pilotctl passes (13.1s, ok).

🤖 Generated with Claude Code

https://claude.ai/code/session_0142ryqVGEmJN66VZtCC7wFD

…BEACON

Symptom: the documented bootstrap flow

    pilotctl init --hostname my-agent
    pilotctl daemon start

writes a dead beacon (127.0.0.1:9001) into ~/.pilot/config.json while
writing the production registry (34.71.57.205:9000) into the same file.
A node bootstrapped this way registers fine but cannot traverse NAT —
its beacon points at localhost where nothing is listening.

Three code locations conspired:

1. cmdInit: beaconAddr := flagString(flags, "beacon", "127.0.0.1:9001")
   — localhost fallback, inconsistent with the registry default in the
   same function ("34.71.57.205:9000").
2. buildDaemonArgs: when config lacked a beacon it injected
   "127.0.0.1:9001", and it never consulted PILOT_BEACON — while the
   registry path in the same function resolves flag > config > env >
   hardcoded default (via getRegistry).
3. cmd/daemon's own default IS the production beacon
   ("34.71.57.205:9001", with $PILOT_BEACON support), but pilotctl
   always passes an explicit --beacon, so the daemon's correct default
   was unreachable through the documented start path. pilotctl's own
   `daemon start --help` already documents "--beacon <addr> beacon
   address (default: $PILOT_BEACON or 34.71.57.205:9001)" — this change
   makes the code match its shipped help.

Fix: both pilotctl fallbacks now use 34.71.57.205:9001, and beacon
resolution gains a getBeacon() helper mirroring getRegistry() exactly,
closing the env-precedence gap (flag > config > PILOT_BEACON > default).

Blast radius:
- Every 127.0.0.1:9001 in tests is a local test *registry* listen
  address (registry.New / NewWithStore) or an explicit SetBeaconAddr —
  none depends on the removed pilotctl fallback.
- Installer users are unaffected: both install.sh in this repo and the
  one in pilot-protocol/release write an explicit "beacon" key into
  config.json and pass -beacon in the service units.
- Local-dev beacons still work via --beacon, the config key, or (new)
  PILOT_BEACON — the same three escape hatches the registry has.

Verified: gofmt clean; go build ./cmd/... ok; go test ./cmd/pilotctl ok.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0142ryqVGEmJN66VZtCC7wFD
@pstayets
pstayets requested a review from TeoSlayer as a code owner July 23, 2026 22:05
@TeoSlayer
TeoSlayer merged commit 1719451 into pilot-protocol:main Jul 24, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants