blue.example.com and api.blue.example.com. The chart runs with its production checks on.
You need tofu, aws, kubectl, helm, jq, docker, and AWS credentials that can create VPC, EKS, RDS, ElastiCache, S3, IAM, KMS, ACM and Route 53 records. Run everything from the bundle’s infra/aws folder, in one terminal. The files this guide writes go in that folder. Everything here costs money every hour.
Nothing in Blue reads Redis. It is here for the LiteLLM gateway you may run later; drop include_redis to save the cost. To land in a cluster or VPC you already run, set eks_cluster_name and vpc_id; see the AWS module README.
Blue does not need Kubernetes. This is the maintained implementation of the Deployment contract; any platform that meets the contract works.
Before you start
1. Create the cluster, databases and certificate
terraform.tfvars, skip the three tofu output lines for the certificate and hostnames, and set them yourself:
2. Connect kubectl and prepare the cluster
3. Copy the secrets into the cluster
4. Add Blue’s config file
blue-blue-dashboard URLs are calls inside the cluster, so they stay plain HTTP. See Configure blue.yaml for every field.
5. Write the Helm settings
6. Install Blue
7. Point the names at the load balancer
tofu apply and create two CNAME records at your DNS provider, $BLUE_DASHBOARD_HOST and $BLUE_API_HOST, both pointing at $ALB.
8. Check it, use it, delete it
open is macOS; on Linux, paste the dashboard address into a browser. Session uploads go straight to S3, so no port-forward is needed. If tofu destroy fails on the VPC, the load balancer is still being removed. Wait and retry. If it fails on the buckets, they still have objects in them. Empty them and retry.
DNS not in Route 53? Run tofu destroy as above, then delete the two records and the certificate yourself.
Changing the config later
Edit$BLUE_CONFIG_FILE, then upload it and restart the API and worker. The server compares the new file’s content to the stored baseline and publishes a revision when they differ:
Hardening
- Set
deletion_protectionback totrue, so the database can’t be destroyed by accident and gets a final snapshot if it is. - Add
networkPolicy.externalHttpsCidrsto your values file with the S3 and STS ranges for your region fromhttps://ip-ranges.amazonaws.com/ip-ranges.json, plus any package hosts you allow. The generated settings leave HTTPS open. - Limit who can reach the cluster API with
cluster_endpoint_public_access_cidrs, and who can reach the load balancer withalb.ingress.kubernetes.io/inbound-cidrs. - Check the rendered install with
scripts/verify-deployment.shfrom the source repository.
Backups and upgrades
Back up PostgreSQL, the package bucket, and the session bucket separately; they have different retention and recovery needs. To upgrade, pin the new image digest in the values file and run the step 6helm upgrade again. The chart’s pre-upgrade Job runs the database migrations before the new pods start. See the migration policy.
Gateway mode: route agent inference through Blue
Continues from step 8 with the cluster still running. Adds Blue’s inference proxy athttps://iproxy.<zone>: agents send model calls there, the proxy checks a Blue-issued token, then forwards to your LiteLLM, which holds the provider keys. LiteLLM is already running somewhere you manage, and you have its URL and master key. It must serve a model named claude-opus-4-8, the name the governance policy in step 4 hands to agents. Installs cert-manager into the cluster for the internal certificates.
Read Bring your own gateway for how the routing and credentials work.
9. Point Blue at your LiteLLM
10. Add the gateway secrets
11. Install cert-manager
The proxy and the API talk over an encrypted internal link where each side shows a certificate. The chart declares those certificates; cert-manager makes and renews them, and Blue picks up new files without a restart.12. Add the gateway to Blue’s config
13. Turn the proxy on
inference_proxy_subdomain after the first apply, Tofu reissued the certificate: rerun step 2’s kubectl apply with the new BLUE_CERT_ARN.
LiteLLM not on HTTPS port 443? The generated settings let pods reach any address on 443 and nothing else. For another port, or a LiteLLM inside this cluster, add its address to the gateway values file:
