helm: add zddc-server-cache example chart + ZDDC_NO_AUTH on prod/dev

New chart helm/zddc-server-cache/ deploys zddc-server in client mode
against an upstream master. Mirrors the prod chart's source-build-via-
init-container pattern but with:

- ZDDC_UPSTREAM, ZDDC_MODE, ZDDC_BEARER_FILE, ZDDC_NO_AUTH,
  ZDDC_SKIP_TLS_VERIFY, ZDDC_MIRROR_SUBTREE, ZDDC_MIRROR_MIN_INTERVAL
  wired from values.yaml. Mirror-only env vars conditionally rendered
  (only when mode=mirror) to keep the rendered manifest minimal.
- Bearer token mounted from a separately-created Kubernetes Secret
  (defaultMode 0400) at /etc/zddc/bearer/token. values.yaml.example
  documents the secret-creation flow but contains no token. Secret
  reference can be set to "" to disable bearer auth (only valid for
  upstreams running --no-auth).
- Recreate strategy + replicaCount: 1 (multiple replicas would race
  the cache directory and double the upstream walker traffic).
- TCP-socket probes instead of HTTP — HTTP probes against / would
  fail when both upstream is unreachable AND the cache is empty
  (the cache layer returns 503 + offline header in that state),
  causing crashloops. TCP verifies process liveness without depending
  on upstream reachability or cache contents.
- Mounts a separate cache PVC (operator-provided, like the master's
  data PVC). Sized to the working set you expect to mirror; can be
  much smaller than the master's data volume.

Existing prod and dev charts gain optional ZDDC_NO_AUTH wired from
zddc.env.noAuth (default false → no change to existing rendered
manifests). Useful for trusted-LAN or genuinely-public master
deployments.

Updated docs: helm/README.md gains the cache row in the chart table,
the cache-install quickstart with the secret-creation flow, and the
cache-specific structural notes (Recreate / TCP probes / single-
instance). CLAUDE.md and ARCHITECTURE.md updated to reflect three
charts instead of two.

Verified with helm template rendering: ZDDC_NO_AUTH only renders
when noAuth: true; ZDDC_MIRROR_SUBTREE / ZDDC_MIRROR_MIN_INTERVAL
only render when mode: mirror; bearer volume + ZDDC_BEARER_FILE
only render when bearer.secretName is non-empty.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZDDC 2026-05-08 08:33:01 -05:00
parent 8a049ca2a4
commit 55852a9efb
13 changed files with 498 additions and 7 deletions

View file

@ -66,7 +66,7 @@ Website files (what `zddc.varasys.io` serves) live on a **separate Codeberg repo
Every URL under `/releases/` resolves directly via the symlink chain — no `manifest.json`, no Caddy regex-rewrite, no JavaScript indirection, no third-party mirror. Caddy serves these as plain static files. The Docker-tag pattern: `:1.2.3` is pinned, `:1.2` floats, `:1` floats further, `:stable` floats furthest, and `:beta` / `:alpha` are mutable channel mirrors that overwrite in place.
**zddc-server binaries are reproducible from a tag, not in git** — `./build alpha|beta|release` cross-compiles them into `dist/release-output/`, `./deploy` rsyncs them to `/srv/zddc/releases/`, Caddy serves from there. Older versions: `git checkout zddc-server-v0.0.8 && ./build release 0.0.8`. The `helm/zddc-server-{prod,dev}/` charts build from source via init container, but operators who want a prebuilt binary just `curl -O https://zddc.varasys.io/releases/zddc-server_stable_linux-amd64`. The single cell link per release points at `zddc-server_<X>.html`, a small generated stub that surfaces all four platform downloads.
**zddc-server binaries are reproducible from a tag, not in git** — `./build alpha|beta|release` cross-compiles them into `dist/release-output/`, `./deploy` rsyncs them to `/srv/zddc/releases/`, Caddy serves from there. Older versions: `git checkout zddc-server-v0.0.8 && ./build release 0.0.8`. The `helm/zddc-server-{prod,dev,cache}/` charts build from source via init container, but operators who want a prebuilt binary just `curl -O https://zddc.varasys.io/releases/zddc-server_stable_linux-amd64`. The single cell link per release points at `zddc-server_<X>.html`, a small generated stub that surfaces all four platform downloads.
To preview a build locally, open `dist/tool.html` directly via the dev server. To publish on `zddc.varasys.io`, cut a release with `./build alpha|beta|release` and then `./deploy`.

View file

@ -25,7 +25,7 @@ This is a **monorepo of independent tools**, not one application:
- `zddc/` — Go HTTP server (separate sub-project; Go 1.24+). Two deployment shapes from the same binary: (1) **master** — owns a file tree under `ZDDC_ROOT`, applies `.zddc` ACL cascades, serves files / app HTML / archive listings. Two auth paths on master: `Authorization: Bearer <token>` validated against self-issued tokens at `<ZDDC_ROOT>/.zddc.d/tokens/<sha256-hex>` for CLI/scripted callers, or `X-Auth-Request-Email` injected by an upstream proxy for browser sessions. Self-service token UI at `/.tokens` + JSON API at `/.api/tokens`. (2) **client** — when `--upstream <url>` is set, the binary becomes a downstream proxy/cache/mirror (`zddc/internal/cache/`); master-side machinery is bypassed and `--root` becomes the cache directory. Three sub-modes via `--mode proxy|cache|mirror` (mirror is phase 3). Cache layout is a normal ZDDC root, so the cache dir can be served as a plain master if you unset `--upstream`. Marker file `.zddc-upstream` records provenance. `--no-auth` skips ACL enforcement entirely on this instance (distinct from `--insecure` which only relaxes the no-root-`.zddc` startup check); `--skip-tls-verify` is a separate flag for self-signed upstream certs. Cross-compiled binaries are produced by `./build` and live in `dist/release-output/` (gitignored); `./deploy` rsyncs them to `/srv/zddc/releases/` on the deploy host (Caddy serves them at `https://zddc.varasys.io/releases/`). The `helm/` charts in this repo build from source at deploy time.
- `shared/``base.css` plus shared JS modules (`zddc.js`, `hash.js`, `zddc-filter.js`, `theme.js`, `help.js`) included by every tool's build, and `build-lib.sh` (POSIX sh helpers sourced by every tool's `build.sh` AND by the top-level `build` for lockstep release helpers).
- **Two-repo + deploy-host model.** Source code lives here (`codeberg.org/VARASYS/ZDDC`). Hand-edited website content lives in a separate repo (`codeberg.org/VARASYS/ZDDC-website`, typically cloned at `~/src/zddc-website/` — just `index.html`, `reference.html`, `css/`, `js/`, `img/`; no releases, no LFS). The live site at `zddc.varasys.io` is served from `/srv/zddc/` on the deploy host: Caddy bind-mounts that path, and it's populated by `./deploy` from this repo's `dist/release-output/` plus `~/src/zddc-website/`. **Releases are NOT in any git history** — they're reproducible from this repo's `<tool>-vX.Y.Z` tags by checking out the tag and running `./build release X.Y.Z`. Per-version files (`<tool>_v<X.Y.Z>.html`) are immutable; partial-version pins (`<tool>_v<X.Y>.html`, `<tool>_v<X>.html`) and channel mirrors (`<tool>_{stable,beta,alpha}.html`) are symlinks; zddc-server has analogous `zddc-server_v<X.Y.Z>_<platform>` per-version binaries plus channel/partial-version symlinks plus `zddc-server_<X>.html` stub pages that fan out the four-platform download in one cell. **Install model:** local use is a download from `/releases/`. Server use is `zddc-server`, which has the current-stable build of all six tools baked in via `//go:embed` (compile-time default). Tools auto-served at folder-name-driven paths: `archive` everywhere, `classifier` in `Incoming`/`Working`/`Staging` subtrees, `mdedit` in `Working` subtrees, `transmittal` in `Staging` subtrees, `landing` only at root. Override via `.zddc apps:` cascade entry (channel/version/URL/path) — fetched once, cached at `<ZDDC_ROOT>/_app/`. Drop a real `.html` file at any path to override.
- `helm/` — example Helm charts for zddc-server (`zddc-server-prod/`, `zddc-server-dev/`). Both compile from source via init container. Operators copy `values.yaml.example` and customize. No secrets in repo.
- `helm/` — example Helm charts for zddc-server. Three flavors: `zddc-server-prod/` (production master), `zddc-server-dev/` (development master with OverlayFS isolation), `zddc-server-cache/` (downstream client running in proxy/cache/mirror mode against an upstream master, with bearer token from a Kubernetes Secret). All compile from source via init container. Operators copy `values.yaml.example` and customize. No secrets in repo — the cache chart references a separately-created Secret for the bearer token.
- `tests/` — Playwright specs (Chromium only, requires File System Access API). `tests/schema.spec.js` validates `transmittal.schema.json` against canonical fixtures via `ajv` (only dev dep besides Playwright)
## Most-used commands

View file

@ -1,7 +1,7 @@
# Helm charts
Two example charts for deploying [zddc-server](../zddc/) on Kubernetes.
Both compile zddc-server from source via an init container — no
Three example charts for deploying [zddc-server](../zddc/) on Kubernetes.
All 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
@ -11,16 +11,24 @@ alpine + the freshly built static binary.
| 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`. Mounts the data PVC directly RW at `ZDDC_ROOT`. |
| **`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). Wraps the data PVC in **OverlayFS** (lower = PVC mounted RO, upper = ephemeral `emptyDir`) so dev-side writes never mutate the underlying store. Use this shape when the dev replica points at the same data as prod. |
| **`zddc-server-prod/`** | Production **master**. Pin `zddc.gitRef` to a stable tag (`zddc-server-vX.Y.Z`). Slower probe cadence; image-pull policy `IfNotPresent`. Mounts the data PVC directly RW at `ZDDC_ROOT`. The token system is enabled automatically (tokens persist on the data PVC at `<ZDDC_ROOT>/.zddc.d/tokens/`); operators visit `/.tokens` to issue them. |
| **`zddc-server-dev/`** | Development / soak **master**. 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). Wraps the data PVC in **OverlayFS** (lower = PVC mounted RO, upper = ephemeral `emptyDir`) so dev-side writes never mutate the underlying store. Use this shape when the dev replica points at the same data as prod. |
| **`zddc-server-cache/`** | Downstream **client** (proxy / cache / mirror) of an upstream master. Set `zddc.upstream.url` + `zddc.upstream.mode`; the binary skips master-side machinery and forwards all requests to the master, persisting responses under the cache PVC (in cache or mirror modes). Bearer auth via a separately-created Kubernetes Secret. Use cases: corporate-master → DR-mirror, vendor-scoped mirror in a vendor's own cluster, regional edge cache, dev environment that mirrors prod read-only. Mirror mode adds an access-triggered subtree walker. |
The chart values are nearly identical between the two; the differences
The prod and dev chart values are nearly identical; the differences
are encoded as defaults in each chart's `values.yaml.example`. The
dev chart's overlay-isolation layer is a structural difference, not a
values-level toggle — see `zddc-server-dev/templates/deployment.yaml`
for the privileged init container and the `data-readonly` /
`overlay-scratch` / `data` volume sandwich.
The cache chart shares the same source-build pattern but adds
client-mode env wiring (`ZDDC_UPSTREAM`, `ZDDC_MODE`, `ZDDC_BEARER_FILE`,
`ZDDC_NO_AUTH`, `ZDDC_SKIP_TLS_VERIFY`, mirror-mode subtree config),
a Recreate strategy (single-instance — multiple replicas would race
the cache directory), and TCP-socket probes (HTTP probes against `/`
would fail when both upstream is down AND the cache is empty).
## Quick start
```sh
@ -48,6 +56,30 @@ 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
# Cache install (downstream client of an upstream master)
#
# 1) Issue a bearer token on the master at https://<master>/.tokens
# 2) Create the Secret (do NOT put the token in values.yaml):
kubectl create secret generic zddc-cache-bearer \
--from-literal=token=<paste-token-here>
# 3) Create a cache PVC (separate from the master's data PVC; can
# be smaller — sized to the working set you expect to mirror):
kubectl apply -f - <<'PVC'
apiVersion: v1
kind: PersistentVolumeClaim
metadata: { name: zddc-cache }
spec:
accessModes: [ReadWriteOnce]
resources: { requests: { storage: 50Gi } }
storageClassName: your-block-storage
PVC
# 4) Install the chart, pointing at your master:
cp helm/zddc-server-cache/values.yaml.example my-cache-values.yaml
$EDITOR my-cache-values.yaml # set zddc.upstream.url, mode, etc.
helm install zddc-server-cache helm/zddc-server-cache/ -f my-cache-values.yaml
```
## What the chart does and doesn't do
@ -107,8 +139,12 @@ for tracking-main convenience).
```sh
helm lint helm/zddc-server-prod/
helm lint helm/zddc-server-dev/
helm lint helm/zddc-server-cache/
# 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
helm template test-cache helm/zddc-server-cache/ \
--values helm/zddc-server-cache/values.yaml.example
```

View file

@ -0,0 +1,32 @@
apiVersion: v2
name: zddc-server-cache
description: |
Downstream cache / mirror 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.
Runs in client mode against an upstream zddc-server master, caching
every accessed file (and, in mirror mode, proactively walking
configured subtrees).
Use cases: corporate-master → DR-mirror, vendor-scoped mirror in a
vendor's own cluster, regional edge cache, dev/staging environment
that mirrors prod. Distinct from `zddc-server-prod` (which IS a
master) and `zddc-server-dev` (a master with overlay isolation).
TLS upstream is verified by default (set --skip-tls-verify only for
self-signed dev masters or internal CAs you haven't yet added to
the trust store).
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
- cache
- mirror
- file-server
- document-control

View file

@ -0,0 +1,33 @@
{{/*
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/component: cache
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 }}
app.kubernetes.io/component: cache
{{- end -}}

View file

@ -0,0 +1,162 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "zddc-server.fullname" . }}
labels:
{{- include "zddc-server.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
# Cache writes serialize through the local filesystem; running two
# replicas would race the cache directory + double the upstream
# walker traffic. Recreate strategy ensures only one pod holds the
# cache PVC at a time.
strategy:
type: Recreate
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 }}
{{- if .Values.bearer.secretName }}
- name: bearer
secret:
secretName: {{ .Values.bearer.secretName | quote }}
defaultMode: 0400
items:
- key: {{ .Values.bearer.secretKey | quote }}
path: token
{{- end }}
initContainers:
# Build zddc-server from the pinned git ref. Same flow as the
# master charts — the binary is the same; client mode is
# selected at runtime via ZDDC_UPSTREAM.
- 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 }}
{{- if .Values.zddc.env.noAuth }}
- name: ZDDC_NO_AUTH
value: "1"
{{- end }}
# Client-mode flags. ZDDC_UPSTREAM activates client mode
# in cmd/zddc-server/main.go's runClient short-circuit.
- name: ZDDC_UPSTREAM
value: {{ .Values.zddc.upstream.url | quote }}
- name: ZDDC_MODE
value: {{ .Values.zddc.upstream.mode | quote }}
{{- if .Values.zddc.upstream.skipTLSVerify }}
- name: ZDDC_SKIP_TLS_VERIFY
value: "1"
{{- end }}
{{- if .Values.bearer.secretName }}
- name: ZDDC_BEARER_FILE
value: "/etc/zddc/bearer/token"
{{- end }}
{{- if eq .Values.zddc.upstream.mode "mirror" }}
{{- with .Values.zddc.upstream.mirrorSubtree }}
- name: ZDDC_MIRROR_SUBTREE
value: {{ . | quote }}
{{- end }}
{{- with .Values.zddc.upstream.mirrorMinInterval }}
- name: ZDDC_MIRROR_MIN_INTERVAL
value: {{ . | quote }}
{{- end }}
{{- end }}
volumeMounts:
- name: zddc-bin
mountPath: /zddc
- name: data
mountPath: {{ .Values.zddc.env.rootPath }}
{{- with .Values.data.subPath }}
subPath: {{ . | quote }}
{{- end }}
{{- if .Values.bearer.secretName }}
- name: bearer
mountPath: /etc/zddc/bearer
readOnly: true
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
# TCP-socket probes only — HTTP probes against `/` would
# fail when both upstream is unreachable AND the cache is
# empty (the cache layer returns 503 in that state). TCP
# probes verify the server process is alive without
# depending on upstream reachability or cache contents.
livenessProbe:
tcpSocket:
port: http
initialDelaySeconds: 5
periodSeconds: 30
timeoutSeconds: 5
readinessProbe:
tcpSocket:
port: http
initialDelaySeconds: 2
periodSeconds: 10
timeoutSeconds: 3

View file

@ -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 }}

View file

@ -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 }}

View file

@ -0,0 +1,150 @@
# values.yaml.example — zddc-server-cache
#
# Copy to values.yaml (or pass via --values) and customize for your
# environment. Contains NO secrets — the upstream bearer token MUST be
# provided via a separately-created Kubernetes Secret (see `bearer:`
# below). Do not paste the token value here.
# 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 caches; tracking main is fine
# for dev mirrors.
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 "Client mode".
env:
# Local cache directory (mounted from the cache PVC; see `data:`
# below). The cache layer writes files here as they're fetched.
rootPath: /srv
# Listening address for incoming requests to this cache instance.
# Plain HTTP — ingress / mesh terminates TLS upstream of the pod.
addr: ":8080"
# Email-header convention from your authenticating reverse proxy.
# Used for AccessLog only in client mode (auth flows to upstream
# as a bearer; the cache layer doesn't enforce ACL locally when
# noAuth: true).
emailHeader: X-Auth-Request-Email
# CORS allowlist for the local instance. Same semantics as the
# master chart — empty disables CORS, which is the right default
# for embedded-tools / same-origin browsing.
corsOrigin: ""
# info / warn / error / debug.
logLevel: info
indexPath: ".archive"
# Skip ACL enforcement on incoming requests. Almost always true
# for a personal/field-engineer cache (the laptop is single-user-
# trust and the upstream master already filtered). Set to false
# only if you've put your own auth proxy in front of this cache
# AND want it to re-evaluate ACLs against cached `.zddc` files.
noAuth: true
# Upstream master configuration.
upstream:
# The master URL. Required. Don't include a trailing slash.
url: "https://zddc.example.com"
# proxy / cache / mirror.
# proxy — forward live, no disk persistence
# cache — persist responses on access (default; field-engineer use)
# mirror — cache + access-triggered subtree warmer (vendor /
# backup / complete-offline use)
mode: cache
# Accept self-signed / untrusted upstream TLS certs. Distinct from
# noAuth. Use only for dev masters with self-signed certs or for
# internal CAs your cluster's trust store doesn't yet have.
skipTLSVerify: false
# Mirror-mode only. Comma-separated URL subtrees the access-
# triggered walker keeps current. Empty + mode=mirror = full
# mirror ("/"). Ignored when mode != mirror.
mirrorSubtree: ""
# Mirror-mode only. Min gap between walks of the same subtree.
# Idle subtrees generate zero upstream traffic until next access.
# Default 1h.
mirrorMinInterval: 1h
# Bearer token — required when the upstream master enforces auth.
# Create a Secret separately (do NOT paste the token here):
#
# 1. On the master, sign in via your auth proxy and visit
# https://<master>/.tokens to issue a token.
# 2. Wrap it in a Kubernetes Secret:
#
# kubectl create secret generic zddc-cache-bearer \
# --from-literal=token=<paste-token-here>
#
# 3. Reference the Secret here.
#
# Set `secretName: ""` to disable bearer auth (only valid when the
# upstream is `--no-auth` or behind your own auth proxy that doesn't
# require bearer auth from internal callers).
bearer:
secretName: zddc-cache-bearer
secretKey: token
# Cache-storage PVC. Sized for the working set you expect to mirror —
# can be smaller than the master's data volume since only accessed
# files (or, in mirror mode, files under configured subtrees) get
# cached. Operators provision the PVC themselves; this chart only
# references it by name. ReadWriteOnce is fine — the cache is single-
# instance by design.
data:
pvcName: zddc-cache # name of an existing PersistentVolumeClaim
subPath: ""
# Service exposure. The cache listens on a plain HTTP port; ingress
# (or mesh sidecar) terminates TLS and forwards to this service.
service:
type: ClusterIP
port: 8080
# Ingress is optional — disabled by default since most cache
# deployments wire into an existing ingress / auth-proxy stack.
ingress:
enabled: false
className: ""
host: zddc-cache.example.com
tls:
enabled: false
secretName: zddc-cache-tls
# Pod resource limits. Cache instances are mostly I/O bound; the
# defaults below suit a small mirror (~1k files in working set).
# Bump cpu/memory for mirror mode against larger trees.
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
# Replicas. Cache instances are single-instance by design — multiple
# replicas would race on writes to the same cache directory and
# duplicate the upstream walker traffic. Use a separate cache
# deployment per region/tenant if you need fan-out.
replicaCount: 1
# Build-stage Go image (init container).
buildImage:
repository: docker.io/golang
tag: 1.24-alpine
# Runtime image (main container).
runtimeImage:
repository: docker.io/alpine
tag: "3.19"
# Image pull credentials, if your registry requires them.
imagePullSecrets: []
# - name: regcred

View file

@ -147,6 +147,10 @@ spec:
value: {{ .Values.zddc.env.logLevel | quote }}
- name: ZDDC_INDEX_PATH
value: {{ .Values.zddc.env.indexPath | quote }}
{{- if .Values.zddc.env.noAuth }}
- name: ZDDC_NO_AUTH
value: "1"
{{- end }}
volumeMounts:
- name: zddc-bin
mountPath: /zddc

View file

@ -30,6 +30,15 @@ zddc:
logLevel: debug # full request headers logged; sensitive!
indexPath: ".archive"
# Skip ACL enforcement entirely. Useful in trusted-LAN dev clusters
# where authentication isn't needed and you want to iterate without
# configuring an upstream auth proxy. Default false.
noAuth: false
# Token system: enabled automatically — tokens persist at
# <ZDDC_ROOT>/.zddc.d/tokens/ on the data PVC. Sign in via your
# cluster's auth proxy and visit /.tokens to issue one.
data:
pvcName: zddc-root-dev # name of an existing PVC in your dev namespace
subPath: ""

View file

@ -86,6 +86,10 @@ spec:
value: {{ .Values.zddc.env.logLevel | quote }}
- name: ZDDC_INDEX_PATH
value: {{ .Values.zddc.env.indexPath | quote }}
{{- if .Values.zddc.env.noAuth }}
- name: ZDDC_NO_AUTH
value: "1"
{{- end }}
volumeMounts:
- name: zddc-bin
mountPath: /zddc

View file

@ -44,6 +44,23 @@ zddc:
# collision with a real directory named ".archive".
indexPath: ".archive"
# Skip ACL enforcement entirely on this instance. Anyone hitting
# the port reads everything in scope. Only enable for genuinely-
# public archives (and even then, only behind an authenticating
# ingress that doesn't gate on identity for /). Distinct from
# --insecure (which gates the startup check requiring a root .zddc).
# Default false.
noAuth: false
# Bearer-token system. Master automatically self-issues tokens via
# /.tokens (browser) and /.api/tokens (JSON). The token store lives
# at <ZDDC_ROOT>/.zddc.d/tokens/<sha256> on the data PVC; no Helm
# configuration required. Operators sign in via the upstream auth
# proxy, visit /.tokens, copy the displayed token into a 0600 file,
# and pass --bearer-file to any CLI / cache / mirror that needs to
# authenticate against this master. See zddc/README.md "Bearer
# tokens" for the full lifecycle.
# 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.