Skip to content

feat: support Portal Tunnel as a remote-access backend #202

Closed

Description

@gosunuts

Problem

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.

Where

No response

Workarounds and alternatives

No response

Activity

  1. devswha commented on Sep 30, 2026

    @devswha
    Owner

    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:

    1. 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.
    2. 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.

  2. rabbitson87 commented on Oct 1, 2026

    @rabbitson87
    Contributor

    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.

    Does that fit what you had in mind?

  3. gosunuts commented on Oct 10, 2026

    @gosunuts
    Author

    @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:

    • Detect an installed Portal binary.
    • Show the public HTTPS URL and QR code.
    • Optionally provide Start/Stop controls.
    • Require an access token before public exposure.
    • Reuse the existing authentication and process-management patterns.

    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.

  4. devswha commented on Oct 13, 2026

    @devswha
    Owner

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions