8c119efff8
- #3 Liveness probe targets full SSR DB-querying / route, coupling pod liveness to SQLite - #4 Chart values-staging/production.yaml are dead config under Flux; drift trap - #6 tsconfig includes gitignored emdash-env.d.ts that only the dev server generates - #7 Dockerfile package-lock glob + npm install fallback can silently build an unlocked image - #8 Dockerfile creates runtime user without pinning its GID - #9 entrypoint.sh gates `emdash init` on data.db absence, skipping migrations on PVC reuse - #10 pullPolicy: Always vs digest pinning - #11 Dockerfile state symlinks contradict the STATE_DIR contract; Dockerfile does not set ENV STATE_DIR - #12 astro is a production dependency, so npm prune --omit=dev keeps build-only tooling - #14 Two ImageUpdateAutomations write back to the same anton-helm-workloads main branch - #16 memoryCache provider is per-process; correctness depends implicitly on replicas:1 - #17 Root catch-all [slug].astro couples nav links to pages-collection rows + DB hit per unmatched path - #18 Detail pages render a 200-style body under a 404 status and have no try/catch around getEmDash* calls - #19 vite allowedHosts hardcodes ddev hostnames (dev-only; no prod impact)
107 lines
3.5 KiB
YAML
107 lines
3.5 KiB
YAML
# Defaults for the cms-plugins chart.
|
|
# Per-env overrides: Flux applies ONLY the HelmRelease `values:` block.
|
|
# values-staging.yaml / values-production.yaml are for direct `helm upgrade -f`
|
|
# use and are NOT read by Flux — keep them in sync with the HR by hand.
|
|
|
|
image:
|
|
repository: git.oleks.space/oleks/cms-plugins
|
|
tag: develop-latest
|
|
# `Always` is here for the chart-default FLOATING-TAG path: with no
|
|
# `digest` set, the image renders as `repository:<branch>-latest`
|
|
# (a mutable pointer CI retags onto each build), so kubelet must
|
|
# re-pull or it would pin to the first cached digest and never roll.
|
|
# NOTE: the deployed overlays pin by `digest` (repository@sha256:…),
|
|
# where a tag change instead changes the image *reference string*, so
|
|
# `helm upgrade` already detects it and `Always` is a no-op (a digest
|
|
# is content-addressed — it can never resolve to different bytes).
|
|
# `IfNotPresent` would be marginally better on the digest path but is
|
|
# left as `Always` so both render paths share one safe value.
|
|
pullPolicy: Always
|
|
|
|
service:
|
|
port: 4321
|
|
|
|
ingress:
|
|
enabled: true
|
|
host: cms-plugins.kotkanagrilli.fi
|
|
# TLS terminates at the Caddy reverse-proxy at the cluster edge
|
|
# (matches the woodpecker / emdash-kotkanagrilli pattern). The
|
|
# Ingress object is plain — no inline TLS, no cert-manager Certificate.
|
|
className: kube-system-traefik
|
|
|
|
# SQLite is single-writer — pin to one node so the local-path PV is sticky.
|
|
# kotkan hosts the kotkanagrilli subdomain pool, matching the
|
|
# anton-helm-workloads convention (hello-kotkan, kotkanagrilli, etc.).
|
|
nodeSelector:
|
|
kubernetes.io/hostname: kotkan
|
|
|
|
tolerations: []
|
|
affinity: {}
|
|
|
|
persistence:
|
|
enabled: true
|
|
storageClass: local-path
|
|
size: 5Gi
|
|
# Mounted at /app/state. The image symlinks /app/data.db and /app/uploads
|
|
# into this volume, so a single PVC covers SQLite + uploaded media.
|
|
mountPath: /app/state
|
|
|
|
# Plain env values (non-secret).
|
|
env:
|
|
HOST: "0.0.0.0"
|
|
PORT: "4321"
|
|
NODE_ENV: production
|
|
DEPLOY_TARGET: node
|
|
STATE_DIR: /app/state
|
|
EMDASH_ALLOWED_ORIGINS: ""
|
|
|
|
# All secrets project from one Secret. Keys expected:
|
|
# - EMDASH_ENCRYPTION_KEY (required)
|
|
existingSecret: cms-plugins-secrets
|
|
|
|
imagePullSecrets:
|
|
- name: gitea-registry-creds
|
|
|
|
probes:
|
|
liveness:
|
|
# /_emdash/api/health requires auth (401 to unauthenticated requests),
|
|
# so we probe the public site root instead. But `/` is server-rendered
|
|
# and queries SQLite content, so a content/render or DB fault makes it
|
|
# 500 while the Node process is perfectly alive. Liveness must NOT
|
|
# crash-loop the single SQLite replica over a transient content/DB
|
|
# error: keep failureThreshold high so only a genuinely wedged process
|
|
# (sustained failures) triggers a restart. Readiness (below) is what
|
|
# sheds traffic on a content 500.
|
|
path: /
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 30
|
|
timeoutSeconds: 5
|
|
failureThreshold: 6
|
|
readiness:
|
|
# Probe the public site root. A content/render 500 here removes the pod
|
|
# from Endpoints (stops serving 500s) WITHOUT the kubelet killing the
|
|
# process — readiness failures never restart the container.
|
|
path: /
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 10
|
|
timeoutSeconds: 5
|
|
failureThreshold: 3
|
|
|
|
resources:
|
|
requests:
|
|
cpu: 100m
|
|
memory: 256Mi
|
|
limits:
|
|
cpu: "1"
|
|
memory: 1Gi
|
|
|
|
podSecurityContext:
|
|
fsGroup: 1001
|
|
containerSecurityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 1001
|
|
runAsGroup: 1001
|
|
allowPrivilegeEscalation: false
|
|
capabilities:
|
|
drop: [ALL]
|