Skip to main content

Deploy on Google Cloud

One Cloud Shell script provisions a GKE Autopilot cluster and installs the whole stack.

The script installs the bundled Helm chart (gateway, optimizer, console, Postgres) and exposes the gateway API (:8787) and console (:3000) as load balancers scoped to the CIDR you choose. Already run your own cluster? Use Kubernetes (Helm) instead: GKE is an ordinary conformant cluster, and The two files you author install the same chart with nothing Google-specific in them. The only GKE-specific part:

Create the cluster, then install the chart yourself
gcloud container clusters create-auto anyray --region us-central1
gcloud container clusters get-credentials anyray --region us-central1

helm install anyray oci://public.ecr.aws/anyray/anyray \
-f my-values.yaml --namespace anyray --create-namespace

Autopilot's default standard-rwo StorageClass satisfies the chart's volumes, so there is nothing to pre-create.

Prerequisites

  • A Google Cloud project with billing enabled and permission to create GKE, Compute Engine, and load balancer resources. The script enables the Kubernetes Engine and Compute Engine APIs for you.
  • A narrow ALLOWED_CIDR: your office or VPN range. For a single workstation: curl -fsS https://api.ipify.org, then <that-ip>/32. The script rejects 0.0.0.0/0; the console and gateway carry your org's spend data and admin access.
  • An Anyray deployment token (adt_…) from app.anyray.ai (setup wizard, or Settings → Deployments → New deployment).

Cloud Shell already has gcloud, kubectl, and helm; nothing to install locally.

Install

1
Open in Cloud Shell

Clones the install repo into Cloud Shell and opens the guided walkthrough.

Open in Cloud Shell

Any machine with the gcloud SDK, kubectl, and helm works too; see Install from your own terminal below.

2
Set your inputs and run the script
Cloud Shell
export ALLOWED_CIDR="203.0.113.0/24" # your office / VPN range
export DEPLOYMENT_TOKEN="adt_..." # from app.anyray.ai
# Optional overrides:
# export REGION="us-central1"
# export CLUSTER="anyray"
# export NAMESPACE="anyray"
# export IMAGE_TAG="latest" # or pin vX.Y.Z
./gcp/deploy.sh

The script enables the APIs, creates the Autopilot cluster, generates the secrets (ANYRAY_ADMIN_TOKEN, ANYRAY_CONTENT_KEY, the pseudonym salt, stored as the anyray-secrets Kubernetes Secret, never printed), installs the chart, waits for the load balancer IPs, and prints your URLs and admin key.

3
Wait for first boot

The Autopilot cluster is the long pole (~5–8 min), then the load balancers take ~1–3 min to get external IPs. The gateway restarts until Postgres is reachable, then goes healthy.

4
Open the console

Open the printed Console URL and sign in with the printed admin key. Read the key again any time:

kubectl get secret anyray-secrets -n anyray \
-o jsonpath='{.data.ANYRAY_ADMIN_TOKEN}' | base64 --decode; echo
5
Verify the deployment
export GATEWAY_URL="http://your-gateway-lb-ip:8787"
export ADMIN_TOKEN="..." # from the deploy output

curl -fsS "$GATEWAY_URL/" && echo "gateway ok"
# Deployment health: gateway / observability / spend / optimizer / portal:
curl -fsS "$GATEWAY_URL/admin/health" -H "Authorization: Bearer ${ADMIN_TOKEN}"

/admin/health returns 503 and names the failing leg if any required service is down; a healthy stack returns "ok": true with every leg green.

Everything above runs in your Google Cloud project. Point your local coding tools at the gateway with npx anyray-connect@latest --gateway <GatewayURL> (developer FAQ).

Install from your own terminal

From any machine with the gcloud SDK, kubectl, and helm authenticated to your project:

git clone https://github.com/anyrayHQ/install anyray && cd anyray

export PROJECT_ID="my-gcp-project"
export ALLOWED_CIDR="203.0.113.0/24" # your office / VPN range
export DEPLOYMENT_TOKEN="adt_..." # from app.anyray.ai

./gcp/deploy.sh

The script is idempotent: re-running it reuses an existing cluster and keeps the existing anyray-secrets rather than rotating the content key. The inputs:

VariableRequiredDefaultWhat it is
PROJECT_IDyesgcloud's active projectGCP project to deploy into.
ALLOWED_CIDRyesn/aCIDR allowed to reach the console/gateway LBs; 0.0.0.0/0 is rejected.
DEPLOYMENT_TOKENyesn/aAnyray Billing app deployment token (adt_…).
REGIONnous-central1Autopilot region.
CLUSTERnoanyrayCluster name (reused if present).
NAMESPACEnoanyrayKubernetes namespace.
IMAGE_TAGnolatestAnyray image tag; pin vX.Y.Z for a reproducible deploy.
DEFAULT_MODELnoanthropic/claude-sonnet-4-5Target for the anyray-default model alias.

Configuration

Gateway hardening and optimizer tuning are ordinary Helm values; set them in my-values.yaml or pass --set on a helm upgrade and the gateway rolls with the new value. The values and their defaults: gateway hardening. To re-scope the load balancers to a different CIDR later, see Troubleshoot below.

Troubleshoot

A LoadBalancer Service has no external IP

GKE provisions the external IP in ~1–3 min:

kubectl get svc gateway anyray-proxy -n anyray

If EXTERNAL-IP stays <pending> for several minutes, confirm the Compute Engine API is enabled and the project has quota for external IP addresses.

The console or gateway is unreachable from your network

The load balancers only admit traffic from ALLOWED_CIDR. Confirm your current public IP is inside that range (curl -fsS https://api.ipify.org), and re-scope if needed:

helm upgrade anyray ./helm -f my-values.yaml --namespace anyray --reuse-values \
--set gateway.service.loadBalancerSourceRanges[0]=<your-cidr> \
--set proxy.service.loadBalancerSourceRanges[0]=<your-cidr>
A pod is stuck Pending or CrashLooping
kubectl get pods -n anyray
kubectl describe pod -n anyray <pod>
kubectl logs -n anyray deployment/anyray-gateway

A Pending Postgres or *-data PVC usually means no default StorageClass. Autopilot ships standard-rwo; confirm with kubectl get storageclass. A gateway that keeps restarting is most often still waiting on Postgres.

Upgrade

IMAGE_TAG=latest follows the moving release channel. Re-run ./gcp/deploy.sh to converge, or pin a version and roll the chart directly; a pinned :vX.Y.Z keeps rollbacks reproducible and auditable:

helm upgrade anyray ./helm -f my-values.yaml \
--namespace anyray --reuse-values --set image.tag=vX.Y.Z