Preview URLs

Relay stores a preview URL for every deploy.

You can run Relay in direct host-port mode or let Relay manage host routing through its built-in Caddy global proxy. The dashboard and CLI use the preview URL stored on the deploy record, so it helps to understand where that value comes from.

Two common shapes
Port mode:  http://127.0.0.1:3005
Host mode:  https://app-main.preview.example.com
Port mode

The simplest setup maps a host port directly to the app container.

This is the easiest mode to start with locally. The agent launches the app container with a host port mapping and stores a preview URL like `http://127.0.0.1:<port>`.

CLI deploy
relay deploy --host-port 3005 --stream
Host mode

If RELAY_BASE_DOMAIN is set, the agent can derive preview hostnames automatically.

In host mode, Relay runs a per-app edge proxy for the app slot and a global Caddy proxy for public domains. Relay can derive `<app>-<branch>.<base-domain>` as the public preview host, and this is also where blue-green traffic switching happens.

Set `RELAY_BASE_DOMAIN=preview.example.com` on the agent.

Optional but recommended: set `RELAY_DASHBOARD_HOST=admin.preview.example.com` so the Relay dashboard has its own hostname.

Make sure DNS points both the dashboard host and app hosts at the same server IP.

Relay stores the derived public host on the app state and the deploy record.

Derived host
RELAY_BASE_DOMAIN=preview.example.com

site-demo-main.preview.example.com
Slot routing

Host mode uses blue-green slots behind the edge proxy.

The agent alternates between blue and green containers, points the edge proxy at the newly ready slot, and keeps the previous slot alive for a short drain window. traffic_mode controls how the proxy treats clients during that window.

active_slot

Stored on app state so the agent knows which slot is currently live.

traffic_mode=edge

All requests move to the new active slot as soon as the proxy is reloaded.

traffic_mode=session

The edge proxy sets a relay_slot cookie and can keep a browser pinned to a specific slot for the duration of the standby window.

Drain behavior

The old slot is removed only after RELAY_ROLLOUT_DRAIN_SECONDS elapses.

App config for slot-aware routing
{
  "app": "demo",
  "env": "preview",
  "branch": "main",
  "mode": "traefik",
  "traffic_mode": "session",
  "public_host": "demo-main.preview.example.com",
  "service_port": 3000
}
Host ownership

Keep the dashboard hostname separate from app hostnames.

Relay itself serves the dashboard root on its own host. If you point an app at the same hostname, requests can resolve to the dashboard instead of the app. Give the dashboard and each app separate hosts.

Dashboard host

Use a dedicated admin host such as `admin.f4ust.com`.

App host

Use a different host such as `relay.f4ust.com` or let Relay derive `<app>-<branch>.<base-domain>`.

Old nginx front proxy

If nginx is still bound to :80/:443, it will intercept requests before Relay's Caddy proxy can route them.

Saved guard

The admin rejects saving a public_host that matches the configured dashboard host.

Recommended split
Dashboard:  https://admin.f4ust.com
App:        https://relay.f4ust.com
Derived:    https://site-main.f4ust.com
Verification

Verify DNS and host routing with curl before opening a browser.

The quickest way to separate DNS problems from proxy problems is to resolve the host manually and inspect the response headers. Test the dashboard host and the app host independently.

Step 1

Confirm both names resolve to the server IP with nslookup or dig.

Step 2

Use curl --resolve against admin.f4ust.com and the app host before relying on browser cache or DNS propagation.

Step 3

If the response still says `Server: nginx`, your old front proxy is still in the path.

Step 4

If the app host returns `Location: /dashboard/`, the app host still collides with the dashboard host or an old proxy rule.

Curl checks
curl -I --resolve admin.f4ust.com:443:185.27.135.235 https://admin.f4ust.com
curl -I --resolve relay.f4ust.com:443:185.27.135.235 https://relay.f4ust.com
What gets recorded

Preview URLs are part of the deploy history, not a front-end guess.

The dashboard shows a Visit link because the server stores a preview URL on each deploy once rollout completes. Deploy history also carries the routing shape that was live at the time through app state fields like mode, public_host, host_port, active_slot, and traffic_mode.

Deploy record

Stores the preview URL for the specific deployment.

App state

Stores host mode, host port, service port, public host, active slot, and traffic mode details.

CLI output

Prints the preview URL when the deploy reaches ready state.

Dashboard cards

Render the preview as a clickable link when present.

Ready output
preview URL: http://127.0.0.1:3005
deploy success. image=relay/site-demo:preview-main-...