Deploy your own hub

Helm Deployment

Deploy the kedge hub with Helm — local kind, single-node k3s, or full production.

The kedge-hub Helm chart deploys kcp + kedge-hub as a single StatefulSet. The same chart works for local kind, a single-node k3s on a VPS, or a full production setup behind cert-manager and a real ingress controller.

Prerequisites

ToolDescription
kubectlKubernetes CLI
helm v3+Package manager
A target clusterkind / k3s / EKS / GKE / AKS — any will do

For production you’ll also want cert-manager for TLS and an ingress controller (nginx, traefik, Cloudflare Tunnel — see Ingress).

Quick install (local kind)

Try the hub locally first; it’s the fastest feedback loop.

# 1. Cluster
kind create cluster --name kedge

# 2. Values file
cat > values-kind.yaml <<EOF
hub:
  hubExternalURL: "https://localhost:9443"
  devMode: true
  staticAuthToken: "$(openssl rand -hex 32)"
EOF

# 3. Install
helm upgrade --install kedge \
  oci://ghcr.io/faroshq/charts/kedge-hub \
  -f values-kind.yaml \
  --namespace kedge-system \
  --create-namespace

# 4. Wait
kubectl -n kedge-system wait --for=condition=ready pod \
  -l app.kubernetes.io/name=kedge-hub --timeout=120s

# 5. Port-forward
kubectl -n kedge-system port-forward svc/kedge-kedge-hub 9443:9443

In another terminal:

kubectl kedge login \
  --hub-url https://localhost:9443 \
  --token $(grep staticAuthToken values-kind.yaml | awk '{print $2}' | tr -d '"') \
  --insecure-skip-tls-verify

You’re in. Try kubectl kedge edge list.

Production deployment

For a public hub you need:

  1. A public ingress with a real DNS name (see Ingress)
  2. TLS — usually via cert-manager + Let’s Encrypt
  3. Auth — static token for personal use, OIDC for teams (see Security)

Example production values:

hub:
  hubExternalURL: "https://hub.example.com"
  devMode: false

  # Pick one — static token OR OIDC (idp section below)
  staticAuthToken: "<generated-with-openssl-rand-hex-32>"

  tls:
    selfSigned:
      enabled: false
    certManager:
      enabled: true
      issuerRef:
        name: letsencrypt-prod
        kind: ClusterIssuer
      dnsNames:
        - "hub.example.com"

# Only for OIDC — omit the staticAuthToken above if you set this
idp:
  issuerURL: "https://idp.example.com"
  clientID: "kedge"
  clientSecret: "<secret>"

ingress:
  enabled: true
  className: "nginx"   # or traefik, cloudflare-tunnel, etc.
  hosts:
    - host: hub.example.com
      paths:
        - path: /
          pathType: ImplementationSpecific

Install or upgrade:

helm upgrade --install kedge \
  oci://ghcr.io/faroshq/charts/kedge-hub \
  -f values-prod.yaml \
  --namespace kedge-system \
  --create-namespace

Operations

Logs

# kcp (the multi-tenant API server)
kubectl -n kedge-system logs kedge-kedge-hub-0 -c kcp

# kedge-hub (the API + tunnel endpoints)
kubectl -n kedge-system logs kedge-kedge-hub-0 -c hub

Upgrading

helm upgrade kedge oci://ghcr.io/faroshq/charts/kedge-hub \
  -f values.yaml --namespace kedge-system

TLS secrets are annotated helm.sh/resource-policy: keep so they survive helm uninstall. The kcp PVC is also retained.

Uninstall

helm uninstall kedge --namespace kedge-system

To fully wipe:

kubectl -n kedge-system delete pvc --all
kubectl -n kedge-system delete secret kedge-kedge-hub-tls
kubectl delete namespace kedge-system

Values reference

Hub

KeyDescriptionDefault
hub.hubExternalURLRequired. External URL agents and users hit. Embedded in kubeconfigs and OIDC callbacks.""
hub.listenAddrPod listen address.:9443
hub.devModeSkip OIDC issuer TLS verification. Dev only.false
hub.staticAuthTokenStatic bearer token. Bypasses OIDC entirely.""

Identity provider (OIDC)

KeyDescriptionDefault
idp.issuerURLOIDC issuer URL.""
idp.clientIDOIDC client ID.kedge
idp.clientSecretOIDC client secret.""

TLS

KeyDescriptionDefault
hub.tls.existingSecretUse an existing TLS Secret.""
hub.tls.selfSigned.enabledGenerate a self-signed cert.true
hub.tls.selfSigned.dnsNamesExtra DNS SANs.[]
hub.tls.selfSigned.ipAddressesIP SANs.["127.0.0.1"]
hub.tls.certManager.enabledIssue via cert-manager.false
hub.tls.certManager.issuerRef.nameIssuer name.""
hub.tls.certManager.issuerRef.kindIssuer kind.ClusterIssuer
hub.tls.certManager.dnsNamesAdditional DNS SANs.[]

Storage & kcp

KeyDescriptionDefault
persistence.sizekcp data PVC size.10Gi
persistence.storageClassStorage class."" (cluster default)
kcp.featureGateskcp feature gates.WorkspaceMounts=true
kcp.extraArgsExtra kcp CLI arguments.[]

Networking

KeyDescriptionDefault
service.typeService type.ClusterIP
ingress.enabledEnable Ingress.false
ingress.classNameIngress class name.""