9 KiB
Go Tell Helm chart
This chart deploys Go Tell as one image: a Go binary that serves the API and
embeds the React frontend, with a persistent volume for the content file. It
publishes a single HTTPS host, https://tell.dev, behind ingress-nginx with a
certificate from cert-manager.
1. What the chart creates
| Resource | Name | Purpose |
|---|---|---|
| Deployment | go-tell |
CMS binary, API and web UI in one container |
| Service | go-tell |
Cluster-internal service, ingress backend |
| Ingress | go-tell |
One rule and one TLS SAN for tell.dev |
| Issuer | go-tell-selfsigned |
cert-manager self-signed issuer |
| Certificate | go-tell-ca |
Chart CA that signs the leaf certificate |
| Certificate | go-tell |
Leaf certificate for tell.dev |
| PersistentVolumeClaim | go-tell |
Content file storage, emptyDir when disabled |
| Secret | go-tell-secrets |
Go Loose client credentials and the proxy token |
There are no tenants and no per-tenant hosts: one release, one host, one content file.
2. Prerequisites
- A Kubernetes cluster reachable through
KUBECONFIG, by default~/.kube/config. - A
StorageClasswhenpersistence.enabledistrue. - ingress-nginx with the
nginxingress class:make ingress-nginx-install. - cert-manager when
ingress.tls.enabledistrue:make cert-manager-install. - Cluster nodes trusting
batty1039.startdedicated.net:5000as an insecure registry, or an HTTPS registry.
Run everything the chart depends on in one step:
make cluster-prepare
3. Deploy
make helm-lint
make helm-deploy-development
The development profile runs the demo profile on NodePort 30010 with
ephemeral content and Go Loose disabled, which is what make frontend talks to.
Production runs the persisted content file with browser sign-in:
export GO_LOOSE_CLIENT_ID=...
export GO_LOOSE_CLIENT_SECRET=...
make helm-deploy-production
Credentials are never written into a values file. They reach the release
secret through --set, or through the GO_LOOSE_CLIENT_ID and
GO_LOOSE_CLIENT_SECRET secrets of the deploy workflow. The chart refuses to
render when goLoose.enabled is true and either of them is missing, because a
release without credentials would have no way to sign anybody in.
After a successful install the release notes list the URL and the command that
exports the CA certificate. With the local platform, prefer
docs/KUBERNETES-DEPLOYMENTS.md in the infrastructure repository, which covers
/etc/hosts entries and CA trust for the whole platform.
4. The single host
host is the only host the release serves:
host: tell.dev
The chart derives, without any extra configuration:
- One ingress rule for that host.
- One certificate SAN for that host, so a single secret covers the release.
GO_LOOSE_APP_DOMAIN, which the API turns into the redirect URIhttps://tell.dev/api/auth/callback.
That redirect URI has to be registered on the Go Loose application together with
the client id and secret. goLoose.tenant names the Go Loose tenant that owns
the login, which decides where the browser is sent first:
https://tell.dev/api/auth/login
-> https://tell.auth.dev/connect/authorize
-> https://tell.dev/api/auth/callback
5. Values
Top level
| Key | Default | Description |
|---|---|---|
nameOverride |
"" |
Overrides the chart name in resource names and labels |
fullnameOverride |
"" |
Replaces the generated resource name prefix |
host |
tell.dev |
Public host of the CMS |
replicaCount |
1 |
CMS replicas, the content file is shared through the volume |
imagePullSecrets |
[] |
Pull secrets added to the pod |
nodeSelector, tolerations, affinity |
empty | Scheduling of the deployment |
image and app
| Key | Default | Description |
|---|---|---|
image.repository |
batty1039.startdedicated.net:5000/go-tell |
CMS image |
image.tag |
latest |
CMS image tag |
image.pullPolicy |
IfNotPresent |
CMS pull policy |
app.profile |
production |
CMS_PROFILE, demo enables the in-memory seed and the sudo terminal |
app.allowedOrigins |
https://tell.dev |
CMS_ALLOWED_ORIGINS |
app.contentFile |
/data/content.json |
CMS_CONTENT_FILE, ignored when persistence is disabled |
app.postgresURL |
"" |
CMS_POSTGRES_URL, reserved for the PostgreSQL adapter |
app.ssoHeader |
X-SSO-Token |
CMS_SSO_HEADER, empty disables the proxy identity |
app.ssoCookie |
"" |
CMS_SSO_COOKIE, cookie carrying the same value |
app.resources |
100m/128Mi to 500m/512Mi |
Requests and limits |
app.podAnnotations, app.podLabels |
{} |
Extra pod metadata |
goLoose
| Key | Default | Description |
|---|---|---|
goLoose.enabled |
true |
Injects the Go Loose environment into the pod |
goLoose.tenant |
tell |
Go Loose tenant that owns the login, one DNS label |
goLoose.authDomain |
auth.dev |
Identity domain shared by every Go Loose tenant |
goLoose.appDomain |
tell.dev |
Public host, which determines the redirect URI |
goLoose.clientID |
"" |
Client id of the Go Loose application, required when enabled |
goLoose.clientSecret |
"" |
Client secret of the Go Loose application, required when enabled |
goLoose.ca.existingSecret |
"" |
Secret holding the CA bundle of an internally signed identity domain |
goLoose.ca.key |
ca.crt |
Key projected from that secret |
goLoose.ca.mountPath |
/certs/local-ca.crt |
GO_LOOSE_CA_FILE target |
secrets.ssoToken |
"" |
Shared secret the proxy header value must match |
The CA bundle is only mounted when goLoose.ca.existingSecret is set. A
publicly signed identity domain therefore needs no extra configuration, while an
internally signed one, such as the local platform, has to publish its
certificate first:
kubectl -n go-tell-production create secret generic local-ca --from-file=ca.crt=certs/local-ca.crt
ingress and certManager
| Key | Default | Description |
|---|---|---|
ingress.enabled |
true |
Creates the ingress |
ingress.className |
nginx |
Ingress class of the controller |
ingress.annotations |
TLS redirect | Controller annotations |
ingress.path |
/ |
Path routed to the service |
ingress.pathType |
Prefix |
Path type of that route |
ingress.tls.enabled |
true |
Terminates TLS on the controller |
ingress.tls.secretName |
"" |
Defaults to <fullname>-tls |
ingress.tls.existingSecret |
"" |
Uses a certificate managed outside the chart |
certManager.enabled |
true |
Chart creates the certificates |
certManager.issuerRef |
{} |
Uses an existing issuer instead of the chart CA |
certManager.duration |
8760h |
Certificate lifetime |
certManager.renewBefore |
720h |
Renewal window |
certManager.caSecretName |
"" |
Defaults to <fullname>-ca |
Four certificate objects are created: a self-signed Issuer, a CA
Certificate stored in caSecretName, an Issuer that serves that CA, and the
leaf Certificate stored in the ingress TLS secret for host. Set
certManager.issuerRef to sign with a cluster issuer instead:
certManager:
issuerRef:
name: internal-acme
kind: ClusterIssuer
group: cert-manager.io
Set ingress.tls.existingSecret to use a certificate the chart does not own,
and certManager.enabled: false to stop emitting cert-manager objects.
Storage and pod security
| Key | Default | Description |
|---|---|---|
persistence.enabled |
true |
Persistent volume for the content file |
persistence.size |
2Gi |
Volume size |
persistence.accessModes |
[ReadWriteOnce] |
Volume access modes |
persistence.storageClass |
"" |
Storage class, the cluster default when empty |
podSecurityContext |
fsGroup: 10001 |
Pod security context, gives the volume to the image user |
securityContext |
non-root 10001, read-only root filesystem |
Container security context |
strategy.type |
Recreate |
The old pod releases the volume before the new one starts |
The image runs as its own go-tell user (uid 10001) and declares no
HOME, so readOnlyRootFilesystem needs the writable /tmp mount the chart
adds.
6. Upgrade and remove
make helm-deploy-production
helm -n go-tell-production history go-tell
helm -n go-tell-production rollback go-tell 1
make helm-down-production
Keep the Go Loose credentials outside the cluster: uninstalling removes the release secret, and Go Loose shows a new secret only once.
7. Verify
kubectl -n go-tell-production get ingress go-tell
kubectl -n go-tell-production get certificate
kubectl -n go-tell-production rollout status deployment/go-tell
curl --resolve tell.dev:443:127.0.0.1 --cacert go-tell-ca.crt https://tell.dev/health
curl -I --cacert go-tell-ca.crt https://tell.dev/api/auth/login
The login request must answer 302 towards
https://tell.auth.dev/connect/authorize; a 404 means the release has no Go
Loose credentials. The test pod installed by helm test checks the health
endpoint from inside the cluster.