ai-eks/dsh-auth-tunnel ↗★ 4

dsh-auth-tunnel

Password-gated public access for the Web GUI via Cloudflare Tunnel: a loopback password gate (login page + HMAC cookie) in front of the webserver, published by spawning cloudflared in quick or named-tunnel mode - tells the shell and the model the public URL 提供登录页面、HMAC Cookie验证及内网穿透,适合需要将本地Web GUI安全发布到公网的用户。

Package
dsh-auth-tunnel
Compatibility
Unverified
Harness peer range
^0.2.0-rc.2
Cordis peer range
^4.0.4
Version
0.2.0-rc.2
License
MIT
Last updated
Oct 5, 2026

Install

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:ai-eks/dsh-auth-tunnel

Usage

Prerequisites

  • The dsh CLI and pnpm are available on PATH; the plugin command creates the Web profile when it is missing.
  • cloudflared available on PATH, or an absolute executable configured for the plugin.
  • A long, random shared password stored as a DSH credential.

Install

Install the latest published prerelease bundle from npm:

dsh plugin --profile web add dsh-auth-tunnel@next

Or install the current sources from Git:

dsh plugin --profile web add github:ai-eks/dsh-auth-tunnel

This release targets DeepSeek Harness 0.2.0-rc.2 (the 0.2.0 prerelease), using its volatile Config fields, configuration forms, and Plugins bundle page. Older Harness versions must pin a compatible package version, immutable tag, or revision:

dsh plugin --profile web add 'github:ai-eks/dsh-auth-tunnel#6e521da3a4899849937411dd1c341369205c96d6' # Harness 0.1.7-rc.2
dsh plugin --profile web add dsh-auth-tunnel@0.1.7-rc.1 # Harness 0.1.7-rc.1
dsh plugin --profile web add dsh-auth-tunnel@0.1.5-rc.1 # Harness 0.1.2-rc.1 / 0.1.3-alpha.2 / 0.1.5-rc.1
dsh plugin --profile web add dsh-auth-tunnel@0.1.1-rc.2.1 # Harness 0.1.1-rc.2
dsh plugin --profile web add 'github:ai-eks/dsh-auth-tunnel#v0.1.0-rc.8' # Harness rc.8
dsh plugin --profile web add 'github:ai-eks/dsh-auth-tunnel#b4baea7c47f5c245da789d3553d41938df89b311' # Harness rc.7
dsh plugin --profile web add 'github:ai-eks/dsh-auth-tunnel#v0.1.0-rc.6' # Harness rc.6

Git installs build the checked-out sources through prepare. pnpm 10 and later may first ask you to allow that build in the profile's pnpm-workspace.yaml; follow the path and exact package key printed by dsh and then rerun the command.

For a local checkout, build it before adding the path:

cd /path/to/dsh-auth-tunnel
pnpm install
dsh plugin --profile web add .

The bundle inserts and enables the auth-tunnel row in quick mode and replaces the Host-native directory picker with the in-app browser picker. No deepseek-harness source edit or extra profile row is required.

Quick mode

Quick mode is the default. Store the shared password in $DSH_HOME/.credentials.yaml ($DSH_HOME defaults to ~/.dsh):

DSH_WEB_PASSWORD: 'replace-with-a-long-random-password'

Start the Web profile:

dsh web

Starting before DSH_WEB_PASSWORD is configured no longer fails the Web profile. The plugin stays mounted with an error status and starts the tunnel automatically after that credential is added.

After the tunnel is ready, the terminal prints:

cloudflare tunnel: https://.trycloudflare.com

Open that URL and enter DSH_WEB_PASSWORD on the login page. Share the URL, not the password. The active row also appears in Web Plugins.

Web settings

With the Loader auth-tunnel row enabled, open Plugins → dsh-auth-tunnel to edit every option. Saving the Enable public tunnel switch immediately starts or stops the gate and cloudflared while keeping this card available. The card also shows applying, running, stopped, or failed state and the current public URL.

Allow remote pages to change settings is enabled by default. The shared access password is an administrator credential: a signed-in public page can read and save the Auth Tunnel card and Language preference without local setup. Disable this switch if authenticated public pages should not manage the tunnel itself; enabling it again then requires a local page or the settings document. These writes use authenticated endpoints owned by this plugin. Configuration changes persist in the active profile’s cordis.patch.yml. The switch is a separate fence from the core Host configuration plane: the gate proxies settings.*, credentials.*, and llm.* straight to the Host for every authenticated public page, except that core settings writes targeting the auth-tunnel namespace are rejected and must use the fenced plugin endpoint. The bundle's immediate client entry publishes that authenticated route before configuration forms classify the browser. The public GUI therefore keeps full configuration parity with the local one — responses come back redacted, and a secret crosses the wire only inside a write payload. Only one remote write is accepted at a time, and writes attempted while a previous change is applying return a conflict so the page can reload and retry. A remote page cannot save a change that would allocate a new random Quick URL (switching to Quick, or changing the Quick gate port or executable); make that change locally so the new URL remains discoverable. Turning the switch off remotely completes that save before access closes.

The card updates the credential named by the currently saved passwordRef through a separate Update password button. Access-password and configuration changes are never submitted together. In Token mode, paste a Tunnel Token directly and Save configuration writes it one-way to the credential named by tokenRef, which defaults to DSH_TUNNEL_TOKEN. Both secret inputs clear after a successful write, and neither the Host nor the page returns or displays the literal. To change passwordRef, create that credential first and save the reference before updating its password.

Related settingQuickToken
Access passwordRequired and shared by both modes; updated separately through the write-only buttonRequired and shared by both modes; updated separately through the write-only button
Tunnel TokenNot usedRequired; paste it directly to store it under tokenRef
Public hostnameNot used; a temporary trycloudflare.com URL is assignedRequired; enter the hostname bound in Cloudflare
Gate portKeep 0 for automatic allocationFixed 1–65535, matching Cloudflare ingress

Saved values apply automatically without restarting DeepSeek Harness. passwordRef and sessionTtlHours update in place; tunnel-level changes such as mode, tokenRef, gatePort, or executable start a candidate and then replace only the plugin's gate or cloudflared. If the candidate cannot start, the card reports the error and keeps the previous tunnel. A successful switch can briefly interrupt the public page; open the newly displayed URL and reload before retrying a failed operation. Switching back to Quick preserves the Token-mode fields for a later switch, and Quick ignores them. Keep the Loader row enabled for normal on/off control: setting Loader disabled: true unloads both the Host auth-tunnel settings namespace and its card.

Named tunnel mode

Use token mode when the public hostname must remain stable. Create a named Cloudflare Tunnel, bind a hostname such as gui.example.com, and point its dashboard ingress at a fixed loopback gate such as http://127.0.0.1:7677.

Paste the Tunnel Token directly in the Web settings card, or pre-store both credentials in $DSH_HOME/.credentials.yaml:

DSH_WEB_PASSWORD: 'replace-with-a-long-random-password'
DSH_TUNNEL_TOKEN: 'eyJhIjo...'

Override the bundle row in $DSH_HOME/profiles/web/cordis.patch.yml:

- id: auth-tunnel
  disabled: false
  config:
    enabled: true
    mode: token
    tokenRef: DSH_TUNNEL_TOKEN
    publicHostname: gui.example.com
    gatePort: 7677

publicHostname is only the DNS hostname: do not include https://, a port, or a path. The configuration and Tunnel Token can both be entered and applied immediately through the Web settings card; the Token only enters the credential service and is never stored in settings or echoed. After changing gatePort, the Cloudflare Dashboard ingress must still point at the same port.

Configuration reference

KeyTypeDefaultEffect
enabledbooleantrueWhether the password gate and cloudflared run; saving false immediately stops public access while keeping settings available.
allowRemoteSettingsbooleantrueWhether authenticated public pages may update Auth Tunnel settings, its write-only access password, and the Language preference.
passwordRefstring (credential-ref)DSH_WEB_PASSWORDCredential reference resolving to the shared access password; when unconfigured, the plugin stays mounted and starts automatically after the credential is added.
sessionTtlHoursnumber ≥ 0.01720Cookie lifetime in hours (30 days).
modequick | tokenquickEphemeral quick tunnel or named token tunnel.
tokenRefstring (credential-ref)DSH_TUNNEL_TOKENTunnel Token reference; token mode only.
publicHostnameDNS hostname—Named-tunnel hostname without scheme, port, or path; token mode only.
gatePortinteger 0…655350Loopback gate port; token mode requires a fixed non-zero value.
executablestringcloudflaredcloudflared PATH name or absolute path.
startupTimeoutMsinteger ≥ 115000How long activation waits for tunnel readiness.

Configuration reference

KeyTypeDefaultEffect
enabledbooleantrueWhether the password gate and cloudflared run; saving false immediately stops public access while keeping settings available.
allowRemoteSettingsbooleantrueWhether authenticated public pages may update Auth Tunnel settings, its write-only access password, and the Language preference.
passwordRefstring (credential-ref)DSH_WEB_PASSWORDCredential reference resolving to the shared access password; when unconfigured, the plugin stays mounted and starts automatically after the credential is added.
sessionTtlHoursnumber ≥ 0.01720Cookie lifetime in hours (30 days).
modequick | tokenquickEphemeral quick tunnel or named token tunnel.
tokenRefstring (credential-ref)DSH_TUNNEL_TOKENTunnel Token reference; token mode only.
publicHostnameDNS hostname—Named-tunnel hostname without scheme, port, or path; token mode only.
gatePortinteger 0…655350Loopback gate port; token mode requires a fixed non-zero value.
executablestringcloudflaredcloudflared PATH name or absolute path.
startupTimeoutMsinteger ≥ 115000How long activation waits for tunnel readiness.