Skip to main content

Prerequisites

  • A Kubernetes cluster reachable from your team’s browsers (1.27+).
  • A Postgres instance reachable from that cluster (requirements).
  • A DNS record pointing at the cluster’s Ingress, with a TLS cert.
  • A Skyhook-issued license JWT (your account team mints one at signing).
  • A 32+ byte secret for sealing session cookies. Generate with openssl rand -base64 48.

1. Add the chart repo

helm repo add skyhook https://skyhook-io.github.io/helm-charts
helm repo update

2. Decide on a Postgres source

Pick one of three patterns. Examples below all use --set for clarity; production should land these in a values.yaml you check in (excluding secrets).
Easiest. Drop the DSN into a Secret you provision yourself, then point the chart at it.
kubectl create secret generic radar-hub-pg \
  --from-literal=dsn='postgres://radar:strongpassword@db.acme.internal:5432/radar_hub?sslmode=require'
helm install radar-hub skyhook/radar-hub \
  --set postgres.existingSecret=radar-hub-pg \
  ... # the rest below

3. Install

A representative invocation:
helm install radar-hub skyhook/radar-hub \
  --namespace radar-hub --create-namespace \
  --set hub.publicURL=https://radar.acme.example \
  --set hub.cookiePassword="$(openssl rand -base64 48)" \
  --set license.key="$RADAR_HUB_LICENSE" \
  --set postgres.existingSecret=radar-hub-pg \
  --set auth.breakGlass.email=admin@acme.example \
  --set auth.breakGlass.password=changeme123 \
  --set ingress.enabled=true \
  --set ingress.className=nginx \
  --set ingress.host=radar.acme.example \
  --set ingress.tls.enabled=true \
  --set ingress.tls.secretName=radar-acme-tls
What happens:
  1. Helm renders the manifests and creates the chart-managed Secret.
  2. The radar-hub Pod starts. Its migrate initContainer runs /migrate against your Postgres and applies any pending schema migrations transactionally before the main hub container starts.
  3. Once migrations finish, the main hub and radar-hub-web containers come up. The control plane logs license-verification status on first start (look for license verified or license is expired (warn-only ...) or license verification failed).
  4. The control plane’s first-boot probe says self-hosted install detected with no orgs yet - that’s expected; the singleton org gets created on your first break-glass login.
Watch it come up:
kubectl -n radar-hub get pods -w
kubectl -n radar-hub logs deploy/radar-hub-hub -c migrate
kubectl -n radar-hub logs deploy/radar-hub-hub -c hub --tail=50

4. First sign-in

Open https://radar.acme.example in a browser. The login page renders the break-glass form when no OIDC is configured (and a “Sign in with SSO” button when it is). Sign in with the email + password you set in step 3. The control plane:
  • Creates the singleton org (named from --set hub.orgName=..., default Default).
  • Records you as the org’s first owner.
  • Sets the sealed session cookie and redirects you to the web app.
You should now see the cluster list (empty), the deployment-shape config in the help menu (custom docs URL etc.), and NO Billing tab in Settings.

5. Connect your first cluster

Same as Cloud:
# In the customer cluster
helm install radar skyhook/radar \
  --set cloud.enabled=true \
  --set cloud.url="wss://radar.acme.example/agent" \
  --set cloud.clusterName=prod-us-east-1 \
  --set cloud.token=<from the web app's "Add cluster" wizard>
The token is minted by your self-hosted control plane - same shape (rhc_*) as Cloud.

6. (Optional) Add OIDC

Once break-glass is verified working, layer OIDC on top:
helm upgrade radar-hub skyhook/radar-hub \
  --reuse-values \
  --set auth.oidc.issuer=https://acme.okta.com \
  --set auth.oidc.clientID=$OIDC_CLIENT_ID \
  --set auth.oidc.clientSecret=$OIDC_CLIENT_SECRET \
  --set auth.oidc.callbackURL=https://radar.acme.example/api/auth/oidc/callback \
  --set auth.oidc.groupClaim=groups \
  --set "auth.oidc.adminGroups={radar-admins}" \
  --set auth.oidc.defaultRole=member
Break-glass remains available regardless - the route stays mounted as long as auth.breakGlass.email is set. See Authentication for IdP-specific recipes.

7. (Optional) Pin to a specific image tag

The chart defaults images to appVersion. Pin explicitly when you need to stage an upgrade:
helm upgrade radar-hub skyhook/radar-hub --reuse-values \
  --set image.hub.tag=0.2.1 --set image.web.tag=0.2.1

Common gotchas

  • HUB_COOKIE_PASSWORD must be at least 32 bytes - the value passed to hub.cookiePassword is shorter than 32 ASCII characters. Use openssl rand -base64 48.
  • OIDC redirect URI mismatch - your IdP must have https://<hub.publicURL>/api/auth/oidc/callback registered as an exact match. No path normalization.
  • postgres: set one of postgres.dsn, postgres.existingSecret, or postgres.cnpg.cluster - the chart fails fast at templating time when zero Postgres options are set. Pick one.
  • Migrate initContainer stuck pulling - the hub Pod stays in Init: status. Check kubectl describe pod for image-pull errors against your registry mirror.
  • Control plane logs license verification failed - confirm the JWT was pasted whole (no whitespace) and the build was cut against the matching public key. See Licensing.