Fix: Skip the transparent listener for a local install, whichever flag starts it - #1256
Conversation
…g starts it The enforce-redirect transparent listener was skipped only under --local. Every service install runs `cortex --config ~/.cortex/config.yaml`, so the supervised proxy bound 127.0.0.1:47603: a port nothing on a laptop redirects to, that the installer never probes, and whose bind failure is fatal. With 47603 occupied the supervised proxy crash-looped, and install.sh misread that as an unusable supervisor and fell back to an unsupervised --local proxy, leaving two supervisors and a launchd job retrying every 30s (rossoctl#1254). Key both redirect-only listeners on the install instead of the flag: skip them when the config is inside ~/.cortex, the same location test the cost ledger default already uses for the same --local/--config split. A config anywhere else, a pod's included, binds and fails exactly as before. Fixes rossoctl#1254 Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com> Signed-off-by: Hai Huang <huang195@gmail.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 53 minutes. View limit detailsLimit details: You’ve used the included review currently available. Review configuration: ⚙️ Run configuration
📒 Files selected for processing (5)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
mrsabath
left a comment
There was a problem hiding this comment.
Correct, minimal fix that replaces a flag check with the install-location check the codebase already uses for the identical --local/--config split. The localMode -> localInstall rename with the "NOT --local alone" counter-note is the right documentation choice: it records the trap rather than just the rule. TestStartedFromLocalInstall's six rows cover the real boundaries, including the .cortex-old prefix case and the no-home path. The accepted limitation (service install --config <outside ~/.cortex> still binds, on a pinned loopback address) is stated explicitly and matches the ledger's boundary, so the two gates stay consistent.
What I verified
Against the latest main via the GitHub API, not a local clone:
--localbehaviour is preserved.main.gosets*configPath = writeBuiltinConfig(absCortex, ...)->~/.cortex/config.yaml, sostartedFromLocalInstallreturns true on that path. The new gate is a strict superset of the old one, adding only the--config ~/.cortex/...service case from #1254.- No silent behaviour flip when
$HOMEis unresolvable.--localalready fatals ondefaultCortexDir()erroring, before the new call, sostartedFromLocalInstall'sreturn falseis unreachable from--local. A pod with no home reaches it and binds, as before. - Assignment ordering is sound.
localInstallis set after the--localblock and before both read sites. No read-before-write. .cortex-oldcannot pass for.cortex, sincepathUnderusesfilepath.Rel. The test's sibling-prefix row asserts exactly that.localModehad no other readers. Thecore/config/config.gohit is a historical comment, not code, so replacing the variable is complete.- The premise holds.
cmd/agentop/setup_probe.gois{"47600", "47601", "47602", "47604"}, commented "47603 is not probed, as install.sh does not". Leaving the four-port lists alone is right: with this change they are correct as they stand.
Findings not anchorable inline
Both are on lines this PR does not touch, so GitHub rejects an inline comment on them. Keeping them here rather than misfiling them onto a nearby changed line.
core/listener/forwardproxy/transparent.go:163 -- nit
A third site still carries the old framing:
// ...this listener is off by default (--local skips it) and every reason it could report is already correct in the log.
The PR body says the two stale claims (the built-in config's comment and agentop's migration note) are reworded. This one survives, and now describes the gate incorrectly in the same way those two did: it is off by default for a local install, --local or --config. Not inline-able because nothing here touches that hunk, which is also why it was missed.
cmd/agentop/setup_probe.go:17 -- suggestion
The comment reads "47603 is not probed, as install.sh does not", which described a stated gap. After this change it is no longer a gap but a consequence: a local install never binds 47603, so there is nothing to probe. Worth upgrading from "we match install.sh" to "nothing binds it" -- the current phrasing invites a future contributor to "fix" the list by adding 47603 back, reintroducing a false preflight failure.
Summary
- Areas reviewed: Go (
cmd/cortex,cmd/agentop), tests, embedded YAML config, commit/PR conventions, security (no secrets; loopback pins preserved) - Commits: 1, signed off: yes
- CI status: passing (27/27, Spellcheck skipped)
Three nit/suggestion-level documentation items, no must-fix.
| return false | ||
| } | ||
| under, _ := pathUnder(dir, configPath) | ||
| return under |
There was a problem hiding this comment.
nit: startedFromLocalInstall and ledgerDefaultOn now duplicate the defaultCortexDir + pathUnder pair with the same semantics. Not worth extracting a third helper, but a one-line cross-reference in each direction would stop them drifting.
Worth noting why they will not stay literally identical: ledgerDefaultOn short-circuits on DirSet() ahead of the location test, and returns a reason string. That asymmetry is the thing a future reader needs told, otherwise the obvious-looking cleanup is to collapse them into one function and quietly give the listener gate a cost_ledger.dir escape hatch it should not have.
Fixes #1254.
Problem
The enforce-redirect transparent listener was skipped only under
--local. Every service install runscortex --supervise --config ~/.cortex/config.yaml(launchd) orcortex --config …(systemd), so the supervised proxy bound127.0.0.1:47603— a port nothing on a laptop redirects to, that the installer's preflight never probes, and whose bind failure is fatal.Reproduced on macOS against
main, with a relabelled, port-shifted build so the live service was not touched. With only the transparent port occupied, the outcome is worse than the issue describes:agentop service installwaits 15s for health, gets nothing, and exits 1.service_install_actionuses the same four-port list, so it reads that as an unusable supervisor and takesfallback. It startscortex --local --supervise, which skips the listener and serves. install.sh exits 0 and says the environment "has no usable OS service supervisor".proxy.log.Already current: … running under launchd user agent and healthy, because launchd sees the--superviseparent and the fallback proxy answers health.Fix
Key both redirect-only listeners (outbound transparent, inbound transparent) on the install instead of the flag: skip them when the config is inside
~/.cortex. That is the location testledgerDefaultOnalready uses for the same--local/--configsplit, and--localpoints--configat that same file.localModehad no other reader, so it is replaced bylocalInstall.A config anywhere else, a pod's included, binds and fails exactly as before. The
127.0.0.1:47603pin stays, so a copy of the file started from elsewhere still binds loopback only. The built-in config's comment and agentop's migration note said--configbinds the listener; both are reworded.Accepted: a service installed with
agentop service install --config <path outside ~/.cortex>still binds it, on the pinned loopback address. The ledger has the same boundary.Not changed: install.sh's four-port preflight and its
fallbackclassification. The thin-installer series replaces both withagentop setup, which already rolls back a failed service install instead of falling back. With this change, the four-port lists in both are correct as they stand.Verification
TestStartedFromLocalInstall(local install, a pod's config, leftover~/.cortexwith the config elsewhere, a.cortex-oldsibling, no home, no config). It fails before the change and passes after.cmd/cortex:go vet, plusgo test -raceuntagged and with thelocal,fullandliteprofiles.cmd/agentop:go vet,go test ./.... gofmt is clean.Running as a launchd user agent, healthy, one supervisor and child on four ports, no errors, no restarts, no fallback.~/.cortex: binds the transparent port when it is free, and exits 1 with the bind error when it is taken.Assisted-By: Claude (Anthropic AI) noreply@anthropic.com