Goal: one‑command in‑cluster deploy, idempotent, no code↔live drift. The repo brings the desired state; this runbook covers standing up a fresh AWS account end‑to‑end. Nothing secret is committed (D5).
- AWS quotas — request G/VT instance vCPU quota (for
g5.2xlargeA10G; 0 by default) plus standard vCPU for the OCP control/worker nodes; check EIP/VPC/NAT quotas for an IPI install. - DNS — create + delegate the Route53 public zone for
base_domain(cd terraform && terraform apply -target=aws_route53_zone.base, then add the output NS records to the parentcoderdemo.iozone). - Red Hat pull secret — from console.redhat.com; used as the cluster global
pull secret at install (for
registry.redhat.io: RHOAI, RHBK, ose‑cli, UBI). - GHCR images — the
build-imagesworkflow pushes the workspace images; make the GHCR packages public or give the cluster a GHCR pull secret (connected mode). Air‑gap usestask mirrorinstead. - Coder license — applied post‑deploy (
coder licenses add); needed for the Premium features this demo uses (OIDC group→role sync, AI Gateway).
See install/. Summary:
cp install/install-config.yaml.example install-config.yaml # fill pull secret + sshKey (NOT committed)
openshift-install create manifests --dir .
ccoctl aws create-all --name <cluster> --region us-east-1 \
--credentials-requests-dir <crs> --output-dir . # creates the IAM OIDC provider
openshift-install create cluster --dir .oc get authentication cluster -o jsonpath='{.spec.serviceAccountIssuer}' # -> oidc_* in terraform.tfvars
cd terraform && terraform apply # creates cert-manager (+ optional Bedrock) roles
export CERT_MANAGER_ROLE_ARN=$(terraform output -raw cert_manager_role_arn)task gpu-node # derives a g5.2xlarge GPU MachineSet from a worker MachineSetWait for the node to join and the NVIDIA GPU operator to label it
nvidia.com/gpu.present=true.
task preflight # tooling + cluster login + warns on missing IRSA/pull-secret
task deploy # connected (default)
# or, air-gap:
task mirror # images + OCI model + oc-mirror into the internal/mirror registry
task deploy MODE=airgap
task status # Argo apps + InferenceService + routes + GPU nodetask deploy runs: bootstrap (operators → Argo root app‑of‑apps) →
irsa (annotate cert‑manager SA from CERT_MANAGER_ROLE_ARN) → gpu-node →
wait-apps (Argo Healthy+Synced) → push-templates (needs coder login) →
air‑gap overlay toggle (MODE).
Password auth is disabled, so the first user must come from Keycloak: the first OIDC sign‑in on an empty deployment becomes the Coder owner.
task creds, then in a browser openhttps://coder.apps.cluster.<domain>/api/v2/users/oidc/callback(starts the Keycloak flow directly — an empty deployment redirects/loginto/setup, which only offers password/GitHub) and sign in asdemoadm(theadminsgroup → owner once the license enables role sync; signing in first as alice/bob would make a non‑admin the owner).- Only then
coder login https://coder.apps.cluster.<domain>(browser token flow),coder licenses add -f <license.jwt>, andtask push-templates.
If coder login asks "Would you like to create the first user?", answer
no — it creates a password owner that can never sign in (password auth is
off) and stops the first OIDC user from becoming owner.
No secret is committed. Persona passwords are generated in‑cluster (ESO) and live
only in Secret/keycloak-realm-secrets:
task creds # personas (alice/bob/demoadm) + Keycloak admin console, read liveRequires cluster‑admin (kube:admin at install; demoadm once the realm is up).
Machine client secrets are wired automatically and intentionally not printed.
Override the namespace with task creds KEYCLOAK_NS=<ns>.
task reset # re-seed the demo realm; drop demo workspaces via Coder UI/CLI; infra untouchedDESTROY_CONFIRM=yes INSTALL_DIR=<dir> task destroy # openshift-install destroy
cd terraform && terraform destroy # Route53 zone + IRSA rolesFresh account → steps 0–4 → SSO‑gated Coder, a workspace-basic from the
internal‑registry image, a workspace-agent whose AI CLI answers from the
in‑cluster RHOAI model; task deploy MODE=airgap denies workspace egress yet the
agent still answers in‑cluster; task reset returns to clean. No hand‑run
scripts; no code↔live drift.