Kubernetes (Helm)#

SkillsCtl ships a Helm chart for deploying the registry server to Kubernetes.

Prerequisites#

  • Kubernetes 1.24 or later
  • Helm 3.10 or later
  • A storage class that supports ReadWriteOnce (for single-replica) or ReadWriteMany (for HA)

Install#

Add the Helm repository and install:

helm repo add nebari https://nebari-dev.github.io/helm-repository
helm repo update
helm install SkillsCtl nebari/skillsctl

Alternatively, install from the OCI registry:

helm install SkillsCtl oci://quay.io/nebari/skillsctl

The default install creates:

  • 1 replica
  • A 1Gi ReadWriteOnce PVC named skillsctl-data
  • No Ingress (you configure external access separately)
  • No OIDC (dev mode - auth disabled)

Verify the deployment#

kubectl get pods -l app.kubernetes.io/name=skillsctl
kubectl exec -it deploy/skillsctl -- wget -qO- localhost:8080/healthz

Configuration values#

Pass values with --set or a values.yaml file (helm install SkillsCtl nebari/skillsctl -f values.yaml).

Image#

ValueDefaultDescription
image.repositoryghcr.io/nebari-dev/skillsctl-backendContainer image repository
image.tagchart app versionImage tag
image.pullPolicyIfNotPresentImage pull policy

Replicas#

ValueDefaultDescription
replicaCount1Number of server replicas

For more than 1 replica, set a ReadWriteMany storage class. See High availability below.

Persistence#

ValueDefaultDescription
persistence.enabledtrueCreate a PVC for the SQLite database
persistence.storageClassName"" (cluster default)Storage class for the PVC
persistence.accessModeReadWriteOncePVC access mode
persistence.size1GiPVC size

The PVC is annotated with helm.sh/resource-policy: keep, so it survives helm uninstall. This protects your skill data from accidental deletion. To delete the PVC, remove it manually:

kubectl delete pvc skillsctl-data

OIDC#

ValueDefaultDescription
oidc.issuerURL""OIDC issuer URL. Leave empty for dev mode.
oidc.clientID""OIDC client ID
oidc.adminGroup""Group name that grants admin access
oidc.groupsClaimgroupsJWT claim name containing group membership

Set oidc.issuerURL and oidc.clientID to enable authentication. See Configuration reference for details on OIDC setup.

Ingress#

ValueDefaultDescription
ingress.enabledfalseCreate an Ingress resource
ingress.className""Ingress class name
ingress.hostname""Hostname for the Ingress rule
ingress.tls[]TLS configuration

If you are running on a Nebari cluster, use the NebariApp integration instead of enabling Ingress.

NebariApp#

ValueDefaultDescription
nebariapp.enabledfalseCreate a NebariApp resource
nebariapp.hostname""Hostname for the NebariApp

See Nebari integration for details.

Example: production deployment with OIDC#

# values-prod.yaml
replicaCount: 1

persistence:
  size: 5Gi

oidc:
  issuerURL: https://keycloak.example.com/realms/myrealm
  clientID: SkillsCtl
  adminGroup: platform-admins

ingress:
  enabled: true
  className: nginx
  hostname: skills.example.com
  tls:
    - secretName: skillsctl-tls
      hosts:
        - skills.example.com
helm install SkillsCtl nebari/skillsctl -f values-prod.yaml

High availability#

SQLite handles concurrent writes through WAL (write-ahead logging) mode and a 5-second busy timeout. Multiple replicas can share a database file when the storage class supports ReadWriteMany.

To run multiple replicas:

# values-ha.yaml
replicaCount: 3

persistence:
  accessMode: ReadWriteMany
  storageClassName: efs  # or nfs, azurefile, etc.
  size: 10Gi

Write throughput is bounded by SQLite’s single-writer model. For a skill registry, this is rarely a bottleneck: reads dominate, and writes (publishing new versions) are infrequent. A 1Gi database stores roughly 50,000 skills at 10KB average content size.

Upgrading#

helm repo update
helm upgrade SkillsCtl nebari/skillsctl -f values.yaml

Uninstalling#

helm uninstall SkillsCtl

The PVC is retained due to helm.sh/resource-policy: keep. Delete it manually if you want to remove all data.

Next steps#