4. Ingress, TLS & auth
Step 4 of the deployment sequence. With Orchestra installed, this page makes it reachable and authenticated over HTTPS. It installs the two external dependencies the chart assumes — Traefik and cert-manager — and configures the bundled oauth2-proxy.
For controller internals (the Traefik middlewares the chart creates, the auth flow, nginx-ingress) see the Ingress Controller guide and the oauth2-proxy setup. This page is the end-to-end procedure that actually works on GKE Standard.
The three host types (recap)
Section titled “The three host types (recap)”All resolve to one static IP in front of Traefik:
app.<domain>— dashboard (frontend), behind oauth2-proxy full-proxy modeapi.<domain>— API, behind Traefik ForwardAuth (identity header injection)*.<domain>— per-session workshop containers, one subdomain each
The wildcard is why we need DNS-01 (HTTP-01 cannot validate *.<domain>) and
a Traefik default TLSStore (per-session IngressRoutes carry no explicit
TLS secret).
1. Reserve a static regional IP
Section titled “1. Reserve a static regional IP”Reserve a regional external IP so the LoadBalancer keeps a stable address across reinstalls (and so DNS can be set up in parallel before cutover):
REGION=us-central1gcloud compute addresses create orchestra-ingress \ --region "$REGION" --project <project>
gcloud compute addresses describe orchestra-ingress \ --region "$REGION" --format='value(address)'# → note this IP; it goes in the Traefik values and every DNS record2. Install Traefik (pinned to the static IP, on the system pool)
Section titled “2. Install Traefik (pinned to the static IP, on the system pool)”Install the Traefik v3 chart, pin the service to the static IP, and place it on the system pool so it doesn’t ride a scale-to-zero NAP node:
helm repo add traefik https://helm.traefik.io/traefik && helm repo update
helm install traefik traefik/traefik \ --namespace traefik --create-namespace \ --set service.type=LoadBalancer \ --set service.spec.loadBalancerIP=<STATIC_IP> \ --set 'nodeSelector.pool=system' \ --set 'tolerations[0].key=dedicated' \ --set 'tolerations[0].value=system' \ --set 'tolerations[0].effect=NoSchedule' \ --set 'tolerations[0].operator=Equal'The Traefik v3 chart’s default entrypoints are web (:80) and websecure
(:443) — the chart’s Ingress objects target these by default, so no extra
entrypoint config is needed. Confirm the service picked up the reserved IP:
kubectl get svc -n traefik traefik -w # EXTERNAL-IP should equal <STATIC_IP>3. Install cert-manager + a DNS-01 wildcard cert
Section titled “3. Install cert-manager + a DNS-01 wildcard cert”helm repo add jetstack https://charts.jetstack.io && helm repo update
helm install cert-manager jetstack/cert-manager \ --namespace cert-manager --create-namespace \ --set crds.enabled=true-
Store the Cloudflare API token (scope
Zone → DNS → Editfor the zone) as a Secret:Terminal window kubectl create secret generic cloudflare-api-token \--namespace cert-manager \--from-literal=api-token=<CLOUDFLARE_API_TOKEN> -
Create the Let’s Encrypt ClusterIssuer with a Cloudflare DNS-01 solver. DNS-01 is required to issue the wildcard (per-session subdomains); HTTP-01 can’t do
*.<domain>.cluster-issuer.yaml apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:name: letsencrypt-prodspec:acme:server: https://acme-v02.api.letsencrypt.org/directoryemail: admin@example.eduprivateKeySecretRef:name: letsencrypt-prod-keysolvers:- dns01:cloudflare:apiTokenSecretRef:name: cloudflare-api-tokenkey: api-tokenTerminal window kubectl apply -f cluster-issuer.yaml -
Issue the wildcard Certificate for
*.<domain>+ apex into the Orchestra namespace, secretorchestra-wildcard-tls(the namegcp-values.yaml’singress.tls.existingSecretpoints at):wildcard-cert.yaml apiVersion: cert-manager.io/v1kind: Certificatemetadata:name: orchestra-wildcardnamespace: orchestra-systemspec:secretName: orchestra-wildcard-tlsdnsNames:- "*.orchestraplatform.org"- "orchestraplatform.org"issuerRef:name: letsencrypt-prodkind: ClusterIssuerTerminal window kubectl apply -f wildcard-cert.yamlkubectl get certificate -n orchestra-system orchestra-wildcard -w # Ready=True
4. Wire Traefik’s default TLSStore for per-session routes
Section titled “4. Wire Traefik’s default TLSStore for per-session routes”Per-session workshop IngressRoutes are created by the operator and carry no
explicit TLS secret — they rely on Traefik’s default TLSStore. Traefik can
only serve a certificate from a secret in its own namespace, so issue a
copy of the wildcard into traefik and point the default store at it.
Issue a second Certificate into the traefik namespace:
apiVersion: cert-manager.io/v1kind: Certificatemetadata: name: orchestra-wildcard namespace: traefikspec: secretName: orchestra-wildcard-tls dnsNames: - "*.orchestraplatform.org" - "orchestraplatform.org" issuerRef: name: letsencrypt-prod kind: ClusterIssuerThen set Traefik’s default TLS store to that secret:
apiVersion: traefik.io/v1alpha1kind: TLSStoremetadata: name: default namespace: traefikspec: defaultCertificate: secretName: orchestra-wildcard-tlskubectl apply -f wildcard-cert-traefik.yaml -f traefik-default-tls.yamlNow every *.<domain> session route serves the wildcard automatically, while the
app. and api. ingresses use the copy in orchestra-system via
ingress.tls.existingSecret.
5. oauth2-proxy (bundled subchart)
Section titled “5. oauth2-proxy (bundled subchart)”The chart bundles oauth2-proxy and runs it in full-proxy mode in front of the
frontend (recommended for Traefik — the login redirect is seamless). Credentials
and domain rules are configured under the root-level "oauth2-proxy" subchart
key; see oauth2-proxy setup and the reference
deploy/gcp-values.yaml. The three host types are auth-wired as in the
recap.
Verify
Section titled “Verify”kubectl get svc -n traefik traefik # EXTERNAL-IP = <STATIC_IP>kubectl get certificate -A # both orchestra-wildcard certs Readykubectl get tlsstore -n traefik defaultNext: DNS cutover — point app, api, and the
* wildcard at the static IP.