Repository navigation
Serve the site on a network without Cloudflare: listen, site_url and access as separate settings (pm-site sprint 5) - #115
Merged
Merged
Conversation
Reach (listen, the bind address) and gate (access, cloudflare or none) become settings of their own beside site_url, so a site can serve a network without Cloudflare. A listen that is not an IP or an unknown access fails hard; AccessMissing names access once the site is exposed and the Access keys under access = "cloudflare"; Migrated is the one explicit inference, for configs from before access existed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d-only A request is local only from a loopback peer naming this machine with no Cf-Connecting-IP: with a LAN bind, Host alone would let any colleague claim localhost, while the Host check stays for a rebinding domain a local browser reaches. Under access = "none" a network viewer reads (pages show the rule instead of reply forms and carry no token) and its reply is refused, per the owner's decision: a reply instructs an agent session and pm cannot tell the owner from a colleague. The service refuses to start exposed without access; a specific listen address also binds 127.0.0.1 so this machine's probes and links keep working, and the port check binds what the service binds. pm init --listen/--access write the settings and refuse an exposed config without access before any write; pm init and pm upgrade migrate access_team configs to access = "cloudflare"; pm doctor and pm where state the new settings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s once listen = "::ffff:127.0.0.1" bound 127.0.0.1 twice: PortFree was always false and FreePort never returned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A bare "[::1]" Host became "[:", and a bracketed IPv6 site_url host never matched url.Hostname's unbracketed form. The Binds test rides along in access_test.go. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both write access = "cloudflare" where ConfigText puts it and keep every other key, so pm doctor finds no drift; without the upgrade's migration the test fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only site_url's host is served beyond this machine, so listen = "0.0.0.0" without it refuses every request from the network; both name pm init --site-url. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rebased onto main, whose served-site move lowered internal/cli's size ratchet to 7307 lines; this sprint's two pm init flags put it 2 over. syncStore, what the pm service runs for pm_sync(), joins SetupStore, what it runs for pm_setup(), in install/workstore.go as SyncStore. internal/cli is down to 7263 lines and its ratchet follows. Co-Authored-By: Claude Opus 5.5 <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.
What
.pm/config.tomlsettings, each written by its ownpm initflag:listen(--listen ADDR): the IP the site binds. 127.0.0.1 when unset. Beside a specific address other than 127.0.0.1 the service also binds 127.0.0.1, so probes,pm record link --localand a tunnel keep working.PortFree,CheckPortandFreePortbind exactly what the service binds.access(--access cloudflare|none): how a request from beyond this machine gets in. It is required oncelistenis not loopback orsite_urlis set: the service refuses to start without it,pm doctornames it, andpm initrefuses the flag change before writing anything.Hostnames this machine and it has noCf-Connecting-IP. A LAN peer sendingHost: localhostis refused. The Host check stays, against rebinding domains reached from a local browser.access = "none": the network readssite_url's host with no login. The owner decided that a non-local viewer may not reply:Site.FillReadOnly);/versionhashes the page that viewer is served;POST /replygets a 403 naming the rule;access = "cloudflare": the Access JWT check as before.pm init(session start included) andpm upgradegive a config withaccess_teamand noaccessthe lineaccess = "cloudflare". It goes where ConfigText writes it, sopm doctorsees no drift.pm upgradematters most here: it moves the pin that the restarted service reads.pm doctorand a typedpm initwarn whenlistenis on the network butsite_urlis unset, since every network request is then refused.pm whereand the service log state a non-loopbacklisten.--helptexts, with the golden files regenerated;prime.mdclause;changelog.d/site-listen-access.md, with an Upgrade guide step;site-replies(Security rewritten by peer, Host and access),pm-product,pm-goandviews-and-site.Sprint: https://pm.yeeefs.com/sprints/pm-site-5.html
Evidence
make test-go: 19 packages ok.make lint: 0 issues.make test: 152 passed, 169 skipped.make test-full -k):test_init_and_upgrade_keep_what_is_not_pms,test_service_refuses_the_public_host…,test_doctor_reports_each_changed…,test_service_install…,test_every_config_key…,test_reply_is_refused…: 7 passed.listen = "0.0.0.0",access = "none",site_url = http://byeeefy:42075; requests from the LAN address 192.168.178.115:byeeefy:42075: 200, no token in the page;Host: localhost: 403;POST /reply: 403 naming the rule.🤖 Generated with Claude Code