Relay docs

Deployment

Relay is three ASP.NET Core apps (gateway API, control-panel host, and this docs site) plus SQL Server, and optionally ClickHouse/ClickStack and Qdrant. The .NET Aspire AppHost is a local-development orchestrator only and is not deployed.

#Build

Build in Release with --no-restore (running instances can lock Debug DLLs, and the environment restore is restricted):

dotnet build Application.sln -c Release --no-restore

Publish each app you deploy:

dotnet publish Application.Api -c Release -o out/api
dotnet publish Application     -c Release -o out/panel
dotnet publish Application.Doc -c Release -o out/docs

The repo's GitHub Actions workflows (.github/workflows/deploy_api.yml, deploy_app.yml, deploy_docs.yml) do exactly this on a self-hosted runner and copy the output into IIS sites — a push to dev deploys the test environment, a push to main deploys prod, and each workflow triggers only when its projects change. The DACPAC publish is not part of CI.

#Database schema (DACPAC)

Schema is not applied by the apps at runtime — there are no EF migrations for the gateway schema. Publish the Application.Database DACPAC to the relay_gateway database (SqlPackage / Visual Studio) as part of your release, before the new build runs: the gateway selects recently added columns on every request. New tables/columns are authored as .sql there and mirrored in the DbContext model.

ClickHouse needs no schema step: relay_observation and relay_score are created, and new columns added, by the apps at startup.

#Configuration in production

Supply secrets via environment variables or Key Vault — never committed files. At minimum:

  • ConnectionStrings:GatewayDb on both apps; ConnectionStrings:UserManagementDb and the identity-app sign-in settings (Identity:BaseUrl, Identity:ClientId, Identity:ClientSecret) on the panel host, which refuses to start without the secret.
  • Encryption:MasterKey — the same value on the panel host and the gateway, or neither can read what the other encrypted and the Playground delegation fails.
  • Gateway:PublicBaseUrl (and Gateway:InternalBaseUrl when the panel reaches the gateway over a different address) so the panel's Playground, workflow approvals and resume links point at the right place; Gateway:PanelBaseUrl for links in approval notifications.
  • Provider keys are entered in the panel and stored encrypted; set a SecretRef config key only for providers you deliberately keep on the configuration fallback.
  • ClickHouse:ConnectionString on both apps if you want telemetry, dashboards and traces.
  • Qdrant:Url (+ key) if you use knowledge bases.
  • Connectors:RedirectUri only behind a reverse proxy that rewrites the host.

See the full Configuration reference.

#Telemetry and HyperDX

Relay always writes its own observability tables when ClickHouse is configured. For HyperDX dashboards and alerting on the same data, run ClickStack (the all-in-one image bundles ClickHouse + an OpenTelemetry collector + HyperDX), set Gateway:Otlp:Enabled=true, Gateway:Otlp:Endpoint and Gateway:Otlp:ApiKey (the HyperDX ingestion key), and optionally Telemetry:DashboardSource=otel to read the usage dashboard from the collector's otel_traces. Telemetry:Backend is obsolete and ignored. See Telemetry & dashboards and the repo's docs/clickstack.md.

#Networking notes

  • On Windows/dev, prefer 127.0.0.1 over localhost for containerised dependencies (IPv4 vs. IPv6).
  • Restrict the control-plane CORS origins with Cors:PanelOrigins.
  • Serve the gateway over HTTPS: a page served over HTTPS can only open wss:// realtime sockets to a remote host.
  • The gateway API and the panel can scale independently, but several gateway stores are per instance: the response cache and idempotency store, the per-key rate limiter, provider health, and realtime session tokens (mint and connect must reach the same process — use sticky sessions behind a load balancer).

#This docs site

Application.Doc is self-contained (no external packages, content copied to output). Publish and host it like any static-ish ASP.NET app; it serves the Markdown under Docs/ rendered on the fly.