Pulse/docs/RELAY.md
rcourtman b69c8c8007 Wire PULSE_RELAY_ENABLED and PULSE_RELAY_SERVER as real env overrides
These two env vars were documented as relay overrides in v6 docs since
March 18 (CONFIGURATION.md, RELAY.md, and the frontend-served doc copy)
but no code ever read them. Operators trying to bootstrap relay headlessly
saw no effect.

Implement them rather than remove the documentation. Headless and
container deployments now have a real path to enable relay and point it
at a private endpoint without going through Settings → Relay.

internal/relay/config_env.go:
  - ApplyEnvOverrides(*Config) mutates relay.Config in place.
  - PULSE_RELAY_ENABLED accepts true/false/yes/no/1/0/on/off (case-
    insensitive). Unrecognized values log a warning and leave the file
    value untouched — important so "unset" reads differently from
    "explicit false."
  - PULSE_RELAY_SERVER goes through the existing validateRelayServerURL
    check; invalid URLs log a warning and fall through.

internal/config/persistence_relay.go:
  LoadRelayConfig calls ApplyEnvOverrides after the file load and after
  the default-fallback when relay.enc is absent, so the env override
  applies on every load.

Tests cover unset / true / false / garbage-bool / valid-URL / invalid-URL
/ both-together / nil-config paths in the relay package, plus two
end-to-end tests in internal/config that prove the override flows through
LoadRelayConfig against a real persisted file and against the
missing-file default branch.

Restore the env-var docs with the correct default URL (the full
wss://relay.pulserelay.pro/ws/instance, not the bare hostname the
original aspirational table claimed) and add an explicit precedence note:
saving from the UI after an env override persists the env-effective state
to disk, so clearing the env alone does not revert.

Add internal/relay/config_env_test.go to the relay-runtime registry's
desktop-relay-runtime exact_files so the new code surface is proof-tracked.
Update the matching pin in subsystem_lookup_test.py. Extend the
relay-runtime contract Extension Point 3 to document the override
semantics LoadRelayConfig must satisfy.
2026-05-12 11:18:31 +01:00

5 KiB

Relay / Pulse Mobile Handoff (Relay and Above)

Pulse Relay provides end-to-end encrypted remote access foundations for Pulse instances. It allows secure remote connectivity without exposing your Pulse server to the public internet.

Supported Pulse Mobile clients pair from Settings → Relay using a QR code or deep link and connect through Pulse Relay over end-to-end encrypted remote access.

How It Works

┌──────────┐         ┌──────────────┐         ┌──────────┐
│  Pulse    │◄──E2E──►│  Relay       │◄──WSS──►│  Pulse   │
│  Mobile   │  ECDH   │  Server      │         │  Server  │
└──────────┘         └──────────────┘         └──────────┘
  1. Your Pulse server maintains a persistent WebSocket connection to the relay server.
  2. A mobile client connects to the relay server and authenticates.
  3. An ECDH key exchange creates a per-channel encryption key.
  4. Tunneled remote-access traffic is encrypted end-to-end — the relay server never sees plaintext data.

Quick Start

  1. Go to Settings → Relay.
  2. Toggle relay On.
  3. Use the QR Code or Deep Link to pair a supported Pulse Mobile client.
  4. Your paired mobile client connects through relay.

Requirements

  • Relay, Pro, legacy Pro+, or Cloud license — relay is gated by the relay feature key.
  • Outbound WebSocket — Pulse must be able to reach relay.pulserelay.pro (port 443).
  • No inbound ports — you do not need to open any ports on your firewall.

Security

Relay was designed with a zero-trust model:

Property Detail
Encryption End-to-end ECDH key exchange per channel
Plaintext Relay server never sees your monitoring data
Authentication Per-session mobile authentication
Back-pressure Data limiters prevent channel flooding
License-gated Requires an active Relay-or-higher license
Configurable Can be enabled/disabled at any time via Settings
Audit Relay connection events are logged to the audit trail

Configuration

UI

Settings → Relay — toggle on/off, view QR code, and manage relay pairing sessions.

Environment Variables

For headless / container deployments, two env vars override the persisted relay.enc values at load time. Unset leaves the file value untouched.

Variable Description Default
PULSE_RELAY_ENABLED Enable/disable relay (true/false/yes/no/1/0). Unrecognized values are ignored. (unset)
PULSE_RELAY_SERVER Override relay server URL. Must be ws:// or wss://. Invalid values are logged and ignored. wss://relay.pulserelay.pro/ws/instance

Env vars take precedence over the file at load. Saving from the UI after an env override is active persists the env-effective state to disk, so clearing the env var alone will not revert the change — disable in the UI too.

Storage

Relay configuration is stored encrypted in relay.enc in the Pulse data directory.

API Reference

Method Endpoint Scope Description
GET /api/settings/relay settings:read Get relay status and config
PUT /api/settings/relay settings:write Update relay settings
POST /api/onboarding/qr settings:read Generate mobile onboarding QR code
POST /api/onboarding/deep-link settings:read Generate mobile deep link

Pulse Mobile Pairing

iOS / Android

  1. Join mobile early access when available.
  2. Open Pulse Mobile and tap Connect to Server.
  3. Scan the QR code from Settings → Relay in your Pulse web UI.
  4. The app connects via the relay for push notifications and secure Open Pulse handoff.

Multiple Servers

Pulse Mobile can pair with multiple Pulse instances. Each pairing has its own encrypted channel.

Troubleshooting

Relay showing "Disconnected"

  1. Confirm your Relay, Pro, grandfathered Pro+, or Cloud license is active (Settings → Plans).
  2. Verify the Pulse server can reach the relay server:
    curl -s https://relay.pulserelay.pro/healthz
    
  3. Check Pulse logs for relay errors:
    journalctl -u pulse | grep -i relay
    # or
    docker logs pulse | grep -i relay
    

Pulse Mobile can't connect

  1. Verify relay is enabled in Settings → Relay.
  2. Confirm your mobile account has beta access.
  3. Re-scan the QR code — sessions can expire.
  4. Ensure your mobile device has internet access.

Open Pulse handoff not loading

  1. Check the relay connection status in Settings → Relay.
  2. Look for WebSocket reconnection messages in Pulse logs.
  3. Restart Pulse Mobile.

See Also