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.
Scanned 9/12/2026
Install to Claude Code
npx -y skills add sparq-org/sparq --skill helm-deploy --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Helm Deploy?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/sparq-org-helm-deploy)More formats (shields.io, HTML) on the badges page.
---
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`.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!