You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add a tunnel client mode so a JSS pod can dial out to an existing JSS relay and be exposed publicly — the inverse of the relay we already ship.
src/tunnel/index.js (tunnelPlugin, enabled by jss start --tunnel) is the relay/server half: it accepts WebSocket clients at wss://<pod>/.tunnel, proxies public HTTP (https://<pod>/tunnel/{name}/…) down the socket, and relays responses back. Registration is WebID-authenticated and the wire protocol is fully specified in the file header.
What's missing is the client half: a mode (e.g. jss start --tunnel-connect wss://<relay>/.tunnel --tunnel-name <name>) where, after the local pod is listening, JSS opens an outbound WS to the relay, registers, and forwards each proxied request to its own http://localhost:<port>.
Why
Exposes a pod behind CGNAT / on mobile (no public IP, no port-forwarding) — it's a single outbound connection.
Operator already runs a JSS --tunnel relay in the cloud; only the client is needed to connect to it.
Scope (the client)
Against the protocol already defined in src/tunnel/index.js:
Open a WS to the relay's /.tunnel (with auth — see below).
Send register with a name → receive the registered public path.
On each request frame ({ id, method, path, headers, body }) → fetch('http://localhost:<podport>' + path, …) against the local pod → reply with a response frame ({ id, status, headers, body }).
Reconnect with backoff (mobile networks flap); re-register on reconnect.
New option(s): --tunnel-connect <wss-url>, --tunnel-name <name>, plus the auth credential.
Open questions
Relay auth for the client./.tunnel requires a WebID today (getWebIdFromRequestAsync on the upgrade). The outbound client needs a credential the relay accepts:
Pre-shared tunnel token configured on both ends — simplest for a self-hosted relay; likely needs a small relay-side addition to accept it.
Solid-OIDC token — client authenticates to the relay's IdP and presents the bearer. Cleaner, more moving parts.
Path vs subdomain. Relay is path-based today (/tunnel/<name>/), so the tunneled pod's WebID becomes https://<relay>/tunnel/<name>/profile/card#me — works for reachability but trips Solid apps that assume a root-hosted pod. Subdomain (https://<name>.<relay>/) is cleaner for identity but needs wildcard DNS + TLS on the relay.
Stable name so the public URL / WebID / issuer doesn't churn between sessions.
Notes
Mobile lifecycle: the tunnel lives only while the pod runs — fine on Android (foreground service keeps it alive), not viable on iOS (background limits).
Summary
Add a tunnel client mode so a JSS pod can dial out to an existing JSS relay and be exposed publicly — the inverse of the relay we already ship.
src/tunnel/index.js(tunnelPlugin, enabled byjss start --tunnel) is the relay/server half: it accepts WebSocket clients atwss://<pod>/.tunnel, proxies public HTTP (https://<pod>/tunnel/{name}/…) down the socket, and relays responses back. Registration is WebID-authenticated and the wire protocol is fully specified in the file header.What's missing is the client half: a mode (e.g.
jss start --tunnel-connect wss://<relay>/.tunnel --tunnel-name <name>) where, after the local pod is listening, JSS opens an outbound WS to the relay, registers, and forwards each proxied request to its ownhttp://localhost:<port>.Why
crypto.subtleconstraints that currently force same-origin-only sign-in (see js-pod/android Add Git support for containers #5/Phase 2: Link did:nostr to WebID profiles (owl:sameAs) #6). External Solid apps could then reach a phone-hosted pod.--tunnelrelay in the cloud; only the client is needed to connect to it.Scope (the client)
Against the protocol already defined in
src/tunnel/index.js:/.tunnel(with auth — see below).registerwith a name → receive the registered public path.requestframe ({ id, method, path, headers, body }) →fetch('http://localhost:<podport>' + path, …)against the local pod → reply with aresponseframe ({ id, status, headers, body }).--tunnel-connect <wss-url>,--tunnel-name <name>, plus the auth credential.Open questions
/.tunnelrequires a WebID today (getWebIdFromRequestAsyncon the upgrade). The outbound client needs a credential the relay accepts:/tunnel/<name>/), so the tunneled pod's WebID becomeshttps://<relay>/tunnel/<name>/profile/card#me— works for reachability but trips Solid apps that assume a root-hosted pod. Subdomain (https://<name>.<relay>/) is cleaner for identity but needs wildcard DNS + TLS on the relay.Notes