helm-deploy · git:20260715.7b10cc3 · 2026-07-15 · sha256 1f0c7a1272b84db4
helm-deploy git:20260715.7b10cc3B
Immutable. This exact content is served forever at /api/v1/blob/1f0c7a1272b84db4.
--- name: helm-deploy description: Deploy sparq-server or configure the planned native sparq-lws-core deployment on Kubernetes with the in-repo Helm chart or plain quickstart manifest. Use when installing, configuring, exposing, upgrading, or validating deploy/helm/sparq, including existing-Secret auth, ingress-nginx TLS, selector-dependent images/ports/probes, persistent data, and single-replica safety constraints. --- # Deploy sparq with Helm > [GPT-5.6] Verified against `deploy/helm/sparq` on 2026-07-15. The chart targets > Kubernetes 1.20 or later and does not build images. The `sparq-server` GHCR image > is published; the LWS selector becomes runnable only after sq-lmz40 publishes its image. ## Preserve the security boundary Treat these as invariants: - Keep `SPARQ_AUTH_TOKEN` in an existing Kubernetes `Secret`. Never pass a token through Helm values or commit a `Secret` manifest. - Keep the built-in Service as `ClusterIP`. Use the optional ingress-nginx Ingress for public access; it requires a TLS Secret and forces HTTPS redirects. - Keep the chart's non-root, read-only-root-filesystem, dropped-capability, and disabled-service-account-token settings. - Use `/health` on port 3030 for `sparq-server`; use `/livez` and `/readyz` on port 3000 for `lws`. - [GPT-5.6] Run exactly one replica of either server. `sparq-server` has an unreplicated writable in-memory store. The planned canonical LWS image lacks its opt-in Redis replay backend, and Redis alone would not provide a shared blob store. The `sparq-server` image is open by default at the image layer because it bakes `SPARQ_ALLOW_REMOTE=1`. The chart refuses to render that server without an auth Secret. Do not remove the token wiring. The token always gates writes; set `auth.requireTokenForReads=true` to gate reads too. ## Install sparq-server privately Create the Secret before installing the chart: ```sh kubectl create namespace sparq kubectl create secret generic sparq-auth-token \ --namespace sparq \ --from-literal=SPARQ_AUTH_TOKEN="$(openssl rand -hex 32)" helm upgrade --install sparq ./deploy/helm/sparq \ --namespace sparq \ --set auth.existingSecret=sparq-auth-token ``` This creates only a `ClusterIP` Service. Test it over a local port-forward: ```sh kubectl port-forward --namespace sparq svc/sparq 3030:3030 curl http://127.0.0.1:3030/health ``` ## Expose sparq-server over HTTPS Use the built-in Ingress only with ingress-nginx and a pre-provisioned or cert-manager-managed TLS Secret: ```sh helm upgrade --install sparq ./deploy/helm/sparq \ --namespace sparq \ --set auth.existingSecret=sparq-auth-token \ --set auth.requireTokenForReads=true \ --set ingress.enabled=true \ --set ingress.host=sparq.example.com \ --set-string 'ingress.annotations.cert-manager\.io/cluster-issuer=letsencrypt-prod' \ --set ingress.tls.enabled=true \ --set ingress.tls.secretName=sparq-tls ``` For a different Ingress or Gateway controller, leave `ingress.enabled=false` and create a controller-specific HTTPS-only route to the `ClusterIP` Service. ## Install LWS Use this path only after sq-lmz40 publishes `ghcr.io/sparq-org/sparq-lws-core`. Supply HTTPS URLs for the public base URL and trusted OIDC issuer. Selecting `server=lws` automatically selects `ghcr.io/sparq-org/sparq-lws-core`, port 3000, `SOLID_SERVER_BIND=0.0.0.0:3000`, `/livez`, and `/readyz`. ```sh helm upgrade --install sparq-lws ./deploy/helm/sparq \ --namespace sparq-lws \ --create-namespace \ --set server=lws \ --set lws.trustedIssuer=https://idp.example.com \ --set lws.baseUrl=https://pod.example.com \ --set ingress.enabled=true \ --set ingress.host=pod.example.com \ --set ingress.tls.enabled=true \ --set ingress.tls.secretName=lws-tls ``` Do not scale this release horizontally. A future image and chart revision must provide both shared replay protection and a shared durable data/blob path before raising `replicaCount`. ## Use persistence and private images - Set `persistence.enabled=true` to create a PVC mounted at `/data`, or also set `persistence.existingClaim` to use a pre-provisioned PVC. - Leave `image.repository` empty for the selector-dependent canonical image. Set `image.repository`, `image.tag`, and `imagePullSecrets` for a fork, pinned release, or private registry. The default `latest` tag uses pull policy `Always`; use `IfNotPresent` only with an immutable tag. - Set `service.port` only to change the cluster-internal Service port. The container port and health contract remain selector-dependent. ## Use the plain manifest Follow the header in `deploy/helm/quickstart/sparq-server-quickstart.yaml`. Create the namespace and `sparq-auth-token` Secret separately, then apply the file. It intentionally contains no Ingress and no Secret object. ## Validate changes ```sh helm lint ./deploy/helm/sparq --set auth.existingSecret=test-secret helm template sparq ./deploy/helm/sparq \ --set auth.existingSecret=test-secret > /tmp/sparq.yaml kubeconform -strict -summary -exit-on-error /tmp/sparq.yaml ``` Read `deploy/helm/README.md` and `deploy/helm/sparq/values.yaml` for the complete value reference. Unsafe combinations fail during `helm lint` or `helm template` through `values.schema.json`.