Skip to main content

Adding an Installation

An installation is one namespace on one cluster, with its own hostnames, branding and identity provider. Adding one is a file, a GitHub Environment and an approval — not a bespoke deployment.

1. Describe it

Two files under environments/<name>/ in the deployment repository. They are split by who reads them: env.yaml configures the deploy and Helm never sees it; values.yaml configures the chart and the workflow never interprets it.

env.yaml is deploy metadata only:

apiVersion: eduide.dev/v1
kind: Environment
metadata:
name: bonn
displayName: EduIDE Bonn
tier: production # test | staging | production
spec:
cluster: eduide # must match a file in clusters/
namespace: eduide-bonn # every namespace carries the eduide- prefix
platform:
chartVersion: 2.0.0
channel: release # release | main

values.yaml is a plain Helm values file: hosts, Gateway parentRefs, Keycloak and branding. Nothing else — image tags, app definitions, the preload list and the storage class are all derived or come from the cluster.

2. Create the GitHub Environment

Named exactly as the directory, holding:

SecretWhat
KUBECONFIGthe cluster's kubeconfig
THEIA_KEYCLOAK_COOKIE_SECRETdd if=/dev/urandom bs=32 count=1 | base64 | tr -d -- '\n' | tr -- '+/' '-_'

The admin API token is a repository secret and is inherited.

Add required reviewers for anything tier: production or staging. Do not add them to an environment that deploys automatically — the approval gate blocks the automation outright and the run waits forever.

3. Bootstrap the cluster

Actions -> Bootstrap cluster -> cluster: <name>, dry_run: true

This derives the Gateway's listeners, the certificate's hostnames and the monitored namespaces from every environment that claims the cluster. Adding an installation therefore needs no second file edited — and cannot end up with a certificate that omits it, which is exactly how one environment ran for six months on a certificate covering only its neighbours.

Read the diff, then run it again with dry_run: false.

4. Outside the repositories

  • DNS for all four hostnames.
  • Keycloak: a client matching clientId, with redirect URIs for all four hosts. A wrong realm or client fails at login, not at deploy, so nothing in CI catches it.
  • The webview wildcard certificate, which cert-manager cannot issue over HTTP-01. It goes in the cluster's bootstrap environment as THEIA_WILDCARD_CERTIFICATE_CERT and _KEY.

5. Deploy

Actions -> Deploy (dispatch) -> environment: <name>

The deploy asserts which cluster it reached before touching anything, shows a helm diff before applying, runs --wait --atomic, and prints a summary read back from the cluster rather than echoed from its inputs.

A note on identity

An installation with no identity provider configured yet must say so explicitly with keycloak.allowUnauthenticated: true. The chart otherwise refuses to render.

That flag exists because the oauth2-proxy configuration is emitted regardless of whether Keycloak is enabled — the operator mounts it into every session pod by literal name, so it cannot be conditional. Left at the chart's defaults it points the proxy at a host that does not exist, and sessions fail at the proxy rather than running unauthenticated. That is the worst of both outcomes, so the chart makes you choose deliberately.