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
{{ message }}
Repository navigation
feat: support Portal Tunnel as a remote-access backend #202
Remote phone access currently centers on Tailscale. herdr-web-ui already supports reverse-proxy/public-domain access, but there is no simple built-in path for exposing the local server through an account-free public tunnel.
Portal Tunnel could provide that optional path while keeping the server bound to 127.0.0.1.
Proposal
Consider supporting Portal Tunnel as an optional remote-access backend alongside the existing Tailscale flow.
"herdr-web-ui" already supports public-domain / reverse-proxy access, and Portal can expose the existing loopback server directly:
portal expose 7317
This provides a public HTTPS/WSS endpoint while keeping "herdr-web-ui" bound to "127.0.0.1:7317". Portal also supports forwarded headers and WebSocket upgrades, so it should fit the current reverse-proxy path without changing the server architecture.
Possible scope:
document manual Portal setup first;
optionally add Portal under Settings → Phone / Remote access later, including the public URL and QR code;
keep Tailscale as the existing private-network option rather than replacing it.
For safety, public exposure should require "HERDR_WEB_TOKEN" or an already-paired device before opening the tunnel.
Thanks, this is a well-scoped proposal, and I'd like to support it. Keeping the server on 127.0.0.1 and putting Portal in front fits the existing reverse-proxy path.
One thing needs care first. Today the server locks to paired devices only after the first pairing, so a public URL opened before that point would let anyone pair first. The plan I have in mind:
Docs first: a short Portal section in the remote-access guide. It will say to pair your phone (or set HERDR_WEB_TOKEN) before running portal expose.
Later, in the app: an optional Portal entry under Settings → Phone. It would show the public URL and QR code, and it would refuse to open the tunnel until a device is paired or a token is set.
Tailscale stays the default private option. A PR for step 1 is welcome if you'd like to take it.
Thanks, that plan sounds good. I'm preparing step 1. Before writing it I traced how herdr's access check behaves behind Portal, and the plain portal expose 7317 can't be documented as it is. This is from reading both codebases; I haven't run it through a public relay yet.
portal expose 7317 ends TLS in the portal process and copies the bytes to 127.0.0.1:7317 unchanged, so no X-Forwarded-For is added. herdr takes a loopback connection with no X-Forwarded-For for "this computer" (decideAccess in server/access.ts), so with no token set a visitor through the tunnel gets in as the local owner, whether or not a device is paired. That also breaks the guide's rule that a proxy must send X-Forwarded-For.
portal expose --http-route /=127.0.0.1:7317 (routed mode) does send X-Forwarded-For, but it rewrites Host to 127.0.0.1:7317 and sends X-Forwarded-Proto: http. sameOrigin in server/machine-security.ts compares the browser's Origin (https://<name>.<relay>) with the request URL, which comes from the Host header and is only treated as https when x-forwarded-proto: https arrives. As I read it, /ws and every POST (pairing and token sign-in included) would get 403. The bare command sends no x-forwarded-proto either, so a browser fails the same check there.
So I'll fix Portal first: routed mode will keep the browser's Host for a local upstream and send X-Forwarded-Proto: https (a PR to gosuda/portal-tunnel). Once that's released I'll open the docs PR here: a short section under On your phone that closes the gate first (a token, or pairing over another address) and then uses portal expose --http-route …, with Tailscale staying the default. I'd also correct the guide's line saying x-forwarded-proto is only needed for Secure cookies, since the origin check needs it too.
Done in #746: Settings → Phone & devices → Portal detects an installed Portal, requires an access token, and has Start/Stop with the public address and its QR code. It is on main and ships with the next release. The manual setup is in the guide since #229.
Activity
devswha commentedon Sep 30, 2026
Thanks, this is a well-scoped proposal, and I'd like to support it. Keeping the server on
127.0.0.1and putting Portal in front fits the existing reverse-proxy path.One thing needs care first. Today the server locks to paired devices only after the first pairing, so a public URL opened before that point would let anyone pair first. The plan I have in mind:
HERDR_WEB_TOKEN) before runningportal expose.Tailscale stays the default private option. A PR for step 1 is welcome if you'd like to take it.
rabbitson87 commentedon Oct 1, 2026
Thanks, that plan sounds good. I'm preparing step 1. Before writing it I traced how herdr's access check behaves behind Portal, and the plain
portal expose 7317can't be documented as it is. This is from reading both codebases; I haven't run it through a public relay yet.portal expose 7317ends TLS in theportalprocess and copies the bytes to127.0.0.1:7317unchanged, so noX-Forwarded-Foris added. herdr takes a loopback connection with noX-Forwarded-Forfor "this computer" (decideAccessinserver/access.ts), so with no token set a visitor through the tunnel gets in as the local owner, whether or not a device is paired. That also breaks the guide's rule that a proxy must sendX-Forwarded-For.portal expose --http-route /=127.0.0.1:7317(routed mode) does sendX-Forwarded-For, but it rewritesHostto127.0.0.1:7317and sendsX-Forwarded-Proto: http.sameOrigininserver/machine-security.tscompares the browser'sOrigin(https://<name>.<relay>) with the request URL, which comes from theHostheader and is only treated as https whenx-forwarded-proto: httpsarrives. As I read it,/wsand every POST (pairing and token sign-in included) would get 403. The bare command sends nox-forwarded-protoeither, so a browser fails the same check there.So I'll fix Portal first: routed mode will keep the browser's
Hostfor a local upstream and sendX-Forwarded-Proto: https(a PR to gosuda/portal-tunnel). Once that's released I'll open the docs PR here: a short section under On your phone that closes the gate first (a token, or pairing over another address) and then usesportal expose --http-route …, with Tailscale staying the default. I'd also correct the guide's line sayingx-forwarded-protois only needed for Secure cookies, since the origin check needs it too.Does that fit what you had in mind?
docs(guide): a public HTTPS address with Portal
docs(guide): a public HTTPS address with Portal
docs(guide): a public HTTPS address with Portal
docs(guide): a public HTTPS address with Portal
docs(guide): a public HTTPS address with Portal
docs(guide): a public HTTPS address with Portal (#229)
gosunuts commentedon Oct 10, 2026
@devswha Thanks for merging the Portal setup guide in #229!
Would you be open to a follow-up PR that adds Portal integration directly to Settings → Phone & devices?
I'd like to keep it minimal and reuse the existing UI and Portal CLI:
Would you prefer a read-only setup flow with a copyable command, similar to Tailscale, or direct Start/Stop controls?
Happy to follow whichever approach fits the project's architecture better.
feat(settings): give this PC a public address through Portal (#746)
devswha commentedon Oct 13, 2026
Done in #746: Settings → Phone & devices → Portal detects an installed Portal, requires an access token, and has Start/Stop with the public address and its QR code. It is on
mainand ships with the next release. The manual setup is in the guide since #229.