docs: correct the "pi-studio has no bind flag" claim everywhere it was baked
1e4c238fixed README; the same claim lived in three more places, all wrong since pi-studio 0.9.60 added /studio --listen-all: - rootfs/usr/local/bin/studio-expose header (and so its --help; the sed range grows 2,31p -> 2,35p so --help still ends at "runs it backgrounded.") - pi-devbox-environment skill section 7: --listen-all as a third path, plus the 0.10 whole-URL / 409 / "link looks damaged" notes, the published-port rule, --stop before --port, and the on-host curl 403-vs-empty-reply diagnostic - Dockerfile.variant STUDIO_PORT comment Bridge and --listen-all on one port: whichever starts second fails, measured both ways on tor-ms22 (v1.11.2): Studio "listen EADDRINUSE ... 0.0.0.0:8765" with the bridge up; studio-expose rc 1 on socat "bind(...): Address already in use" with a 0.0.0.0 listener up. README's warning now says both directions. Cost: studio-expose and the skill are in rootfs/, which base_tag hashes, so the next release rebuilds the base (recomputed with the CI recipe: base-6f3b20266de1 at1e4c238-> base-26d425cea6c2 now). Noted in the CHANGELOG Unreleased entry. No pin changes. lint-shell, dockerfile-directives and base-hash guards pass; check-doc-drift is red only for the unrelated pi-extensions 750b2a8 -> 0d8e417.
This commit is contained in:
+16
-6
@@ -13,18 +13,28 @@ Pre-v1.0.0 tags followed the pi npm version (`v{pi_version}[letter]`).
|
||||
|
||||
## Unreleased
|
||||
|
||||
Docs only: this entry changes no pin.
|
||||
Docs and comments only: this entry changes no pin. Two of the files are
|
||||
baked into the base image (`rootfs/usr/local/bin/studio-expose` and the
|
||||
`pi-devbox-environment` skill), and `base_tag` hashes all of `rootfs/`, so
|
||||
**the next release rebuilds the base** rather than reusing
|
||||
`base-6f3b20266de1`.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **README "Using pi-studio" said pi-studio has no bind flag.** It has had
|
||||
`/studio --listen-all` (binds `0.0.0.0`) since pi-studio 0.9.60, so the
|
||||
section now lists it as path **C**, next to host networking (A) and the
|
||||
`studio-expose` bridge (B). It also warns not to combine B and C on one port.
|
||||
With `STUDIO_EXPOSE=1` the bridge holds the egress IP on `$STUDIO_PORT`
|
||||
from boot, and `/studio --listen-all --port 8765` then fails with
|
||||
`listen EADDRINUSE: address already in use 0.0.0.0:8765` (measured on
|
||||
tor-ms22, v1.11.2).
|
||||
`studio-expose` bridge (B). It also warns not to combine B and C on one
|
||||
port, because whichever starts second fails. With `STUDIO_EXPOSE=1`,
|
||||
`/studio --listen-all --port 8765` fails with
|
||||
`listen EADDRINUSE: address already in use 0.0.0.0:8765`. In the other
|
||||
order, `studio-expose` exits 1 on socat's `bind(…): Address already in
|
||||
use` (both measured on tor-ms22, v1.11.2). The same stale "no bind
|
||||
flag" claim is corrected in the three other places that carried it:
|
||||
the `studio-expose` header (and so its `--help`, whose `sed` range
|
||||
grows from `2,31p` to `2,35p`), §7 of the baked `pi-devbox-environment`
|
||||
skill (which also gains the whole-URL, published-port and `curl` notes
|
||||
below), and the `STUDIO_PORT` comment in `Dockerfile.variant`.
|
||||
- **The remote recipe described a pi-studio 0.9 URL.** Since 0.10 the printed
|
||||
URL carries `studioTabState` and `hostedWorkspace` as well as the token, and
|
||||
a token-only URL is answered `409`. The recipe now says to open the whole
|
||||
|
||||
+5
-4
@@ -676,10 +676,11 @@ RUN if [ "${INSTALL_STUDIO}" = "true" ]; then \
|
||||
|
||||
# STUDIO_PORT: advisory default consumed by docker-compose port publishing
|
||||
# and the recommended `/studio --no-browser --port "$STUDIO_PORT"` launch.
|
||||
# Harmless in the non-studio variant. NOTE: pi-studio hard-binds the server
|
||||
# to 127.0.0.1 inside the container (index.ts: .listen(port,"127.0.0.1")),
|
||||
# so reaching it from a browser needs a loopback bridge or host networking —
|
||||
# see the "Using pi-studio" section in README.md.
|
||||
# Harmless in the non-studio variant. NOTE: by default pi-studio binds the
|
||||
# server to 127.0.0.1 inside the container, so reaching it from a browser
|
||||
# needs host networking, the studio-expose loopback bridge, or the opt-in
|
||||
# `/studio --listen-all` (pi-studio >= 0.9.60; never together with the
|
||||
# bridge on one port) — see the "Using pi-studio" section in README.md.
|
||||
ENV STUDIO_PORT=8765
|
||||
|
||||
# ── Optional: Go toolchain ───────────────────────────────────────────
|
||||
|
||||
@@ -261,10 +261,11 @@ publish. Keep the publish on `127.0.0.1:` as in B: anyone who can reach the
|
||||
port and has the full URL controls Studio, including running prompts and
|
||||
reading or writing files, and there is no TLS.
|
||||
|
||||
> **Use B or C on a port, not both.** With `STUDIO_EXPOSE=1` the bridge holds
|
||||
> the container's egress IP on `$STUDIO_PORT` from boot, and `--listen-all` on
|
||||
> that same port fails with `EADDRINUSE` (`0.0.0.0` includes that address).
|
||||
> If the bridge is running, start Studio *without* `--listen-all`.
|
||||
> **Use B or C on a port, not both.** Whichever starts second fails with
|
||||
> `EADDRINUSE`: `0.0.0.0` includes the egress IP the bridge binds. With
|
||||
> `STUDIO_EXPOSE=1` the bridge holds `$STUDIO_PORT` from boot, so
|
||||
> `/studio --listen-all --port 8765` fails. If the bridge is running, start
|
||||
> Studio *without* `--listen-all`.
|
||||
|
||||
### Remote host (SSH / mosh)
|
||||
|
||||
|
||||
@@ -3,13 +3,17 @@
|
||||
# through a published Docker port.
|
||||
#
|
||||
# WHY THIS EXISTS
|
||||
# pi-studio hard-binds its HTTP/WebSocket server to 127.0.0.1 inside the
|
||||
# container (index.ts: `.listen(port, "127.0.0.1")`) and there is no
|
||||
# --host / bind flag. A plain `docker run -p 8765:8765` forwards to the
|
||||
# By default pi-studio binds its HTTP/WebSocket server to 127.0.0.1 inside
|
||||
# the container. A plain `docker run -p 8765:8765` forwards to the
|
||||
# container's EXTERNAL interface (eth0), not its loopback, so it cannot
|
||||
# reach Studio. This helper runs a socat TCP relay that listens on the
|
||||
# container's egress IP and forwards to 127.0.0.1:<port>, so a published
|
||||
# port (and an `ssh -L` tunnel from your laptop) can reach Studio.
|
||||
# reach a default Studio. This helper runs a socat TCP relay that listens
|
||||
# on the container's egress IP and forwards to 127.0.0.1:<port>, so a
|
||||
# published port (and an `ssh -L` tunnel from your laptop) can reach Studio.
|
||||
#
|
||||
# The alternative (pi-studio >= 0.9.60) is `/studio --listen-all`, which
|
||||
# binds 0.0.0.0 and needs no bridge. Use one or the other on a port, never
|
||||
# both: whichever starts second fails with EADDRINUSE (0.0.0.0 includes
|
||||
# the egress IP this relay binds).
|
||||
#
|
||||
# SECURITY
|
||||
# This intentionally exposes Studio beyond loopback — anything that can
|
||||
@@ -34,7 +38,7 @@ set -euo pipefail
|
||||
PORT="${1:-${STUDIO_PORT:-8765}}"
|
||||
|
||||
if [ "$PORT" = "--help" ] || [ "$PORT" = "-h" ]; then
|
||||
sed -n '2,31p' "$0" | sed 's/^# \{0,1\}//'
|
||||
sed -n '2,35p' "$0" | sed 's/^# \{0,1\}//'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
@@ -356,8 +356,8 @@ window: 0". Leave the indexing alone in this environment.
|
||||
## 7. pi-studio reachability (only in the `-studio` variant)
|
||||
|
||||
Present only if `/opt/pi-studio` exists / the `studio_*` tools are in your tool
|
||||
list. pi-studio **binds to `127.0.0.1` inside the container** with no host-bind
|
||||
flag, so a plain `docker -p` publish can't reach it. Two supported paths:
|
||||
list. By default pi-studio **binds to `127.0.0.1` inside the container**, so a
|
||||
plain `docker -p` publish can't reach it. Three supported paths:
|
||||
|
||||
- **Host networking** (`network_mode: host`): container loopback == host
|
||||
loopback; open the tokenized URL on the host. (Changes
|
||||
@@ -365,10 +365,25 @@ flag, so a plain `docker -p` publish can't reach it. Two supported paths:
|
||||
- **`studio-expose` bridge** (`STUDIO_EXPOSE=1` or run `studio-expose &`): a
|
||||
`socat` relay from the container's external interface to its loopback, so a
|
||||
published `127.0.0.1:PORT` + `ssh -L PORT:127.0.0.1:PORT host` reaches it.
|
||||
- **`/studio --listen-all`** (pi-studio ≥ 0.9.60): binds `0.0.0.0`, so the
|
||||
published port reaches it with no bridge; the printed URL still says
|
||||
`127.0.0.1`. **Never on the same port as the bridge**: whichever starts
|
||||
second fails with `EADDRINUSE`. `ss -ltnp | grep ":$STUDIO_PORT"` showing a
|
||||
`socat` line means the bridge is up, so start Studio without `--listen-all`.
|
||||
|
||||
The real auth token comes from the `/studio` slash command (`/studio --status`
|
||||
to reprint), **not** from `studio-expose`. For Graphviz, use `dot-watch` →
|
||||
PNG (Studio renders Mermaid natively and previews PNG, but not SVG/DOT).
|
||||
to reprint), **not** from `studio-expose`. Hand over the **whole** printed
|
||||
URL: since pi-studio 0.10 it also carries `studioTabState` + `hostedWorkspace`
|
||||
(or `docPath`/`watchFile`/… for `--watch`), and a token-only URL is answered
|
||||
`409`. The URL wraps across TUI lines; if a side panel's text lands inside the
|
||||
copy, Studio answers *"This link looks damaged…"*. Studio must run on the
|
||||
**published** port (only the laptop side of `ssh -L` is free to choose), and
|
||||
`--port` on a running server only warns, so `/studio --stop` first. On the
|
||||
Docker host, `curl -s http://127.0.0.1:$STUDIO_PORT/` answering `403` means
|
||||
the chain is up; an empty reply means Studio is down or on another port.
|
||||
|
||||
For Graphviz, use `dot-watch` → PNG (Studio renders Mermaid natively and
|
||||
previews PNG, but not SVG/DOT).
|
||||
|
||||
## 8. MemPalace is the shared brain
|
||||
|
||||
|
||||
Reference in New Issue
Block a user