diff --git a/helm/README.md b/helm/README.md new file mode 100644 index 0000000..155a289 --- /dev/null +++ b/helm/README.md @@ -0,0 +1,108 @@ +# Helm charts + +Two example charts for deploying [zddc-server](../zddc/) on Kubernetes. +Both compile zddc-server from source via an init container — no +container image needs to be pulled from a registry, and no binary needs +to be built ahead of time. The init container clones the repo at a +configured git ref and runs `go build`; the main container is plain +alpine + the freshly built static binary. + +## Charts + +| Chart | When to use | +|---|---| +| **`zddc-server-prod/`** | Production. Pin `zddc.gitRef` to a stable tag (`zddc-server-vX.Y.Z`). Slower probe cadence; image-pull policy `IfNotPresent`. | +| **`zddc-server-dev/`** | Development / soak. Tracks `main` by default; `helm upgrade` triggers a pod recreate so each rollout pulls the latest commit. Faster probes; debug-level logging (request headers logged — sensitive). | + +The chart values are nearly identical between the two; the differences +are encoded as defaults in each chart's `values.yaml.example`. + +## Quick start + +```sh +# Pre-requisite: a PersistentVolumeClaim for ZDDC_ROOT data +kubectl apply -f - <<'EOF' +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: zddc-root +spec: + accessModes: [ReadWriteMany] # or RWO if single replica is fine + resources: { requests: { storage: 100Gi } } + storageClassName: your-shared-fs # NFS, CephFS, SMB, etc. +EOF + +# Production install +cp helm/zddc-server-prod/values.yaml.example my-prod-values.yaml +$EDITOR my-prod-values.yaml # set zddc.gitRef, hostnames, etc. +helm install zddc-server-prod helm/zddc-server-prod/ -f my-prod-values.yaml + +# Dev install (tracks main HEAD) +cp helm/zddc-server-dev/values.yaml.example my-dev-values.yaml +$EDITOR my-dev-values.yaml +helm install zddc-server-dev helm/zddc-server-dev/ -f my-dev-values.yaml + +# Trigger a rebuild from latest main HEAD (dev chart) +helm upgrade zddc-server-dev helm/zddc-server-dev/ -f my-dev-values.yaml +``` + +## What the chart does and doesn't do + +**Does:** + +- Clones the configured `zddc.gitRepo` at `zddc.gitRef` in an init + container, builds the Go binary, copies it to a shared `emptyDir`, + and starts the main container against that binary. +- Wires the `ZDDC_*` environment-variable contract (root path, addr, + email header, CORS allowlist, log level, index path). +- Mounts a caller-supplied PersistentVolumeClaim at `ZDDC_ROOT`. +- Optionally creates an Ingress (`ingress.enabled: true`). + +**Does not:** + +- Create the PVC. Operators provision storage themselves; the chart + only references it by name. +- Manage TLS for the pod. zddc-server runs in plain HTTP mode behind + whatever ingress / authenticating reverse proxy the cluster already + has. `ZDDC_TLS_CERT=none` and `ZDDC_INSECURE_DIRECT=1` are hardcoded + in the templates because the chart is opinionated about the + TLS-terminated-upstream deployment shape. +- Authenticate users. zddc-server reads the user's email from a header + set by the upstream proxy (`X-Auth-Request-Email` by default). The + chart does not deploy oauth2-proxy / nginx-auth-request / Pomerium / + etc. — bring your own. +- Manage secrets. `values.yaml.example` contains no secrets and never + should. ACL email lists belong in `.zddc` files inside the data + volume; image-pull credentials and TLS certs (if you enable ingress + TLS) reference Kubernetes secrets you've created separately. + +## Why build from source instead of using a registry image + +Three reasons: + +1. **Reproducibility.** The init container's logs show exactly which + git ref was built. There's no opaque "what did I deploy" question + that a registry tag can introduce. +2. **One distribution channel.** Codeberg release-asset binaries + already exist for direct downloads; the chart compiles its own + binary from the same source git ref so there's nothing extra to + maintain (no separate image registry, no image-promotion pipeline). +3. **Smaller blast radius.** A compromised build image affects only + pods that pull during the compromise window. A compromised registry + image stays compromised across rollbacks until the digest is rotated. + +The cost: every pod start takes 30-60s to clone + `go build` instead +of pulling a pre-baked image. Acceptable for both chart audiences +(production rollouts are infrequent; dev rollouts trade build time +for tracking-main convenience). + +## Linting + +```sh +helm lint helm/zddc-server-prod/ +helm lint helm/zddc-server-dev/ + +# Render to inspect (uses default values from values.yaml.example): +helm template test-prod helm/zddc-server-prod/ \ + --values helm/zddc-server-prod/values.yaml.example +``` diff --git a/helm/zddc-server-dev/Chart.yaml b/helm/zddc-server-dev/Chart.yaml new file mode 100644 index 0000000..c758455 --- /dev/null +++ b/helm/zddc-server-dev/Chart.yaml @@ -0,0 +1,20 @@ +apiVersion: v2 +name: zddc-server-dev +description: | + Development deployment of zddc-server. Same shape as zddc-server-prod + but tracks main HEAD (rebuilt on every pod restart), runs at debug + log level, has faster probe cadence for quick feedback, and uses + smaller resource limits. Intended for ephemeral / soak / preview + environments — not for production traffic. +type: application +version: 0.1.0 +appVersion: "main" +home: https://zddc.varasys.io/ +sources: + - https://codeberg.org/VARASYS/ZDDC +maintainers: + - name: VARASYS +keywords: + - zddc + - file-server + - development diff --git a/helm/zddc-server-dev/templates/_helpers.tpl b/helm/zddc-server-dev/templates/_helpers.tpl new file mode 100644 index 0000000..8512572 --- /dev/null +++ b/helm/zddc-server-dev/templates/_helpers.tpl @@ -0,0 +1,31 @@ +{{/* +Common labels and the fullname helper. Stays minimal; chart consumers +who want richer labels can override via metadata.labels in their +values.yaml or post-render kustomize. +*/}} + +{{- define "zddc-server.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "zddc-server.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{- define "zddc-server.labels" -}} +app.kubernetes.io/name: {{ include "zddc-server.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/version: {{ .Values.zddc.gitRef | quote }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" }} +{{- end -}} + +{{- define "zddc-server.selectorLabels" -}} +app.kubernetes.io/name: {{ include "zddc-server.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} diff --git a/helm/zddc-server-dev/templates/deployment.yaml b/helm/zddc-server-dev/templates/deployment.yaml new file mode 100644 index 0000000..ab200b4 --- /dev/null +++ b/helm/zddc-server-dev/templates/deployment.yaml @@ -0,0 +1,120 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "zddc-server.fullname" . }} + labels: + {{- include "zddc-server.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + # Dev: always re-pull the build image and re-clone source, so a kubectl + # rollout restart picks up new commits on the tracked ref. + strategy: + type: Recreate + selector: + matchLabels: + {{- include "zddc-server.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "zddc-server.selectorLabels" . | nindent 8 }} + annotations: + # Forces pod recreation on every helm upgrade, ensuring the init + # container re-clones the tracked ref. Useful in dev where you + # want `helm upgrade` to pick up new main HEAD without changing + # values. + zddc.varasys.io/build-time: {{ now | quote }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: zddc-bin + emptyDir: {} + - name: data + persistentVolumeClaim: + claimName: {{ .Values.data.pvcName }} + initContainers: + - name: build-zddc-server + image: {{ printf "%s:%s" .Values.buildImage.repository .Values.buildImage.tag | quote }} + imagePullPolicy: Always + command: ["/bin/sh", "-c"] + args: + - | + set -eu + apk add --no-cache git + git clone --depth 1 --branch "$GIT_REF" "$GIT_REPO" /workspace + cd /workspace/zddc + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \ + go build -trimpath \ + -ldflags="-s -w -X main.version=$GIT_REF" \ + -o /out/zddc-server \ + ./cmd/zddc-server + echo "built /out/zddc-server from $GIT_REF ($(git -C /workspace rev-parse --short HEAD))" + env: + - name: GIT_REPO + value: {{ .Values.zddc.gitRepo | quote }} + - name: GIT_REF + value: {{ .Values.zddc.gitRef | quote }} + volumeMounts: + - name: zddc-bin + mountPath: /out + resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 1000m + memory: 512Mi + containers: + - name: zddc-server + image: {{ printf "%s:%s" .Values.runtimeImage.repository .Values.runtimeImage.tag | quote }} + imagePullPolicy: IfNotPresent + command: ["/zddc/zddc-server"] + ports: + - name: http + containerPort: 8080 + protocol: TCP + env: + - name: ZDDC_ROOT + value: {{ .Values.zddc.env.rootPath | quote }} + - name: ZDDC_ADDR + value: {{ .Values.zddc.env.addr | quote }} + - name: ZDDC_TLS_CERT + value: "none" + - name: ZDDC_INSECURE_DIRECT + value: "1" + - name: ZDDC_EMAIL_HEADER + value: {{ .Values.zddc.env.emailHeader | quote }} + - name: ZDDC_CORS_ORIGIN + value: {{ .Values.zddc.env.corsOrigin | quote }} + - name: ZDDC_LOG_LEVEL + value: {{ .Values.zddc.env.logLevel | quote }} + - name: ZDDC_INDEX_PATH + value: {{ .Values.zddc.env.indexPath | quote }} + volumeMounts: + - name: zddc-bin + mountPath: /zddc + - name: data + mountPath: {{ .Values.zddc.env.rootPath }} + {{- with .Values.data.subPath }} + subPath: {{ . | quote }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + # Tighter probe cadence than prod — fail fast in dev so issues + # surface immediately during testing. + livenessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: 3 + periodSeconds: 10 + timeoutSeconds: 3 + readinessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: 1 + periodSeconds: 5 + timeoutSeconds: 2 diff --git a/helm/zddc-server-dev/templates/ingress.yaml b/helm/zddc-server-dev/templates/ingress.yaml new file mode 100644 index 0000000..bcd3d72 --- /dev/null +++ b/helm/zddc-server-dev/templates/ingress.yaml @@ -0,0 +1,29 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "zddc-server.fullname" . }} + labels: + {{- include "zddc-server.labels" . | nindent 4 }} +spec: + {{- with .Values.ingress.className }} + ingressClassName: {{ . }} + {{- end }} + {{- if .Values.ingress.tls.enabled }} + tls: + - hosts: + - {{ .Values.ingress.host }} + secretName: {{ .Values.ingress.tls.secretName }} + {{- end }} + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "zddc-server.fullname" . }} + port: + number: {{ .Values.service.port }} +{{- end }} diff --git a/helm/zddc-server-dev/templates/service.yaml b/helm/zddc-server-dev/templates/service.yaml new file mode 100644 index 0000000..8ded8b6 --- /dev/null +++ b/helm/zddc-server-dev/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "zddc-server.fullname" . }} + labels: + {{- include "zddc-server.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - name: http + port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + selector: + {{- include "zddc-server.selectorLabels" . | nindent 4 }} diff --git a/helm/zddc-server-dev/values.yaml.example b/helm/zddc-server-dev/values.yaml.example new file mode 100644 index 0000000..cfe651e --- /dev/null +++ b/helm/zddc-server-dev/values.yaml.example @@ -0,0 +1,66 @@ +# values.yaml.example — zddc-server-dev +# +# Copy to values.yaml (or pass via --values) and customize for your +# environment. Same as the prod chart's example, but defaults are +# tuned for active development: +# +# - gitRef defaults to "main" (rebuilt on every pod restart) +# - ZDDC_LOG_LEVEL=debug (every request's full header map gets logged +# — this includes auth tokens and cookies; debug builds belong in +# trusted/private namespaces only) +# - Faster liveness/readiness probes +# - Smaller resource limits (single-developer test cluster) +# +# Contains NO secrets — see helm/zddc-server-prod/values.yaml.example +# for the secrets-management note. + +zddc: + gitRepo: https://codeberg.org/VARASYS/ZDDC.git + gitRef: main # tracks the latest commit; rebuilt on pod restart + + env: + rootPath: /srv + addr: ":8080" + emailHeader: X-Auth-Request-Email + corsOrigin: "https://zddc.varasys.io,http://localhost:8000" + logLevel: debug # full request headers logged; sensitive! + indexPath: ".archive" + +data: + pvcName: zddc-root-dev # name of an existing PVC in your dev namespace + subPath: "" + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + host: zddc-dev.example.com + tls: + enabled: false + secretName: zddc-dev-tls + +# Smaller than prod — dev clusters are usually resource-constrained. +resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 250m + memory: 256Mi + +# Dev runs single-replica. The init container always pulls main HEAD, +# so two replicas would race on different SHAs. +replicaCount: 1 + +buildImage: + repository: docker.io/golang + tag: 1.24-alpine + +runtimeImage: + repository: docker.io/alpine + tag: "3.19" + +imagePullSecrets: [] diff --git a/helm/zddc-server-prod/Chart.yaml b/helm/zddc-server-prod/Chart.yaml new file mode 100644 index 0000000..028108d --- /dev/null +++ b/helm/zddc-server-prod/Chart.yaml @@ -0,0 +1,20 @@ +apiVersion: v2 +name: zddc-server-prod +description: | + Production deployment of zddc-server. Compiles from source via an + init container at deploy time (no image pull from a registry); the + main container is alpine + the freshly-built binary. TLS is expected + to be terminated upstream (ingress / sidecar / load balancer); the + pod listens on plain HTTP and requires ZDDC_INSECURE_DIRECT=1. +type: application +version: 0.1.0 +appVersion: "0.0.7" # zddc-server git tag this chart was last verified against +home: https://zddc.varasys.io/ +sources: + - https://codeberg.org/VARASYS/ZDDC +maintainers: + - name: VARASYS +keywords: + - zddc + - file-server + - document-control diff --git a/helm/zddc-server-prod/templates/_helpers.tpl b/helm/zddc-server-prod/templates/_helpers.tpl new file mode 100644 index 0000000..8512572 --- /dev/null +++ b/helm/zddc-server-prod/templates/_helpers.tpl @@ -0,0 +1,31 @@ +{{/* +Common labels and the fullname helper. Stays minimal; chart consumers +who want richer labels can override via metadata.labels in their +values.yaml or post-render kustomize. +*/}} + +{{- define "zddc-server.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "zddc-server.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} + +{{- define "zddc-server.labels" -}} +app.kubernetes.io/name: {{ include "zddc-server.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/version: {{ .Values.zddc.gitRef | quote }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" }} +{{- end -}} + +{{- define "zddc-server.selectorLabels" -}} +app.kubernetes.io/name: {{ include "zddc-server.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} diff --git a/helm/zddc-server-prod/templates/deployment.yaml b/helm/zddc-server-prod/templates/deployment.yaml new file mode 100644 index 0000000..6872432 --- /dev/null +++ b/helm/zddc-server-prod/templates/deployment.yaml @@ -0,0 +1,112 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "zddc-server.fullname" . }} + labels: + {{- include "zddc-server.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "zddc-server.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "zddc-server.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: zddc-bin + emptyDir: {} + - name: data + persistentVolumeClaim: + claimName: {{ .Values.data.pvcName }} + initContainers: + # Build zddc-server from the pinned git ref. The static binary + # lands in the shared zddc-bin volume that the main container + # mounts. No image pull from a custom registry — the build + # image is golang upstream + the runtime image is alpine. + - name: build-zddc-server + image: {{ printf "%s:%s" .Values.buildImage.repository .Values.buildImage.tag | quote }} + imagePullPolicy: IfNotPresent + command: ["/bin/sh", "-c"] + args: + - | + set -eu + apk add --no-cache git + git clone --depth 1 --branch "$GIT_REF" "$GIT_REPO" /workspace + cd /workspace/zddc + CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \ + go build -trimpath \ + -ldflags="-s -w -X main.version=$GIT_REF" \ + -o /out/zddc-server \ + ./cmd/zddc-server + echo "built /out/zddc-server from $GIT_REF" + env: + - name: GIT_REPO + value: {{ .Values.zddc.gitRepo | quote }} + - name: GIT_REF + value: {{ .Values.zddc.gitRef | quote }} + volumeMounts: + - name: zddc-bin + mountPath: /out + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + cpu: 1000m + memory: 512Mi + containers: + - name: zddc-server + image: {{ printf "%s:%s" .Values.runtimeImage.repository .Values.runtimeImage.tag | quote }} + imagePullPolicy: IfNotPresent + command: ["/zddc/zddc-server"] + ports: + - name: http + containerPort: 8080 + protocol: TCP + env: + - name: ZDDC_ROOT + value: {{ .Values.zddc.env.rootPath | quote }} + - name: ZDDC_ADDR + value: {{ .Values.zddc.env.addr | quote }} + - name: ZDDC_TLS_CERT + value: "none" + - name: ZDDC_INSECURE_DIRECT + value: "1" + - name: ZDDC_EMAIL_HEADER + value: {{ .Values.zddc.env.emailHeader | quote }} + - name: ZDDC_CORS_ORIGIN + value: {{ .Values.zddc.env.corsOrigin | quote }} + - name: ZDDC_LOG_LEVEL + value: {{ .Values.zddc.env.logLevel | quote }} + - name: ZDDC_INDEX_PATH + value: {{ .Values.zddc.env.indexPath | quote }} + volumeMounts: + - name: zddc-bin + mountPath: /zddc + - name: data + mountPath: {{ .Values.zddc.env.rootPath }} + {{- with .Values.data.subPath }} + subPath: {{ . | quote }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + livenessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: 5 + periodSeconds: 30 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: 2 + periodSeconds: 10 + timeoutSeconds: 3 diff --git a/helm/zddc-server-prod/templates/ingress.yaml b/helm/zddc-server-prod/templates/ingress.yaml new file mode 100644 index 0000000..bcd3d72 --- /dev/null +++ b/helm/zddc-server-prod/templates/ingress.yaml @@ -0,0 +1,29 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "zddc-server.fullname" . }} + labels: + {{- include "zddc-server.labels" . | nindent 4 }} +spec: + {{- with .Values.ingress.className }} + ingressClassName: {{ . }} + {{- end }} + {{- if .Values.ingress.tls.enabled }} + tls: + - hosts: + - {{ .Values.ingress.host }} + secretName: {{ .Values.ingress.tls.secretName }} + {{- end }} + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "zddc-server.fullname" . }} + port: + number: {{ .Values.service.port }} +{{- end }} diff --git a/helm/zddc-server-prod/templates/service.yaml b/helm/zddc-server-prod/templates/service.yaml new file mode 100644 index 0000000..8ded8b6 --- /dev/null +++ b/helm/zddc-server-prod/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "zddc-server.fullname" . }} + labels: + {{- include "zddc-server.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - name: http + port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + selector: + {{- include "zddc-server.selectorLabels" . | nindent 4 }} diff --git a/helm/zddc-server-prod/values.yaml.example b/helm/zddc-server-prod/values.yaml.example new file mode 100644 index 0000000..af38f81 --- /dev/null +++ b/helm/zddc-server-prod/values.yaml.example @@ -0,0 +1,100 @@ +# values.yaml.example — zddc-server-prod +# +# Copy to values.yaml (or pass via --values) and customize for your +# environment. Contains NO secrets — secrets like the .zddc admin email +# list, TLS certs (if used), and image-pull credentials must be +# materialised from your secret-management system (sealed-secrets, +# external-secrets, kubectl create secret, etc.) and referenced by name +# below. + +# Source-build configuration. The init container clones the repo at +# `gitRef` and compiles cmd/zddc-server. Pin gitRef to a stable tag +# (zddc-server-vX.Y.Z) for production; trying main HEAD risks pulling +# unreleased changes. +zddc: + gitRepo: https://codeberg.org/VARASYS/ZDDC.git + gitRef: zddc-server-v0.0.7 # pin to a stable tag + + # ZDDC environment-variable contract — see zddc/README.md + env: + # Path inside the container where ZDDC_ROOT data is mounted. + # The chart wires the data PVC to this path automatically. + rootPath: /srv + + # Listening address (plain HTTP — ingress terminates TLS). + addr: ":8080" + + # Email-header convention from your authenticating reverse proxy. + emailHeader: X-Auth-Request-Email + + # Comma-separated CORS allowlist. Set to your tools host, or empty + # to disable CORS entirely (when tools are same-origin). + corsOrigin: "https://zddc.varasys.io" + + # info / warn / error / debug. Production stays on info; debug logs + # every request's full header map (includes cookies/auth tokens). + logLevel: info + + # Index URL segment for the virtual archive index. Default fits + # most deployments; only change if you have a tracking-number + # collision with a real directory named ".archive". + indexPath: ".archive" + +# Persistent storage for ZDDC_ROOT. Operators provide their own PVC, +# typically backed by a shared filesystem (NFS, CephFS, SMB) so multiple +# replicas of zddc-server (and your sync tooling) see the same tree. +# This chart does NOT create the PVC — it only references it by name. +data: + pvcName: zddc-root # name of an existing PersistentVolumeClaim + subPath: "" # optional subPath within the PVC + +# Service exposure. zddc-server listens on a plain HTTP port; ingress +# (or whatever reverse proxy you put in front) terminates TLS and +# enforces authentication, then forwards to this service. +service: + type: ClusterIP + port: 8080 + +# Ingress is optional — disabled by default since most deployments wire +# zddc-server into an existing ingress / auth-proxy stack. Enable here +# only if this chart is the only thing in front of the pod. +ingress: + enabled: false + className: "" + host: zddc.example.com + tls: + enabled: false + secretName: zddc-tls # secret you create separately + +# Pod resource limits. Sized for a small/medium archive (~10k files). +resources: + requests: + cpu: 100m + memory: 128Mi + limits: + cpu: 500m + memory: 512Mi + +# Replicas. zddc-server is read-only stateless given a shared filesystem +# behind it, so multiple replicas are safe. +replicaCount: 1 + +# Build-stage Go image (init container). Pinned digest is recommended +# in production for reproducibility; using a tag means upstream changes +# break your deploy. +buildImage: + repository: docker.io/golang + tag: 1.24-alpine + # digest: sha256:... + +# Runtime image (main container). Must contain a basic shell + libc; +# the static binary is copied in by the init container. Alpine is fine. +runtimeImage: + repository: docker.io/alpine + tag: "3.19" + # digest: sha256:... + +# Image pull credentials, if your registry requires them. Reference a +# secret you've created separately; do not put credentials in values. +imagePullSecrets: [] +# - name: regcred