Platform features

Deploy production, staging, dev, and preview lanes without giving up host control.

Relay keeps the path from local repo to running container short and inspectable: lane-aware routing, protected edge access, signed sharing, expiring temporary lanes, staged promotion, streamed logs, rollback-ready images, build tracking, user accounts, and secrets encryption.

Built for

Protected dev and staging environments.

Self-hosted product teams.

Operators who care about where the container actually lives.

Core set

Speed, visibility, policy, and operational control.

First-class lanes

Relay ships with production, staging, dev, and preview lanes. Each lane carries defaults for routing, retention, promotion, and browser access instead of relying on scattered env checks.

Edge access policies

Choose public, relay-login, signed-link, or ip-allowlist per lane. dev and staging default to Relay-auth gated access so internal environments stay internal.

Differential sync

Upload only changed files using workspace manifests instead of re-sending entire projects on every deploy.

Container rollouts

Build an image, start the next blue or green slot, switch traffic only after readiness passes, then drain the previous slot before cleanup.

Build numbers and deploy tracking

Every deploy gets a sequential build number per app. The dashboard shows who triggered each deploy, the commit message for webhook-driven builds, and full duration history.

User accounts and roles

Create owner, deployer, and viewer accounts with username/password auth. The first boot prompts for an owner account. CLI login uses a browser exchange flow to issue a bearer token.

Secrets encryption at rest

Set RELAY_SECRET_KEY and secrets in relay.db are encrypted with AES-256-GCM. The deploy path decrypts transparently. Existing plain-text secrets continue to work during migration.

Audit log

Deploy triggers, secret writes, user creation, and role changes are all recorded with actor, target, and timestamp. The Server tab surfaces the recent activity trail.

Project services

Spin up companion Postgres, Redis, MySQL, or Mongo services from relay.json. On Docker lanes they share a Docker network. On Station lanes, Relay injects host aliases so the app resolves service names through /etc/hosts.

Framework detection

Built-in buildpacks cover mainstream app types including Sprint UI. Server-installed plugins still handle extra framework shapes when needed.

Managed lane routing

Run in direct port mode or through Relay's built-in edge plus Caddy proxy stack. staging gets a stable host, while dev and preview can generate random managed aliases automatically.

Signed-link sharing

signed-link lanes can now mint a temporary share URL from the dashboard. Relay signs relay_exp and relay_sig centrally and the edge verifies them before the app responds.

Lane retention cleanup

dev and preview lanes can expire automatically. Relay refreshes their retention window on deploy or restart, then stops stale lanes in the background so temporary environments do not linger forever.

Promotion flow

staging can promote the already-validated image into production, pause for owner approval when needed, then watch health and queue rollback automatically if the target lane fails after handoff.

Docker default, Station optional

Container build, run, stop, network, volume, and log operations all route through a ContainerRuntime interface. Docker is the default backend. Station stays available per-app as an experimental runtime.

Operational controls

Restart, stop, stream logs, inspect deploy history, manage app config, and view the activity log from the same control surface.

Security model

User accounts, protected lanes, encrypted secrets, and a full activity trail.

Relay supports both a user-account model with roles and a legacy single-token mode for existing deployments. App traffic can also be gated with lane-level edge access policies, while secrets remain encrypted at rest and every significant action lands in the audit log.

Owner role

Full access: deploy, manage secrets, create and remove users, change roles.

Deployer role

Can trigger deploys and manage secrets. Cannot manage user accounts.

Viewer role

Read-only dashboard access. Cannot trigger deploys or edit secrets.

Lane access policies

Set each lane to public, relay-login, signed-link, or ip-allowlist. dev and staging default to relay-login so browser access stays scoped to Relay users.

Signed-link generator

signed-link lanes can mint temporary share URLs directly from the dashboard instead of relying on operators to hand-build tokens.

Secrets encryption

Set RELAY_SECRET_KEY to store secrets as AES-256-GCM ciphertext. Key is derived via SHA-256 so any string length works. Unencrypted values are still read during the transition.

Audit log

Every deploy, promotion request, secret write, user create, delete, and role change is appended with actor plus timestamp. Exposed at GET /api/audit and visible in the Server tab.

Auth setup
# User accounts (recommended)
# First boot -> dashboard setup wizard
# Add users from Server -> User Management

# CLI browser login
relay login

# Legacy single-token (still supported)
RELAY_TOKEN=your-token relayd

# Secrets encryption
RELAY_SECRET_KEY="strong-passphrase" relayd
Build tracking

Sequential build numbers, deployer names, and commit messages.

Each deploy is assigned the next sequential build number for that app. The dashboard surfaces who triggered each deploy and the commit message for git-push builds, making it easy to trace any running container back to a change.

Build number

Auto-incremented per app and shown as #42 in the dashboard instead of a UUID fragment.

Deployed by

The authenticated username is stored with every CLI-triggered deploy and shown alongside the build number.

Commit message

For GitHub webhook deploys, the first line of head_commit.message is stored and shown in the deployments list.

Duration history

started_at and ended_at are tracked per deploy so average build time is computable across any filter set.

Source label

Each deploy records whether it came from sync or git, surfaced as a badge in the dashboard.

Searchable

The deployment search includes commit message and deployer name alongside branch, commit SHA, and image tag.

Deploy record
{
  "id": "f3a2...",
  "build_number": 42,
  "app": "my-app",
  "env": "staging",
  "branch": "main",
  "status": "success",
  "deployed_by": "alice",
  "commit_message": "fix: auth middleware",
  "commit_sha": "a1b2c3d",
  "source": "sync",
  "created_at": "...",
  "started_at": "...",
  "ended_at": "..."
}
Traffic shape

Relay ships blue-green slot swaps. It does not ship weighted canary routing.

The rollout path in relayd starts the next slot, waits for readiness, flips traffic to that slot, and drains the previous slot for a configurable window. In edge proxy mode, traffic can run as edge or session, and access policy is enforced before the app responds.

Blue-green slots

App containers are named per slot and alternate between blue and green on each successful rollout.

Readiness gate

Traffic only moves after the candidate slot is reachable on its service port.

Drain window

The previous slot is kept alive for RELAY_ROLLOUT_DRAIN_SECONDS before cleanup.

Edge traffic mode

traffic_mode=edge sends everyone to the active slot immediately after the switch.

Session traffic mode

traffic_mode=session sets a cookie and can keep a client pinned to either the active or standby slot during the drain window.

Edge access gate

access_policy is evaluated before the request reaches the active slot, so Relay Login, signed links, and allowlists protect the lane at the proxy boundary.

Promotion handoff

Relay can now request or approve staging-to-prod promotion, reuse the staged image, and queue rollback when the target lane fails health after the handoff.

Not weighted canary

There is still no percentage-based split or weighted routing controller in the current implementation.

Operator framing

Use blue-green wording for the current Relay rollout system.

Use session-pinned standby checks when you need to verify the new slot before the old one drains away.

Do not call it canary unless you also explain that there is no weighted traffic split today.

Runtime support is broader, but the default is explicit.

Next.js
Vite
Expo web
Sprint UI
Node
Go
.NET
Flask
FastAPI
Java
Rust
C / C++
WASM static

Delivery posture matters more than feature count.

User accounts with RBAC mean deploy access can be scoped to specific people, not shared tokens.

Lane access policies mean dev and staging can require a Relay session before the app is ever served.

Signed-link lanes let teams share temporary access without opening the whole lane publicly.

AES-256-GCM encryption at rest means a leaked database file does not expose secrets.

The audit log means you can answer "who deployed this?", "who requested promotion?", and "who changed that secret?" without digging through logs.

Docker is the default runtime again. Plugin install and remove are disabled by default, and Station should be treated as an intentional exception.