Skip to content

Helm chart

The chart installs the control plane (server, scheduler, worker), a migration job, optional runners and, for evaluation only, single-node Postgres, NATS, MinIO and Valkey. It needs Kubernetes 1.27+ and Helm 3.12+.

Terminal window
helm install slipway oci://ghcr.io/slipway-systems/charts/slipway -n slipway --create-namespace \
--set config.baseUrl=https://slipway.example.com

The bundled dependencies are single-node and unmanaged. Do not use them for production data.

Point at managed services, keep the generated credentials in a Secret you control, and enable ingress:

config:
baseUrl: https://slipway.example.com
secrets:
existingSecret: slipway-credentials # keys: session-secret, master-key
serviceAccount:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/slipway # IRSA / Workload Identity
server:
replicaCount: 3
antiAffinity: hard
autoscaling: { enabled: true, minReplicas: 3, maxReplicas: 12, targetCPUUtilizationPercentage: 65 }
scheduler: { autoscaling: { enabled: true } }
worker: { autoscaling: { enabled: true } }
postgresql:
bundled: { enabled: false }
external: { existingSecret: slipway-db, existingSecretKey: url }
nats:
bundled: { enabled: false }
external: { url: "nats://nats.nats.svc:4222", existingSecret: slipway-nats }
objectStore:
bundled: { enabled: false }
bucket: slipway
region: eu-west-1
external: { credentials: iam } # IRSA, no static keys
valkey:
bundled: { enabled: false }
external: { url: "rediss://valkey.example.internal:6379" }
ingress:
enabled: true
className: nginx
annotations:
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-buffering: "off"
hosts: [{ host: slipway.example.com, paths: [{ path: /, pathType: Prefix }] }]
tls: [{ secretName: slipway-tls, hosts: [slipway.example.com] }]
networkPolicy:
enabled: true
egress: { restrict: true, external: [{ cidr: 10.0.0.0/16, ports: [5432, 6379, 4222] }] }
metrics:
serviceMonitor: { enabled: true }

Create the credentials Secret first (GitOps tools cannot use Helm lookup):

Terminal window
kubectl -n slipway create secret generic slipway-credentials \
--from-literal=session-secret="$(openssl rand -hex 32)" \
--from-literal=master-key="$(openssl rand -hex 16)"
Value Default Meaning
config.baseUrl http://localhost:8080 Public URL (OIDC redirects, webhooks, issuer)
config.logLevel, config.logFormat info, json Logging
config.extra {} Extra non-secret SLIPWAY_* settings
image.repository, image.tag ghcr.io/slipway-systems/slipway, chart appVersion Control-plane image
server.replicaCount / scheduler.replicaCount / worker.replicaCount 2 Replicas
*.autoscaling.* off HPA settings
*.pdb on, maxUnavailable: 1 PodDisruptionBudgets
*.antiAffinity soft soft, hard or none
migration.enabled true Hook Job running migrate up before upgrades
postgresql.bundled.enabled and siblings true Evaluation-only dependencies
postgresql.external.*, nats.external.*, objectStore.external.*, valkey.external.* Managed service connections
ingress.* off Ingress, class, hosts, TLS
networkPolicy.enabled, networkPolicy.egress.restrict off Isolation
metrics.serviceMonitor.enabled off Prometheus Operator integration
runner.* off Runner workload. See Runners on Kubernetes

Every value is documented in the chart’s values.yaml and type-checked by values.schema.json, so typos fail at install time.

  • Non-root, read-only root filesystem, all capabilities dropped, RuntimeDefault seccomp on every control-plane pod.
  • Migrations run once per release as a Helm hook (post-install and pre-upgrade), so replicas never race.
  • Rolling updates with maxUnavailable: 0 and a 60-second grace period so live log streams drain.
  • Health: /healthz and /readyz on each component; helm test hits them through the Service.
Terminal window
helm test slipway -n slipway
kubectl -n slipway get pods
kubectl -n slipway logs deploy/slipway-server | head
Terminal window
helm uninstall slipway -n slipway

Secrets marked keep and PVCs are not deleted. Remove them deliberately when you are certain you no longer need the data.