Remote Connections and Pairing
Mobile, Desktop on another computer, and TUI / WebUI can connect to a Gateway on your computer. The client owns input and output; the Gateway and Backend Agent stay on the host. Desktop is not required as a relay.
These steps follow development on
main. Check that both builds include remote pairing.
1. Choose a Connection Method
By default, the Gateway binds to loopback and trusts only literal loopback Host/Origin. Remote requests require a Gateway access credential before they can reach HTTP or WebSocket business APIs. Do not expose the Gateway's loopback port directly to the public Internet.
Clients always use the WebSocket endpoint and device token stored in their connection code. Network publication and Gateway pairing/device authorization are independent layers. The Gateway has only three run modes: local, LAN, and Tailnet.
- LAN is intended for hardware and native Clients on the same trusted Wi-Fi. The Gateway explicitly binds to the LAN, prefers a physical-interface IPv4 address, and advertises a direct
ws://endpoint. Never forward this endpoint to the public Internet. - Private Tailnet is intended for personal computers. Install official Tailscale on both the Gateway host and remote device, and sign in to the same tailnet. The Gateway invokes the system
tailscale servecommand to publish a private HTTPS endpoint.
2. Start the Endpoint
For direct access on the same LAN:
qwenaudio gateway --lanThis binds the Gateway to 0.0.0.0, while the connection code contains the selected physical-interface IPv4 rather than the unusable wildcard address. Use qwenaudio gateway install --lan for a persistent service, or set QWEN_AUDIO_GATEWAY_LAN=1. On a host with multiple physical interfaces, set QWEN_AUDIO_GATEWAY_LAN_HOST=192.168.x.x to select one explicitly.
After installing and signing in to official Tailscale, run the Gateway in the foreground:
qwenaudio gateway --tailnetThe command waits for tailscale serve to print its private HTTPS endpoint and stops that publication when the Gateway exits. For a persistent user service, run qwenaudio gateway install --tailnet, or put this in config.env:
QWEN_AUDIO_GATEWAY_TAILNET=1A reverse proxy is not a Gateway run mode. Keep the default local mode when the proxy runs on the same host; use --lan when the proxy runs on another machine. After configuring the proxy, override the public endpoint only when generating the connection code:
qwenaudio gateway pair --endpoint https://voice.example.com --name "AI Passport"A fixed IP with a publicly trusted IP-address certificate can be used as https://<fixed-ip>. The endpoint must be an HTTPS origin without credentials, path, query, or fragment. The proxy must accept HTTPS only, forward WebSocket correctly, preserve the public Host, and forward traffic to 127.0.0.1:3101 on the same host or the Gateway's LAN address. Also set Forwarded or X-Forwarded-For. Forwarded requests do not receive the local authentication exemption and still require pairing or access credentials; these headers never establish identity. Do not strip both the public Host and all forwarding headers, as the Gateway cannot then distinguish proxy traffic from genuinely local requests.
Tailnet is marked ready only after tailscale serve status --json confirms a private HTTPS root proxy to the current Gateway. A login or consent URL printed by the CLI does not indicate readiness. Complete first-time authorization through official Tailscale.
3. Connect a Client
After the endpoint is ready, open another terminal on the Gateway host and run:
qwenaudio gateway pair --name "AI Passport"The Gateway host directly issues an independent, revocable device token. The small QR contains a URL such as https://gateway/c#credential (or http://IP/c#credential on LAN) and uses it as the only connection code. Scanning it opens the Gateway WebUI even without an installed Client; installed Clients can scan or paste the same code. The Gateway no longer generates or returns a long qwaudio://connect#... deep link. The credential is shown once.
Desktop, Mobile, and other native Clients save the credential, then use one WebSocket connection for authentication, session negotiation, voice, Tasks, history, and approvals—there is no HTTPS pairing exchange. The browser shell exchanges the device token in the fragment for an HttpOnly cookie; the fragment is never included in an HTTP request or access log. The flow is identical for LAN, Tailnet, and a pair --endpoint override. Use qwenaudio gateway devices to list Clients and qwenaudio gateway revoke <device-id> to revoke one. During a rolling upgrade, only older Clients need qwenaudio gateway pair --legacy to generate a short-lived, single-use pairing code.
In Desktop, paste the complete connection code into Settings → Application → Gateway and click Apply to save and connect. The same field accepts local or previously saved remote Gateway URLs; there is no separate remote-connection setting.
LAN and remote access do not bypass Gateway authentication: the WebSocket handshake must carry the device credential.
Verify the Connection
- Check Gateway connectivity and then voice-frontend status. Importing a code does not validate model credentials.
- Allow microphone access on the phone. Tailscale provides network reachability, not Gateway authorization.
- When a second client takes over, the previous client disconnects; the Gateway itself has not exited.
- If a code leaks or a device changes, revoke the old device and rerun
qwenaudio gateway pairon the Gateway host. - If a Tailnet endpoint is unreachable, check that both devices are online in the same tailnet, then check policies and HTTPS publication.
See Mobile and Desktop for client steps, or Troubleshooting for other errors.
Advanced Authentication and Reverse Proxies
For one personal access key:
QWEN_AUDIO_GATEWAY_ACCESS_TOKEN=replace-with-at-least-24-random-charactersGenerate one with openssl rand -base64 32. This token authenticates Gateway access only; never put it in a URL, GCP message, or public log.
Native clients send it as a Bearer token in the WSS handshake. Browser clients carry the same token through the WebSocket subprotocol. To serve the browser UI through a external HTTPS reverse proxy, keep the Gateway on loopback and allowlist the exact public Origin:
HOST=127.0.0.1
QWEN_AUDIO_AGENT_ALLOWED_ORIGINS=https://voice.example.comFor example, a native TUI can connect without putting the credential in its URL:
QWEN_AUDIO_AGENT_URL=https://voice.example.com \
QWEN_AUDIO_GATEWAY_CLIENT_TOKEN="$ACCESS_TOKEN" \
qwenaudio tuiqwenaudio gateway pair uses the loopback-only POST /api/access/devices management endpoint to issue a direct device connection code. Devices can be listed with GET /api/access/devices and revoked with DELETE /api/access/devices/:id; revocation immediately closes active WSS connections. The short-lived pairing endpoints remain for compatibility, but new Clients do not depend on them.
Multiple trusted Origins can be separated by commas. Advanced hosts can map separate access tokens to separate owner identities:
QWEN_AUDIO_AGENT_ACCESS_KEYS='[{"token":"replace-with-a-long-random-token","owner_id":"user_alice","label":"Alice"}]'Each owner has one active Client lease. A second Client is rejected unless it reconnects with the same client.instance_id or explicitly negotiates session.takeover; takeover closes the previous Client and generation-fences late messages from its socket.
QWEN_AUDIO_AGENT_AUTH_SECRET only signs local and remote session identities. It is not a remote access password and must never be sent to a Client.
QWEN_AUDIO_AGENT_ACCESS_TOKEN remains a deprecated alias for both settings. New setups use the separate host and Client names above so a Client credential is never mistaken for Gateway server configuration.