# 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:-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]