Let the daemon choose its own port - #48
Merged
Merged
Conversation
The approval API was on a fixed 127.0.0.1:8787, and the GUI decided it was talking to its own daemon because something answered there. Anything that got to the port first would be handed the unlock passphrase, or an imported nsec, by a GUI with no way to tell the difference. The daemon now binds port 0 in managed mode and reports what the kernel gave it. A port nobody has chosen yet cannot be taken in advance, and the port differs on every start. It reports it on STDOUT, which is not incidental: the SDK's line-mode spawn ignores a child's stderr outright, so the ordinary banner would have been dropped and the GUI would have waited forever for a port it was never told. Read out of the SDK rather than assumed. The GUI sends nothing until it has been told where to send it. Until the port line arrives it stays in `starting`, which is the honest state and one the retry tick already knows how to leave. A restart clears it, because a restarted daemon gets a different port. Attached mode is unchanged: the address comes from the environment and is the operator's business. This does not help against a process running as this user, which can read the token file as easily as the GUI can. It closes the case where something is simply sitting on a known port, waiting. Verified by running it: the daemon reports a real ephemeral port and serves there, the port differs across restarts, and the GUI launched in managed mode reaches first-run setup, which it can only do after an authenticated /info round trip to the port it was told about.
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.
The approval API was on a fixed
127.0.0.1:8787, and the GUI concluded it was talking to its own daemon because something answered there. Anything that reached the port first would be handed the unlock passphrase, or an imported nsec, by a GUI with no way to tell the difference.The daemon now binds port 0 in managed mode and reports what the kernel gave it. A port nobody has chosen yet cannot be taken in advance, and it differs on every start.
It reports it on stdout, and that is not incidental. The SDK's line-mode spawn ignores a child's stderr outright (
.stderr = if (output_mode == .collect) .pipe else .ignore), so the ordinarystd.debug.printbanner would have been dropped on the floor and the GUI would have waited forever for a port it was never told. Read out of the SDK rather than assumed.The GUI sends nothing until it has been told where to send it. Until the port line arrives it stays in
starting, which is the honest state and one the retry tick already knows how to leave. A restart clears it, since a restarted daemon gets a different port. Attached mode is unchanged: the address comes from the environment and is the operator's business.What this does not do
It does not help against a process running as this user, which can read the token file as easily as the GUI can. It closes the case where something is simply sitting on a known port, waiting.
Verified by running it
/inforound trip to the port it was told about; its child daemon was listening on 61235, not 8787