feat(compose): publish on every interface, so the host's own address answers #19
Reference in New Issue
Block a user
No description provided.
Delete Branch "feat/publish-on-all-interfaces"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
One decision of record, D59, amending D55. Count of record fifty-nine.
The site is deployed and healthy on the host as of #18, and it can only be reached from the host. That is D55 working as designed and being the wrong design for right now.
What D55 got wrong
D55 bound the published port to
127.0.0.1, reasoning that TLS terminates at a proxy on the same host and nothing else has business reaching the container. That is right for the host this eventually runs on, and wrong for every step before it: a loopback binding cannot be opened from a browser on another machine. Looking at the site on the VM's own address — before DNS exists, before the proxy exists, from a desktop or a phone that is not the VM — is the first thing anyone wants to do with a fresh deploy, and it was the one thing the compose file forbade.http://<vm-ip>:4321now answers out of the box, the way a normal bridge publish behaves.Which addresses it answers on is a variable, not an edit
SITE_BIND_ADDRin.envnarrows it without touching a file thatdocker compose pullreplaces:That also retires an instruction
DEPLOY.mdhad to give: D55's advice to a proxy running in another container or on another machine was "change the port line indocker-compose.ymlyourself", which is an edit to a file the nextpulloverwrites. It is a variable now.What is given up, said plainly
On a host with a public address, the default means port 4321 answers from the internet directly — plain HTTP beside whatever the proxy serves on 443, and with no proxy in the path to set
X-Forwarded-For, so signups arriving that way share one rate-limit bucket. The site has no login and nothing to steal, so this is untidy rather than dangerous.DEPLOY.md§3.1 states it and names both remedies: firewall the port, or narrow the binding.What was run
Verified by running it, not only by reading it:
docker compose confighost_ip, default0.0.0.0host_ip, withSITE_BIND_ADDR=127.0.0.1127.0.0.1— the narrowing worksdocker compose port site 4321→0.0.0.0:4321http://127.0.0.1:4321/http://<machine's LAN address>:4321/Notes
.envneeds no new value unless you want to narrow the binding.PLAN.mdas D59 under "How phase 12 delivered it", with D55's paragraph amended in place rather than rewritten — the same way D54 amended D6.Co-Authored-By: Claude.🤖 Generated with Claude Code
D55 bound the published port to 127.0.0.1, on the reasoning that TLS terminates at a proxy on the same host and nothing else has business reaching the container. That is right for the host this ends up on and wrong for every step before it: a loopback binding cannot be opened from a browser on another machine, which is the first thing an operator wants to do — look at the site on the VM's own address, before DNS exists, before the proxy exists, from a desktop or a phone. The port line is now "${SITE_BIND_ADDR:-0.0.0.0}:${SITE_HOST_PORT:-4321}:4321", so http://<vm-ip>:4321 answers out of the box, the way a normal bridge publish behaves. Which addresses it answers on is a variable rather than an edit: SITE_BIND_ADDR narrows it to one interface, or back to loopback, without touching a file that `docker compose pull` replaces. That also retires the "change the port line yourself" instruction DEPLOY.md had to give a proxy running in another container or on another machine. What is given up, said plainly in DEPLOY.md §3.1: on a host with a public address the default answers on port 4321 from the internet, plain HTTP beside the proxy's 443, with no proxy in the path to set X-Forwarded-For — so signups arriving that way share one rate-limit bucket. There is no login and no secret behind it, so it is untidy rather than dangerous, and both remedies are named (firewall the port, or narrow the binding). Verified by running it, not only by reading it: `docker compose config` accepts both bindings and resolves host_ip 0.0.0.0 and 127.0.0.1 respectively; the stack came up healthy, `docker compose port site 4321` reported 0.0.0.0:4321, and the site answered 200 on both 127.0.0.1 and the machine's LAN address, still carrying its own per-page CSP. Recorded as D59, amending D55. Count of record fifty-nine. Co-Authored-By: Claude <noreply@anthropic.com>