Skip to content
Railgrid Docs
Sections
Open console

Enter a topic to search documentation.

    Install the hub

    Choose embedded or external kcp, configure a production hub, and verify the console.

    Choose a deployment

    ModeHub workloadConstraint
    Embedded kcpStatefulSetOne replica; embedded etcd uses its PVC
    External kcpDeploymentHub replicas can scale; operate kcp and its storage separately (guide )

    A hub installation does not install every provider. Install the providers your users need after verifying the hub.

    Prerequisites

    Use a Kubernetes cluster you administer, Helm, kubectl, and a reviewed Railgrid chart version. For public access, configure DNS, TLS, and ingress . Use development credentials only in an isolated test installation.

    The chart is published as oci://ghcr.io/railgrid/charts/railgrid-hub. Its version is the Railgrid release without the v prefix (release vX.Y.Z is chart X.Y.Z), and its appVersion names the matching hub image. Resolve the version once and reuse it in every command below. Helm reports the newest published chart when no version is given:

    Terminal
    HUB_CHART_VERSION=$(helm show chart oci://ghcr.io/railgrid/charts/railgrid-hub \
      | awk '/^version:/ {print $2}')
    echo "$HUB_CHART_VERSION"

    To install a release you have reviewed rather than the newest one, set HUB_CHART_VERSION to that release’s chart version instead. The releases page lists them.

    Local hub

    For a laptop or a throwaway evaluation, do not install the chart by hand. railgrid dev init creates one kind cluster running the hub on embedded kcp, the default providers, and an agent that joins that same cluster as an edge, then signs you in with a static development token at https://console.127.0.0.1.sslip.io:9443:

    Terminal
    railgrid dev init

    railgrid dev delete removes it again. Run Railgrid locally covers prerequisites, options, and troubleshooting, and the railgrid dev init reference lists every flag, including --chart-path for a hub chart you are changing. That environment is not a production installation; the rest of this page configures a hub other people use.

    Configure a production hub

    For a shared cluster, prepare DNS, ingress and TLS , and OIDC first. The values below are what a production hub against external kcp looks like. Substitute your hostnames, identity provider, administrators, and proxy ranges. For embedded kcp, drop the kcp block and keep replicaCount: 1.

    Save this as hub-values.yaml:

    YAML
    replicaCount: 2                 # more than 1 requires external kcp
    
    kcp:
      external:
        enabled: true
        existingSecret: railgrid-kcp   # key admin.kubeconfig; see External kcp
    
    hub:
      hubExternalURL: https://console.example.com
      # In-cluster address baked into minted provider kubeconfigs, so
      # provider -> hub traffic never leaves the cluster. The serving
      # certificate below must cover this name.
      internalURL: https://railgrid-hub.railgrid-system.svc.cluster.local:9443
      adminUsers:
        - admin@example.com
      # Reverse proxies in front of the hub (ingress pods, load balancer).
      # Required behind any proxy; see Ingress.
      trustedProxyCIDRs:
        - 10.244.0.0/16
      # Hosts the console may embed in an iframe: App Studio previews
      # under the infrastructure provider's apps domain.
      portalFrameSources:
        - https://*.apps.example.com
      security:
        providerDelegatedTokens: platform
      tls:
        # A certificate you issue (below). Setting this turns the chart's
        # selfSigned and certManager modes off.
        existingSecret: railgrid-hub-serving-tls
      # CA bundle embedded in every minted provider kubeconfig.
      providerCASecretName: railgrid-provider-ca
    
    idp:
      issuerURL: https://auth.example.com
      clientID: railgrid
      # Keep accounts when you add a Dex connector or change issuer.
      linkVerifiedEmailIssuers:
        - https://auth.example.com

    Everything the example leaves out keeps the chart default: development mode is off, the chart creates no Ingress or HTTPRoute, and the hub image is the chart’s appVersion. Route traffic with your own Ingress or HTTPRoute (see Ingress ), or enable ingress or httpRoute when the chart’s objects fit your controller.

    Set adminUsers to identities as resolved by your authentication setup: the email for OIDC users. An empty list disables the admin surface, including provider onboarding.

    Before installing, create the Secrets the values reference: the kcp kubeconfig (external kcp only), the serving certificate, and the provider CA bundle. The next section covers the certificates. Then render and install:

    Terminal
    helm template railgrid-hub oci://ghcr.io/railgrid/charts/railgrid-hub \
      --version "$HUB_CHART_VERSION" --namespace railgrid-system --values hub-values.yaml
    helm upgrade --install railgrid-hub oci://ghcr.io/railgrid/charts/railgrid-hub \
      --version "$HUB_CHART_VERSION" --kube-context HOSTING_CONTEXT \
      --namespace railgrid-system --create-namespace \
      --values hub-values.yaml --wait --timeout 15m

    Name the release railgrid-hub. The chart’s full name then collapses to railgrid-hub, which is the Service name the provider charts default to in hub.url.

    Replace HOSTING_CONTEXT with the hosting cluster’s kubeconfig context. The hub reads the OIDC discovery document at start and restarts until the issuer is reachable, so install Dex first. A successful Helm rollout verifies workload readiness; complete the authentication and workspace checks below before giving users access.

    Serving certificate and provider trust

    Providers verify the hub’s certificate. A minted provider kubeconfig carries no insecure-skip-tls-verify unless the hub runs in development mode; it embeds the CA bundle from hub.providerCASecretName (Secret key ca.crt) and trusts nothing else. Two consequences:

    • The hub’s serving certificate must be issued by a CA you control and keep stable. The chart’s tls.selfSigned mode generates a fresh CA on every upgrade, which invalidates every minted kubeconfig on the next release. Issue the certificate yourself.
    • With external kcp, providers also follow APIExport endpoints to the shards and verify the shards’ certificates with the same bundle. Append kcp’s root-server-ca certificate (Secret root-server-ca in the kcp namespace) to the bundle, or providers start but report x509: certificate signed by unknown authority against the shard hostnames and stay unready.

    With cert-manager installed, this creates a ten-year CA, an Issuer from it, and a one-year serving certificate. The hub reads its certificate once at start; the long duration and early renewal mean any hub rollout inside the renewal window picks the new certificate up. Browsers never see this certificate when TLS terminates at your edge; providers do.

    YAML
    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: selfsigned
      namespace: railgrid-system
    spec:
      selfSigned: {}
    ---
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: railgrid-hub-ca
      namespace: railgrid-system
    spec:
      isCA: true
      commonName: railgrid-hub-ca
      secretName: railgrid-hub-ca
      duration: 87600h    # 10y; providers embed it, so rotating it means re-minting them
      renewBefore: 8760h
      privateKey:
        algorithm: ECDSA
        size: 256
        rotationPolicy: Never
      issuerRef:
        name: selfsigned
        kind: Issuer
    ---
    apiVersion: cert-manager.io/v1
    kind: Issuer
    metadata:
      name: railgrid-hub-ca
      namespace: railgrid-system
    spec:
      ca:
        secretName: railgrid-hub-ca
    ---
    apiVersion: cert-manager.io/v1
    kind: Certificate
    metadata:
      name: railgrid-hub-serving
      namespace: railgrid-system
    spec:
      secretName: railgrid-hub-serving-tls
      duration: 8760h     # 1y
      renewBefore: 2160h  # 90d
      dnsNames:
        - console.example.com
        - railgrid-hub
        - railgrid-hub.railgrid-system.svc
        - railgrid-hub.railgrid-system.svc.cluster.local
        - localhost
      ipAddresses:
        - 127.0.0.1
      privateKey:
        algorithm: ECDSA
        size: 256
        rotationPolicy: Always
      issuerRef:
        name: railgrid-hub-ca
        kind: Issuer

    Build the provider CA bundle from the CA certificate, plus kcp’s server CA when kcp is external:

    Terminal
    kubectl --context HOSTING_CONTEXT -n railgrid-system get secret railgrid-hub-ca \
      -o jsonpath='{.data.ca\.crt}' | base64 -d > provider-ca.pem
    # External kcp only:
    kubectl --context HOSTING_CONTEXT -n kcp-system get secret root-server-ca \
      -o jsonpath='{.data.tls\.crt}' | base64 -d >> provider-ca.pem
    
    kubectl --context HOSTING_CONTEXT -n railgrid-system create secret generic railgrid-provider-ca \
      --from-file=ca.crt=provider-ca.pem

    The bundle contains only public certificates and can live in version control. If you change it later, restart the hub and re-copy every provider’s kubeconfig Secret: the hub rewrites the minted Secrets on reconcile, but the copies in provider namespaces do not update themselves. See Provider hosting .

    Use external kcp

    For multiple hub replicas, or for a control plane with its own lifecycle, run kcp separately and point the hub at it with a front-proxy kubeconfig. External kcp with the kcp-operator covers etcd, shards, the front proxy, and minting that kubeconfig. Put it in a Secret in the hub namespace with the key admin.kubeconfig:

    Terminal
    kubectl --context HOSTING_CONTEXT -n railgrid-system create secret generic railgrid-kcp \
      --from-file=admin.kubeconfig=/PATH/TO/FRONT-PROXY.kubeconfig

    Create the namespace first if it does not exist. Protect this kubeconfig as an administrative credential; it is system:kcp:admin. The server address and certificate inside it must be reachable and trusted from the hub pods.

    Changing kcp.embedded/kcp.external on an existing embedded installation does not migrate its data; treat that as a separate storage and control-plane migration.

    Settings to review

    SettingWhy it matters
    hub.hubExternalURLClient-facing origin used by hub flows; match DNS, TLS, and the OIDC redirect URI <hubExternalURL>/auth/callback.
    hub.internalURLIn-cluster origin baked into provider kubeconfigs. Must be a SAN of the serving certificate. Leave empty when providers run outside the cluster.
    hub.adminUsersPlatform administrators; empty disables the admin surface and provider onboarding.
    hub.trustedProxyCIDRsRequired behind any proxy or load balancer, or every visitor shares one rate-limit bucket.
    hub.portalFrameSourcesEvery apps domain whose previews the console embeds, as https://*.<domain>.
    hub.tls.existingSecretThe serving certificate, issued from a CA you keep stable.
    hub.providerCASecretNameThe trust bundle every minted provider kubeconfig carries: hub CA, plus the kcp server CA for external kcp.
    hub.security.providerDelegatedTokensplatform hands providers short-lived workspace-scoped tokens instead of the caller’s bearer. Recommended for production.
    idp.issuerURL, idp.clientIDMust agree character for character with the issuer’s discovery document and the public client registered there.
    idp.linkVerifiedEmailIssuersLets returning users keep their account across a connector or issuer change.
    kcp.external.existingSecretThe front-proxy kubeconfig for external kcp, key admin.kubeconfig.
    replicaCountGreater than one requires external kcp.
    image.hub.tagDefaults to the chart’s appVersion; pin only when you need a different image.

    For defaults and additional settings, use the chart values file . Flags the chart does not model go in hub.extraArgs; the chart refuses an entry that repeats a flag it already renders.

    Installation sources

    The product repo includes executable installation recipes for both modes, run in CI against a fresh kind cluster. Use the recipe and chart from the same revision:

    Verify the installation from the terminal

    Use the explicit hosting-cluster context to inspect the discovered workload and serving container. Follow hosting-cluster diagnostics for pod, rollout, and event commands.

    Terminal
    curl -s https://console.example.com/healthz       # {"status":"ok","oidc":true,...}
    kubectl railgrid login --hub-url https://console.example.com
    kubectl railgrid use
    kubectl api-resources

    For static-token deployments, follow login authentication instead of expecting a browser flow. Success means authentication works, the intended workspace is selectable, and its APIs are discoverable. Then sign in to the console as one of adminUsers and confirm the admin area is available; provider onboarding happens there.

    Next steps

    Install providers , then review operations and recovery . For the complete configuration, use the chart values .