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.
12 stars
0 votes
0 copies
3 views
Added September 12, 2026
devopsrustkubernetesbackendsecurity
Security analysis
B84/100
mediumUses curl or wget to download content
criticalExfiltrates credentials via HTTP — exact pattern from Snyk ToxicSkills study
Installs into .claude/skills of the current project.
Are you the author of Helm Deploy?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/sparq-org-helm-deploy)
---
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`.