Run CIHub on Kubernetes

Install CIHub on a Kubernetes cluster with its Helm chart, get a Postgres for it (CloudNativePG, a managed service or your own server), expose it, and update it.

The Helm chart installs a Job that applies the migrations at each install and upgrade, a Deployment of identical replicas, a Service, and, if you want, an Ingress or a Gateway API HTTPRoute.

You need:

Get a Postgres

CIHub needs a database that it owns, through a role that is neither a superuser nor BYPASSRLS. CIHub isolates the organizations with the row level security of Postgres, which such a role ignores: CIHub refuses to start with one. You give CIHub the URL of the database in a Secret, under the key uri.

With the CloudNativePG operator in the cluster, one resource creates the database, its owner, which is not a superuser, and the Secret cihub-db-app, whose key uri holds the URL:

cihub-db.yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cihub-db
spec:
  instances: 2
  imageName: ghcr.io/cloudnative-pg/postgresql:17
  bootstrap:
    initdb:
      database: cihub
      owner: cihub
  storage:
    size: 10Gi
kubectl apply -f cihub-db.yaml

The Secret of the database is cihub-db-app: you create none.

Create the Secrets

One Secret holds the keys of the App, and one the sealing key, at least 32 bytes, which seals the GitHub tokens of the people who sign in. With the keys of the App:

kubectl create secret generic cihub-github \
  --from-file=private-key.pem=<path to the private key> \
  --from-literal=webhook-secret='<webhook secret>' \
  --from-literal=client-secret='<client secret>'
kubectl create secret generic cihub-sealing \
  --from-literal=secret="$(openssl rand -hex 32)"

Keep the sealing key: a new one signs every person out.

Install the chart

helm install cihub oci://ghcr.io/getcihub/charts/cihub \
  --set database.existingSecret=cihub-db-app \
  --set database.secretExistingSecret=cihub-sealing \
  --set github.existingSecret=cihub-github \
  --set github.appId='<App ID>' \
  --set github.clientId='<Client ID>' \
  --set publicUrl=https://cihub.example.com \
  --set replicas=2
  • publicUrl, github.clientId and the client secret turn on the sign-in to the dashboard. Without them, only the API tokens work.
  • Two replicas keep one that receives the webhooks while a pod or a node is lost. The replicas share the work through Postgres; each one opens up to database.poolSize connections (10).
  • For a GitHub Enterprise Server, add --set github.url=https://<your GitHub server>.

The migration Job runs first, then the pods start. Check them:

kubectl get pods -l app.kubernetes.io/instance=cihub
helm test cihub

helm test posts an unsigned delivery to the Service: CIHub must refuse it.

Expose CIHub

GitHub and the people reach CIHub on one address, with every path: the dashboard, /api, /auth and /webhooks/github. With an Ingress:

values.yaml
ingress:
  enabled: true
  className: nginx
  hosts:
    - host: cihub.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - hosts:
        - cihub.example.com
      secretName: cihub-tls

Or with a Gateway: httpRoute.enabled: true, with httpRoute.hostnames and httpRoute.parentRefs.

The dashboard keeps a stream open on /api/v1/orgs/<org>/stream: the proxy must not buffer it, and must keep it open past 15 seconds without data. Serve HTTP/2 to the browsers.

Every value of the chart is in helm/cihub/README.md.

Create an API token

Once the App is installed on your organization, a script or a CI that calls the API needs a token of the organization. The command prints it once:

kubectl exec deploy/cihub -- cihub-server token create --config /etc/cihub/server.yaml --org <login of the organization>

Update CIHub

helm upgrade cihub oci://ghcr.io/getcihub/charts/cihub --reuse-values

The migration Job applies the migrations of the new version before the pods roll.

Go back to an older version

When the older version has fewer migrations, the running version reverts its own first, then Helm rolls back. --to takes the newest migration of the older version: the last file of migrations/ in its tag.

kubectl exec deploy/cihub -- cihub-server migrate down --config /etc/cihub/server.yaml --to <version>
helm rollback cihub

The data of the reverted migrations is lost, and the pods of the newer version fail until the rollback ends.

Next

Install the App on your repositories, then merge your first pull request.

On this page

For agentsThis page as Markdown:/docs/install/kubernetes.md