Skip to content
Railgrid Docs
Sections
Open console

Enter a topic to search documentation.

    Self-host an existing provider

    Run a capability on your infrastructure and connect it to a hub.

    A provider is a chart you install into a Kubernetes cluster you administer. It authenticates to the hub’s kcp with a kubeconfig the hub mints for it, registers itself in the hub’s catalog, and serves its API to the workspaces that enable it. The steps below are the same for every provider; the per-provider guides add the state, credentials, and settings each one needs.

    Prerequisites

    • An existing hub you can reach, and permission to onboard a provider: a platform administrator (listed in the hub’s adminUsers), or an organization administrator for an organization-owned provider.
    • A Kubernetes runtime you administer, Helm, and kubectl.
    • Network access from the provider pods to the hub and to every kcp shard’s advertised virtual-workspace endpoint. Connectivity to the public console alone is not enough.
    • The provider’s own dependencies: a Postgres database, an S3 bucket, a Gateway. Each guide lists them.

    Run the providers in the hub’s cluster when you can. They then reach the hub at its in-cluster Service, which is what the hub bakes into their kubeconfigs when hub.internalURL is set, and the kcp shards through the same split-horizon names the hub uses.

    1. Get the provider’s kubeconfig

    The hub mints one credential per provider: a ServiceAccount in a provider workspace of its own (root:railgrid:providers:<name>), cluster-admin there and nothing above it. Three ways to get it:

    • Console, organization-owned provider. Open Providers → Self-Hosting, select the provider recipe, and follow the generated instructions. They include the chart version, the provider-specific values, and the command that creates the runtime Secret.
    • Console, platform provider. A platform administrator onboards it in the admin area and downloads the kubeconfig there.
    • API, scripted. Creating a Provider object in the hub’s root:railgrid:system:providers workspace does exactly what the admin area does: the hub creates the provider workspace, the ServiceAccount, and writes the kubeconfig to Secret <name>-kubeconfig in that workspace’s default namespace. Railgrid’s own environments mint all six public providers this way from one idempotent script.
    Terminal
    # With an admin kubeconfig for the hub's kcp (front proxy), create the Provider...
    WS=https://kcp.example.com/clusters/root:railgrid:system:providers
    curl --cert admin.crt --key admin.key -X POST -H 'Content-Type: application/json' \
      -d '{"apiVersion":"admin.railgrid.ai/v1alpha1","kind":"Provider","metadata":{"name":"code"},"spec":{"displayName":"code"}}' \
      "$WS/apis/admin.railgrid.ai/v1alpha1/providers"
    # ...then read the minted kubeconfig once status.secretRef appears.
    curl --cert admin.crt --key admin.key "$WS/api/v1/namespaces/default/secrets/code-kubeconfig" \
      | python3 -c 'import sys,json,base64; print(base64.b64decode(json.load(sys.stdin)["data"]["kubeconfig"]).decode())' \
      > code.kubeconfig

    The kubeconfig’s server is the hub (hub.internalURL when set, else hub.hubExternalURL), and its CA data is the hub’s provider CA bundle. It is a credential; keep it out of version control and never use it as a Helm --kube-context.

    2. Create the runtime Secret

    In the cluster where the chart will run:

    Terminal
    kubectl create namespace railgrid-provider-code
    kubectl --namespace railgrid-provider-code create secret generic railgrid-provider-kubeconfig \
      --from-file=kubeconfig=./code.kubeconfig

    The filename can differ, but the Secret data key must be kubeconfig; the charts mount that exact key. Every public provider defaults to Secret name railgrid-provider-kubeconfig (providerKubeconfig.secretName), except the infrastructure provider in operator mode, which reads operator.providerKubeconfigSecret.name. A Secret in the hub cluster is not visible from another cluster; create it where the pods run.

    3. Set the hub values

    Every public provider chart takes the same hub block:

    YAML
    hub:
      # Where heartbeats go. In the hub's cluster, the hub Service.
      url: https://railgrid-hub.railgrid-system.svc.cluster.local:9443
      # Leave empty: heartbeats authenticate with the provider's own
      # ServiceAccount token. Naming a Secret that does not exist wedges the
      # pod in CreateContainerConfigError.
      tokenSecretRef:
        name: ""
    catalogEntry:
      enabled: true     # the init container registers the provider with the hub

    The provider verifies the hub’s serving certificate against the system roots plus the CA bundle inside its own kubeconfig, which the hub minted from hub.providerCASecretName. A hub on a private CA therefore needs nothing more than the Secret from step 2; hub.insecure stays false and is only for development hubs with throwaway certificates. To trust a different bundle, set RAILGRID_HUB_CA_FILE (or RAILGRID_HUB_CA_DATA) in the pod’s environment. Several providers also take a browser-facing hub origin (hub.publicURL, hub.externalURL, hub.actionsExternalURL) for redirects and agents; those must be the public console URL, not the Service.

    4. Install the chart

    The charts are published at oci://ghcr.io/railgrid/charts/railgrid-<provider>-provider. Each provider has its own version line; find the current one and pin it:

    Terminal
    helm show chart oci://ghcr.io/railgrid/charts/railgrid-code-provider | grep -E '^(version|appVersion)'
    helm upgrade --install code oci://ghcr.io/railgrid/charts/railgrid-code-provider \
      --version CHART_VERSION --namespace railgrid-provider-code --values code-values.yaml

    Railgrid’s environments follow 0.2.x through Flux. Images for the public providers are public; a private provider needs an imagePullSecrets entry.

    5. Verify

    1. The pod is Running. The init container has applied the CatalogEntry, schemas, and APIExport into the provider workspace through the kubeconfig; if it fails, see the table below.
    2. The provider appears in the console’s provider list for the hub.
    3. Enable the provider in a test workspace and complete its quickstart. Only this proves the whole path: hub, kcp routing, and the provider’s own backend.

    A fresh provider is UNREADY until a workspace binds it

    Right after install, every provider reports /healthz 200 but /readyz 503 with cannot reach the APIExport virtual workspace ... APIExportEndpointSlice <name>.providers.railgrid.ai publishes no endpoints yet, and its CatalogEntry carries BackendHealthy=False. This is kcp, not a fault: a shard publishes a virtual-workspace endpoint only once a workspace on it has bound the export. Enabling the provider in one workspace makes it Ready. A Helm install with --wait on such a provider times out for the same reason.

    Diagnose an installation failure

    SymptomCheckFix
    Init container: x509: certificate signed by unknown authority against the hubThe kubeconfig was minted before the hub had providerCASecretName, or the hub’s serving certificate changedRe-mint and refresh the kubeconfig
    Pod running but Ready=False, logs show x509 against a shard hostnameThe provider CA bundle lacks the kcp server CAAppend root-server-ca to the bundle, restart the hub, refresh the kubeconfig
    CreateContainerConfigErrorhub.tokenSecretRef.name or another *SecretRef names a Secret that does not existCreate the Secret or leave the reference empty
    ImagePullBackOffImage tag and registry accessPin image.tag to a published version; add a pull Secret for private images
    Pod ready, provider missing from the consoleHeartbeat and CatalogEntry conditions in the provider workspaceCheck hub.url is reachable from the pod and the init container succeeded
    /readyz 503, publishes no endpoints yetNothing has bound the exportEnable the provider in a workspace
    Terminal
    kubectl --namespace railgrid-provider-code get events --sort-by=.lastTimestamp
    kubectl --namespace railgrid-provider-code logs -l app.kubernetes.io/instance=code --all-containers=true --tail=100

    Redact credentials before sharing diagnostics.

    Refresh a provider kubeconfig

    The hub rewrites each provider’s kubeconfig Secret in the provider workspace when it reconciles, for example after the provider CA bundle or hub.internalURL changes. The copy in your runtime namespace does not follow. Re-read the Secret from the hub (step 1), re-create the runtime Secret (step 2), and restart the provider pods. Railgrid’s environments keep this as one idempotent script run after every hub trust change.

    Remove a provider

    Disable the provider in every workspace that uses it and follow the provider’s cleanup instructions first, then helm uninstall the release. Deleting the Provider object on the hub tears down the provider workspace and strands tenant bindings; do not use it as a temporary disable. See Provider access and lifecycle .

    Provider guides