Skip to content

Deployment

Relayna Gateway ships as one binary and one Docker image. The image serves both the core proxy and the admin portal because the admin UI is embedded in the gateway-api binary.

Docker Image

Build the image:

docker build -t relayna-gateway:0.0.10 .

Run it with required dependencies:

docker run --rm \
  -p 8080:8080 \
  -p 8081:8081 \
  -e DATABASE_URL="postgres://user:password@host.docker.internal:5432/relayna_gateway" \
  -e REDIS_URL="redis://host.docker.internal:6379" \
  -e LITELLM_BASE_URL="http://host.docker.internal:4000" \
  -e LITELLM_SERVICE_KEY="sk-litellm-service-key" \
  -e RELAYNA_STUDIO_BASE_URL="http://host.docker.internal:8000" \
  -e GATEWAY_BIND_ADDR="0.0.0.0:8080" \
  -e GATEWAY_CONTROL_BIND_ADDR="0.0.0.0:8081" \
  -e LOG_LEVEL="gateway_api=info,gateway_proxy=info" \
  relayna-gateway:0.0.10

The proxy listens on port 8080. The control API, admin portal, readiness, and metrics listen on port 8081.

PostgreSQL Container

For local container testing:

docker run --rm --name relayna-postgres \
  -p 5432:5432 \
  -e POSTGRES_USER=relayna_gateway \
  -e POSTGRES_PASSWORD=relayna_gateway \
  -e POSTGRES_DB=relayna_gateway \
  postgres:16

Use:

postgres://relayna_gateway:relayna_gateway@host.docker.internal:5432/relayna_gateway

Redis Container

docker run --rm --name relayna-redis -p 6379:6379 redis:7

Use:

redis://host.docker.internal:6379

Kubernetes

The repository includes a baseline manifest at deploy/kubernetes/relayna-gateway.yaml.

  1. Use the image published by the tag-based release workflow:
ghcr.io/sarattha/relayna-gateway:0.0.10

To build and publish manually to another registry:

export RELAYNA_GATEWAY_IMAGE="<your-registry>/<your-org>/relayna-gateway:0.0.10"
docker build -t "$RELAYNA_GATEWAY_IMAGE" .
docker push "$RELAYNA_GATEWAY_IMAGE"
  1. Update the Deployment image when you use a different registry or tag:
image: <your-registry>/<your-org>/relayna-gateway:0.0.10
  1. Store secrets through your cluster secret manager:
kubectl create secret generic relayna-gateway-secrets \
  --from-literal=DATABASE_URL='postgres://user:password@postgres:5432/relayna_gateway' \
  --from-literal=REDIS_URL='redis://redis:6379' \
  --from-literal=LITELLM_BASE_URL='http://litellm:4000' \
  --from-literal=LITELLM_SERVICE_KEY='sk-litellm-service-key' \
  --from-literal=RELAYNA_STUDIO_BASE_URL='http://relayna-studio-backend:8000' \
  --from-literal=RELAYNA_STUDIO_TOKEN='studio-gateway-token'
  1. Apply the manifest:
kubectl apply -f deploy/kubernetes/relayna-gateway.yaml
  1. Verify readiness:
kubectl rollout status deployment/relayna-gateway
kubectl port-forward svc/relayna-gateway 8081:8081
curl http://127.0.0.1:8081/readyz

Network Exposure

Expose the proxy port to clients that need LLM traffic. Keep the control port private or protected by internal ingress, VPN, identity-aware proxy, or strict network policy.

Guardrail Configuration

Database migrations create the guardrail catalog, key policy, execution event, and per-key override tables/columns on startup. The built-in pii-redact catalog entry is enabled but not default-on, so existing keys keep unguarded behavior until an operator selects guardrails for the key.

Use Admin portal Guardrails to manage global catalog defaults:

  • runtime_config is the actual default config used when a guardrail runs.
  • config_schema documents the shape operators should use for runtime config.
  • HTTP guardrail endpoint URL, timeout, and bearer token are separate catalog fields. Bearer tokens are write-only and are never returned by the API.

Use Admin portal Keys to manage each key:

  • mandatory_guardrails always run for that key.
  • optional_guardrails may run when the client requests them.
  • forbidden_guardrails are hidden from discovery and rejected if requested.
  • guardrail_config_overrides tunes selected guardrails per key.

Per-key overrides are shallow-merged over the catalog runtime config. They must be JSON objects, and they only take effect when the guardrail is applied by mandatory, optional, default-on, or client-requested policy. For example, one key can restore pii-redact placeholders in responses while another leaves redacted placeholders in the final output:

{
  "guardrail_policy": {
    "mandatory_guardrails": ["pii-redact"],
    "optional_guardrails": [],
    "forbidden_guardrails": [],
    "guardrail_config_overrides": {
      "pii-redact": {
        "restore_output": false
      }
    }
  }
}

When guarded traffic may stream, ensure every selected response guardrail supports during_call; otherwise Gateway fails closed with guardrail_unavailable instead of buffering an unsupported stream.

Studio Import Connectivity

Gateway imports Studio services by calling the Studio backend endpoint GET /studio/gateway/services. The configured Studio base URL should therefore be the backend base URL. RELAYNA_STUDIO_BASE_URL and RELAYNA_STUDIO_TOKEN remain startup fallbacks; operators can override them in Admin portal Settings without restarting Gateway. Clearing the persisted base URL returns Gateway to the environment fallback.

Deployment shape Example value
Gateway and Studio on the same host http://127.0.0.1:8000
Gateway in Docker, Studio on host http://host.docker.internal:8000
Gateway and Studio in Kubernetes http://relayna-studio-backend:8000
Gateway to protected Studio over TLS https://studio.internal.example.com

Test Studio directly:

curl -sS "$RELAYNA_STUDIO_BASE_URL/studio/gateway/services"

Test through Gateway after startup:

curl -sS \
  -H "Authorization: Bearer $GATEWAY_OPERATOR_TOKEN" \
  -X POST \
  http://127.0.0.1:8081/admin/studio/connection/test

curl -sS \
  -H "Authorization: Bearer $GATEWAY_OPERATOR_TOKEN" \
  http://127.0.0.1:8081/admin/studio/services

If Gateway returns studio_unavailable, check that the backend URL is reachable from the Gateway process, that the path /studio/gateway/services exists, that the effective token matches Studio's expected token when authentication is enabled, and that Studio returns valid service names and route patterns.