fix(connector): find cloudflared when launchd's PATH does not have it - #2
Merged
Conversation
After a machine restart the tunnel was dead and could not be brought back:
`bb cf-tunnel status` said not-provisioned, `bb cf-tunnel provision` printed
success and changed nothing, and reload/disable/enable all left the connector
in backoff.
Provisioning was never the problem. The persisted state had a valid connector
token the whole time. The bb host process had:
PATH=/usr/bin:/bin:/usr/sbin:/sbin
which is launchd's default, and cloudflared lives at /opt/homebrew/bin. So
resolveCloudflaredPath returned null, runConnector threw "cloudflared not found
on PATH", and the service sat in backoff with no tunnel. Started from a terminal
bb inherits the user's PATH and it worked perfectly — which is exactly why the
symptom was "it breaks when I reboot" and not "it is broken".
A GUI process inherits launchd's environment, not a login shell's, so PATH is
not evidence of what is installed on the machine. resolveCloudflaredPath now
searches the known install prefixes after PATH: /opt/homebrew/bin (Homebrew on
Apple silicon), /usr/local/bin (Intel Homebrew and the official .pkg) and
/opt/local/bin (MacPorts). PATH still wins when it has a hit.
The error message now names where it looked, so the next person sees the actual
PATH rather than the word "PATH".
Two existing tests asserted behaviour the fallbacks legitimately change — an
empty PATH now resolves — so they pass fallbackDirs: [] and keep testing PATH
parsing in isolation rather than being loosened.
Verified live: after reload, cloudflared runs from /opt/homebrew/bin, the
service reports running, `bb cf-tunnel status` reports connected, and
127.0.0.1:20242/ready returns readyConnections: 4.
73 tests pass, 4 new.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
After a machine restart the tunnel was dead and could not be brought back:
statussaidnot-provisioned,provisionprinted success and changed nothing, and reload / disable / enable all left the connector inbackoff.Provisioning was never the problem
The persisted state had a valid connector token the whole time. The bb host process had:
That's launchd's default — and
cloudflaredlives at/opt/homebrew/bin. SoresolveCloudflaredPathreturnednull,runConnectorthrew "cloudflared not found on PATH", and the service sat in backoff with no tunnel.Started from a terminal, bb inherits the user's PATH and it works perfectly. That is exactly why the symptom was "it breaks when I reboot" rather than "it is broken."
A GUI process inherits launchd's environment, not a login shell's, so PATH is not evidence of what is installed on the machine.
The fix
resolveCloudflaredPathnow searches the known install prefixes after PATH:/opt/homebrew/bin/usr/local/bin.pkg/opt/local/binPATH still wins when it has a hit. The error message now names where it looked, so the next person sees the actual PATH rather than the word "PATH".
Two existing tests asserted behaviour the fallbacks legitimately change — an empty PATH now resolves — so they pass
fallbackDirs: []and keep testing PATH parsing in isolation, rather than being loosened.Verified live
After reload:
cloudflaredruns from/opt/homebrew/bin, the service reportsrunning,bb cf-tunnel statusreports connected, and127.0.0.1:20242/readyreturnsreadyConnections: 4.73 tests pass, 4 new.
🤖 Generated with Claude Code