Gateway TLS
Put the gateway behind TLS; plaintext http:// breaks long streams.
The gateway never terminates TLS itself: it speaks plain HTTP on :8787 and sits behind a TLS
edge (a reverse proxy, an Ingress, a load balancer, or your platform's router). The rule is the
same everywhere:
Set ANYRAY_GATEWAY_PUBLIC_URL to the https:// URL your users reach the gateway at. The
gateway reports it to your console, so enrollment links resolve to the secure URL automatically.
An http:// value (to anything but a loopback or .local host) is flagged as insecure on the
developer enrollment page at app.anyray.ai.
Pick the recipe for where you run it: Docker Compose below, Kubernetes, a managed platform, or a cloud load balancer. Whichever it is, finish by re-pointing users.
Docker Compose
The stack ships a Caddy TLS edge behind the public profile; it provisions and renews a
Let's Encrypt certificate automatically. You need a domain with a DNS A record pointing at the
host, and ports 80/443 open.
Create a DNS A record, e.g. gateway.example.com → your host's public IP.
In .env:
ANYRAY_PUBLIC_DOMAIN=gateway.example.com # Caddy provisions a cert for this
ANYRAY_GATEWAY_PUBLIC_URL=https://gateway.example.com
ANYRAY_GATEWAY_BIND=127.0.0.1 # so :8787 isn't reachable, bypassing TLS
ANYRAY_TRUST_PROXY=true # trust X-Forwarded-* from Caddy
ANYRAY_HSTS=true # emit Strict-Transport-Security, safe once TLS fronts it
docker compose --profile public up -d
Caddy comes up on :80/:443, gets the certificate, and proxies to the gateway. The console
and /admin stay in-network only.
Exposing the console over HTTPS (optional)
By default the console (compose port 3000) speaks plain HTTP and stays in-network; reach it over
an SSH tunnel. To let the app.anyray.ai Billing app link your admins
straight to it, give the console its own public hostname so the same Caddy edge terminates TLS
for it too: create another DNS A record (e.g. console.example.com → the same host IP), then
ANYRAY_CONSOLE_DOMAIN=console.example.com # Caddy provisions a cert for this
ANYRAY_CONSOLE_PUBLIC_URL=https://console.example.com # reported home, so the Billing app links here
Re-run docker compose --profile public up -d and restart the gateway so it re-reports the URL.
Leave both unset to keep the console in-network only.
The console hostname serves the admin console and the /admin, /public, and /log
endpoints, gated by admin auth (ANYRAY_ADMIN_TOKEN, or console SSO if enabled; the gateway
hostname keeps 403-ing them). Use a strong admin token, and prefer an SSH tunnel if you don't need
the Billing app hand-off.
Kubernetes
Terminate TLS at an Ingress with cert-manager (or your cluster's managed certificate). The
gateway runs as a normal Service on :8787; the Ingress is the only thing exposed.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: anyray-gateway
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts: [gateway.example.com]
secretName: anyray-gateway-tls
rules:
- host: gateway.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: anyray-gateway
port: { number: 8787 }
Then set on the gateway Deployment:
ANYRAY_GATEWAY_PUBLIC_URL=https://gateway.example.com
ANYRAY_TRUST_PROXY=true
/admin privateDon't expose /admin/*, /public/*, or /log/* through the public Ingress; keep the console and
admin API in-network (a separate internal Ingress or kubectl port-forward). The bundled Caddy
edge blocks them by default; on an Ingress you enforce it with path rules.
Managed platforms
Railway, Render, and Fly terminate TLS for you and give the service a public https://
hostname. There's nothing to provision; just don't expose :8787 directly, and set:
ANYRAY_GATEWAY_PUBLIC_URL=https://your-app.up.railway.app
ANYRAY_TRUST_PROXY=true
Cloud load balancers
Terminate TLS at the load balancer with a managed certificate, targeting the gateway on :8787:
- AWS (ALB). An HTTPS:443 listener with an ACM certificate, forwarding to a target group
on the gateway's
:8787. Lock the gateway's security group so:8787only accepts traffic from the ALB. - Google Cloud (HTTPS LB). An external HTTPS load balancer with a Google-managed
certificate and a backend service pointing at the gateway. Restrict the gateway so only the
LB's ranges reach
:8787.
ANYRAY_GATEWAY_PUBLIC_URL=https://gateway.example.com
ANYRAY_TRUST_PROXY=true
Re-point users
Re-run anyray-connect --gateway https://gateway.example.com, or share fresh enrollment links.
Once the gateway reports its https ANYRAY_GATEWAY_PUBLIC_URL, new links resolve to the secure
URL automatically. Once every tool is on https, close off any direct plaintext :8787 exposure.