feat(paperless-ngx): optional valkey subchart, password from the redis item
Validate Helm Charts / Detect changed charts (pull_request) Successful in 4s
Validate Helm Charts / Resource quantities (pull_request) Successful in 12s
Validate Helm Charts / Build paperless-ngx (pull_request) Successful in 6s
Validate Helm Charts / Trivy config paperless-ngx (pull_request) Successful in 22s
Install-test / Install-test paperless-ngx (pull_request) Successful in 3m31s
Validate Helm Charts / Install-test (pull_request) Successful in 3m31s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish Paperless-NGX Helm Chart / Publish Paperless-NGX Helm Chart (push) Successful in 10s
SonarQube Analysis / SonarQube Analysis (push) Successful in 33s
Validate Helm Charts / Detect changed charts (pull_request) Successful in 4s
Validate Helm Charts / Resource quantities (pull_request) Successful in 12s
Validate Helm Charts / Build paperless-ngx (pull_request) Successful in 6s
Validate Helm Charts / Trivy config paperless-ngx (pull_request) Successful in 22s
Install-test / Install-test paperless-ngx (pull_request) Successful in 3m31s
Validate Helm Charts / Install-test (pull_request) Successful in 3m31s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 10s
Publish Paperless-NGX Helm Chart / Publish Paperless-NGX Helm Chart (push) Successful in 10s
SonarQube Analysis / SonarQube Analysis (push) Successful in 33s
paperless-ngx cannot run without a Redis - PAPERLESS_REDIS is the Celery broker - so every installation needed a second Helm release whose address lived in a 1Password item and in neither chart. This adds our own published valkey chart as an optional dependency, off by default and gated on valkeySubchart.enabled (not valkey.enabled, which the subchart's strict schema rejects and which Helm would only have complained about for whoever first switched it on). Additive, default behaviour unchanged: minor, 12.1.3+up3.2.1 -> 12.2.0+up3.2.1. Configured as a QUEUE (PVC + noeviction, the subchart's defaults), unlike stalwart's cache. Read off the 3.2.1 source rather than assumed: one PAPERLESS_REDIS url serves five consumers - the Celery broker, the result backend (Redis in 3.x, the database before), the channels pub/sub layer and two Django caches. allkeys-lru would not be a trade here but actively wrong, because LRU evicts typeless across the whole keyspace and a backlog of waiting consume tasks is exactly what it reads as cold; a dropped task is a document silently never processed. The price, named in values.yaml rather than smoothed over: two of the five consumers are caches, so a full instance refuses writes - new tasks included - and the answer is memory sizing, not a policy change. All three cache-like consumers are TTL-bounded, which is what keeps that price small. The password comes from the SAME item as the Redis connection, in a third field auth-conf holding the complete line "requirepass <password>". It cannot DEFAULT to secrets.redisSecretRef, and that is a property of Helm, not an omission: a values.yaml is never templated and a parent cannot compute a subchart's value. Measured - a template expression there lands verbatim in the subchart's itemPath and fails as a YAML parse error naming neither the value nor the cause. Forgetting it is therefore caught in values.schema.json, by a conditional rule rather than a fail() in a template. Also measured, and the reason: Helm renders a subchart's templates BEFORE the parent's, so a guard in this chart loses the race to the subchart's own required(), which reports "secrets.authSecretRef" and cannot know the path belongs to the redis item. A check that cannot fire is the mistake found while testing #77, so the first draft of that guard was removed rather than shipped. The schema runs before any rendering and names /valkey/secrets/authSecretRef. One trap found while testing and closed here: "valkeySubchart: null" DELETES the key, Helm then cannot resolve the condition path and treats the dependency as ENABLED - so erasing the switch turned the subchart on with no password set. Unlike every other block in this chart (issue #99), that one is rejected by the schema instead of defaulting. The install-test now runs with the subchart ON and the throwaway redis Deployment removed: the url in the fixtures names ci-valkey-service, so the bundled Valkey is the broker the release actually uses. #65 covered this path by a render only - deliberately, since an unused Valkey would have made that test look like it covered clustering. This is the first real installation of the valkey-subchart path. Documented, not glossed: the password now sits in that item twice and a rotation has to touch both fields; with the subchart on the vault url is a mandatory step, not a hint; and a OnePasswordItem materializes every field of its item, so both Secrets carry all three keys - untidy, harmless, and written down so nobody "tidies it up". Fixes #78
This commit was merged in pull request #80.
This commit is contained in:
10 files changed
+521
-57
No files matched your search
@@ -5,9 +5,86 @@ icon: https://raw.githubusercontent.com/paperless-ngx/paperless-ngx/dev/src-ui/s
|
||||
|
||||
type: application
|
||||
|
||||
version: 12.1.3+up3.2.1
|
||||
version: 12.2.0+up3.2.1
|
||||
|
||||
appVersion: 3.2.1
|
||||
|
||||
maintainers:
|
||||
- name: jklein
|
||||
- name: jklein
|
||||
|
||||
# The third chart in this repo with a dependency (after ytdlp-web-player and
|
||||
# stalwart). README, "Chart dependencies", holds the bar a dependency has to
|
||||
# clear and the full price list; what is repeated here is only what is specific
|
||||
# to THIS chart, because the generic half is already written down twice.
|
||||
#
|
||||
# WHY ONE HERE. paperless-ngx cannot run without a Redis: PAPERLESS_REDIS is
|
||||
# the Celery broker, and without it the web UI comes up looking healthy while
|
||||
# consumption, OCR, the scheduled tasks and the index updates never run. So
|
||||
# every installation needs one, and before this block the only way to have one
|
||||
# was a second Helm release whose address lived in a 1Password item and in
|
||||
# neither chart.
|
||||
#
|
||||
# WHY IT IS OFF BY DEFAULT: an installation that already has a Redis (or wants
|
||||
# a shared one, which is what secrets.redisSecretRef' key-prefix field exists
|
||||
# for) points redis-connection-url at it, and this dependency renders nothing.
|
||||
# The subchart is the path for an installation that has none.
|
||||
#
|
||||
# THE SUBCHART IS OUR OWN valkey CHART, resolved from the published index - not
|
||||
# upstream's. So README guideline 14.2 ("we consume their chart as it comes")
|
||||
# does not apply and there are no third-party defaults to leave unpatched: the
|
||||
# subchart follows this repo's conventions because it IS this repo's chart.
|
||||
# What does apply in full is the subchart being invisible to everything
|
||||
# downstream that watches Helm release versions, and the PR-ordering hazard
|
||||
# below.
|
||||
dependencies:
|
||||
- name: valkey
|
||||
# KEEP THIS VERSION MOVING - it is the only path a Valkey update has into a
|
||||
# cluster through this chart. The version declared here is baked into our
|
||||
# packaged .tgz, so anything watching Helm release versions (Fleet
|
||||
# included) sees only "paperless-ngx": a new valkey chart, a security fix
|
||||
# included, arrives ONLY when this line is raised and a new paperless-ngx
|
||||
# version is published. Nothing reports the gap.
|
||||
#
|
||||
# Renovate's BUILT-IN helmv3 manager reads this block and opens the PR, and
|
||||
# ci/renovate-bump-chart.sh bumps this chart's patch version, which is what
|
||||
# actually ships it. No customManagers entry exists or would help - that
|
||||
# manager is for exactly this case, where repository and version sit
|
||||
# together in one file. Measured for Gitea #65 against our self-hosted
|
||||
# index (Renovate 44.132.2, dry run with the dependency pinned low:
|
||||
# newVersion "1.0.0+up9.1.2.alpine", versioning "helm"), so the chain is
|
||||
# proven for this registry and this build-metadata suffix and was not
|
||||
# re-measured here.
|
||||
#
|
||||
# Independent of appVersion: raising it is a patch or minor bump of this
|
||||
# chart and is never tied to the paperless-ngx image.
|
||||
version: "1.0.0+up9.1.2.alpine"
|
||||
# Our own published index, and the READ path only - anonymously readable
|
||||
# (measured), so ci/helm-dependencies.sh needs no credential and was not
|
||||
# touched. The publish target and its credentials still live in 1Password
|
||||
# and appear nowhere in this repository; see README, "CI/CD".
|
||||
repository: "https://git.jk-dev.de/api/packages/jlab-cluster/helm"
|
||||
# Off by default, so a plain install renders none of its objects.
|
||||
#
|
||||
# NOT "valkey.enabled", AND THAT IS NOT A STYLE CHOICE. Everything under
|
||||
# the "valkey:" key is handed to the subchart as ITS values and validated
|
||||
# against ITS schema, and our valkey chart ships additionalProperties:
|
||||
# false with no "enabled" property:
|
||||
# Error: values don't meet the specifications of the schema(s) in the
|
||||
# following chart(s): valkey: - at '': additional properties 'enabled'
|
||||
# not allowed
|
||||
# Worse, Helm skips a DISABLED subchart's schema validation, so with the
|
||||
# default of false that error would stay invisible through lint, render and
|
||||
# install-test and surface only for whoever first switched it on - the one
|
||||
# case the value exists for. The condition is therefore a key of OUR OWN,
|
||||
# outside the subchart's value subtree.
|
||||
condition: valkeySubchart.enabled
|
||||
#
|
||||
# !!! NEVER CHANGE valkey/ AND THIS CHART IN THE SAME PULL REQUEST !!!
|
||||
#
|
||||
# The dependency resolves out of the PUBLISHED index, not out of the working
|
||||
# tree, and valkey/ is published only by a push to main that touches it. A
|
||||
# single PR carrying both therefore runs lint, package, render AND the
|
||||
# install-test against the OLD valkey .tgz and goes green about an artifact
|
||||
# that is not the one in the diff. Two consecutive pull requests: change
|
||||
# valkey/, merge, let it publish, then raise the version here. README, "Chart
|
||||
# dependencies", and the wiki's valkey page carry the long form.
|
||||
@@ -3,6 +3,9 @@
|
||||
{{- $barcodes := fromYaml (include "paperless-ngx.barcodes" .Values.paperless.files.barcodes) -}}
|
||||
{{- $pod := printf "%s-%s-sfs-0" .Release.Name .Chart.Name -}}
|
||||
{{- $scripts := .Values.paperless.scripts | default dict -}}
|
||||
{{- $valkeySub := (.Values.valkeySubchart | default dict).enabled -}}
|
||||
{{- $valkeyAuth := ((.Values.valkey | default dict).secrets | default dict).authSecretRef -}}
|
||||
{{- $valkeySvc := printf "%s-valkey-service" .Release.Name -}}
|
||||
{{- $pre := default (list) $scripts.preConsumptionScripts -}}
|
||||
{{- $post := default (list) $scripts.postConsumptionScripts -}}
|
||||
Paperless-ngx {{ .Chart.AppVersion }} — release {{ .Release.Name }} in namespace {{ .Release.Namespace }}.
|
||||
@@ -70,6 +73,12 @@ WHAT THE 1PASSWORD ITEMS MUST CONTAIN
|
||||
key-prefix PAPERLESS_REDIS_PREFIX — set this per release when
|
||||
several releases share one Redis, or two instances
|
||||
will consume each other's task queue
|
||||
auth-conf the COMPLETE line "requirepass PASSWORD", not a
|
||||
bare password. Read by the bundled Valkey only, so
|
||||
it is {{ if $valkeySub }}REQUIRED for this release — see the Valkey
|
||||
section below{{ else }}unused while valkeySubchart.enabled is
|
||||
false, and the item needs it only once you switch
|
||||
the bundled Valkey on{{ end }}.
|
||||
|
||||
secrets.paperlessSecretRef → {{ .Values.secrets.paperlessSecretRef }}
|
||||
Secret {{ .Release.Name }}-{{ .Chart.Name }}-secret, fields:
|
||||
@@ -117,9 +126,9 @@ CHANGING A SECRET'S CONTENT RESTARTS NOTHING
|
||||
fields points the release at whatever that new endpoint contains, empty or
|
||||
not, and the next start migrates it.
|
||||
|
||||
POSTGRES AND REDIS ARE NOT PART OF THIS CHART
|
||||
Both have to exist and be reachable before the first start. They fail in
|
||||
opposite ways, and only one of them is loud:
|
||||
POSTGRES IS NOT PART OF THIS CHART{{ if not $valkeySub }}, AND NEITHER IS REDIS{{ end }}
|
||||
{{ if $valkeySub }}The database{{ else }}Both{{ end }} ha{{ if $valkeySub }}s{{ else }}ve{{ end }} to exist and be reachable before the first start.{{ if not $valkeySub }} They fail in
|
||||
opposite ways, and only one of them is loud:{{ end }}
|
||||
|
||||
- Without the database paperless does not come up at all. All three probes
|
||||
ask for "/" on port 8000, so you get no useful error: the pod never turns
|
||||
@@ -129,7 +138,72 @@ POSTGRES AND REDIS ARE NOT PART OF THIS CHART
|
||||
broker: consumption, OCR, the scheduled tasks and the index updates simply
|
||||
never run, and documents dropped into the consume directory stay there.
|
||||
A wrong redis-connection-url costs you the whole processing side and
|
||||
nothing turns red.
|
||||
nothing turns red.{{ if $valkeySub }} This release brings its own Valkey (below), so
|
||||
the address is in your hands — which is exactly why the url is the one
|
||||
thing to check first.{{ end }}
|
||||
{{ if $valkeySub }}
|
||||
THIS RELEASE BRINGS ITS OWN VALKEY — ONE MANDATORY STEP IS IN THE VAULT
|
||||
valkeySubchart.enabled is true, so the release contains a Valkey of its own:
|
||||
StatefulSet {{ .Release.Name }}-valkey-sfs, Service {{ $valkeySvc }}, its own
|
||||
NetworkPolicy, and a PersistentVolumeClaim (persistence is on — this is a
|
||||
queue, see below).
|
||||
|
||||
1. THE CONNECTION URL MUST POINT AT IT. This is a step, not a hint: the url
|
||||
lives in the vault and the chart cannot write it. In the item
|
||||
"{{ .Values.secrets.redisSecretRef }}", field redis-connection-url:
|
||||
|
||||
redis://:PASSWORD@{{ $valkeySvc }}:6379
|
||||
|
||||
Pointing elsewhere is not an error anywhere: paperless talks to that other
|
||||
Redis, the Valkey next to it runs along unused, and nothing reports it.
|
||||
|
||||
2. THE PASSWORD IS IN THE ITEM TWICE — once inside redis-connection-url and
|
||||
once in the "requirepass PASSWORD" line of auth-conf. Both are the same
|
||||
password, and a rotation has to touch BOTH fields. Change only one and
|
||||
paperless can no longer authenticate against its own Valkey. After any
|
||||
such change, restart both workloads by hand (Helm cannot see inside a
|
||||
1Password item, so nothing rolls automatically):
|
||||
|
||||
kubectl -n {{ .Release.Namespace }} rollout restart statefulset/{{ .Release.Name }}-{{ .Chart.Name }}-sfs
|
||||
kubectl -n {{ .Release.Namespace }} rollout restart statefulset/{{ .Release.Name }}-valkey-sfs
|
||||
|
||||
3. AUTH-CONF IS A CONFIGURATION LINE, NOT A PASSWORD. The Valkey mounts the
|
||||
field as a file and includes it, so the password never reaches a process
|
||||
list or an environment variable. An init container refuses to start the
|
||||
pod unless a line beginning with "requirepass " is really there — without
|
||||
that check a typo would leave a Valkey running with NO password and
|
||||
looking perfectly healthy.
|
||||
{{- if and $valkeyAuth (ne ($valkeyAuth | toString) ($.Values.secrets.redisSecretRef | toString)) }}
|
||||
|
||||
NOTE: valkey.secrets.authSecretRef points at a DIFFERENT item than
|
||||
secrets.redisSecretRef:
|
||||
valkey.secrets.authSecretRef → {{ $valkeyAuth }}
|
||||
secrets.redisSecretRef → {{ .Values.secrets.redisSecretRef }}
|
||||
That is supported and may well be deliberate — the bundled Valkey is then fed
|
||||
from its own item. It is only worth knowing that you now keep TWO items in
|
||||
step: the password in auth-conf over there and the one inside
|
||||
redis-connection-url here have to stay identical.
|
||||
{{- end }}
|
||||
|
||||
BOTH ITEMS' FIELDS LAND IN BOTH SECRETS. A OnePasswordItem materializes every
|
||||
field of the item it names, so with one shared item the Valkey's Secret also
|
||||
carries redis-connection-url and key-prefix, and this chart's redis Secret
|
||||
also carries auth-conf. Untidy and harmless — nothing mounts a field it does
|
||||
not reference. It is mentioned so it does not get "cleaned up".
|
||||
|
||||
IT IS CONFIGURED AS A QUEUE, and that is a decision: persistence on, eviction
|
||||
policy "noeviction". PAPERLESS_REDIS is the Celery broker, so its contents are
|
||||
work that must not vanish — "allkeys-lru" would evict across the whole
|
||||
keyspace and a backlog of waiting tasks is exactly what LRU reads as cold.
|
||||
The price: the same instance also serves the Django cache, so when it fills,
|
||||
writes are REFUSED rather than old keys dropped — new tasks included. The
|
||||
answer is to give it more memory (valkey.valkey.resources.requests.memory),
|
||||
never to switch the policy. values.yaml argues this in full.
|
||||
|
||||
SCALEDOWN DOES NOT REACH IT. scaleDown: true scales paperless to zero and
|
||||
leaves the Valkey running, which is the right way round for a queue: the
|
||||
backlog stays where it is.
|
||||
{{- end }}
|
||||
|
||||
THE FIRST START MIGRATES, AND THE STARTUP PROBE IS THE CLOCK
|
||||
Every start runs the database migrations before the server answers, and the
|
||||
|
||||
@@ -20,10 +20,12 @@ Usage (the values path to the resources dict varies per chart):
|
||||
{{- include "paperless-ngx.resources" .Values.<app>.resources | nindent 12 }}
|
||||
|
||||
NOTE: this helper is duplicated into every chart's templates/_helpers.tpl with
|
||||
the chart's name as define prefix, because sharing it would mean a library
|
||||
chart, and a dependency is admissible but expensive (README, guideline 14) -
|
||||
this chart takes none. This file in template-chart is the reference
|
||||
implementation.
|
||||
the chart's name as define prefix, because sharing it would mean a LIBRARY
|
||||
chart, and a dependency is admissible but expensive (README, guideline 14).
|
||||
This chart does take one - the optional valkey subchart - which changes
|
||||
nothing here: a library chart for one helper would still be the wrong trade,
|
||||
and the subchart carries its own copy of this helper anyway. This file in
|
||||
template-chart is the reference implementation.
|
||||
*/}}
|
||||
{{- define "paperless-ngx.resources" -}}
|
||||
{{- $resources := . | default dict -}}
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
{{- /*
|
||||
With the valkey subchart on, THIS is the item that also carries the "auth-conf"
|
||||
field the bundled Valkey reads (NOTES.txt prints all three fields). The rule
|
||||
that valkey.secrets.authSecretRef must then be set is enforced in
|
||||
values.schema.json and NOT by a fail() here - measured, see that file: Helm
|
||||
validates the schema before it renders, and it renders a subchart's templates
|
||||
before the parent's, so a check in this file could never beat the subchart's own
|
||||
required() to it.
|
||||
*/ -}}
|
||||
apiVersion: onepassword.com/v1
|
||||
kind: OnePasswordItem
|
||||
metadata:
|
||||
|
||||
@@ -4,6 +4,48 @@
|
||||
"description": "Strict values schema (issue #68). additionalProperties is false on every chart-owned object level, so a key that the chart does not read is rejected at render time instead of being silently ignored. The only objects that stay open are the ones passed verbatim into the Kubernetes pod spec (probes, security contexts, global) - the chart does not interpret their contents, so it cannot judge which keys are meaningful. The hardening, probe and resources blocks of BOTH workloads, and the barcodes block from issue #61, additionally accept null, because an erased block falls back to the chart defaults (issues #61 and #99).",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["valkeySubchart"],
|
||||
"allOf": [
|
||||
{
|
||||
"title": "With the valkey subchart switched on, valkey.secrets.authSecretRef is required",
|
||||
"description": "The one cross-key rule in this file, and it lives here rather than in a template on purpose: Helm validates the schema BEFORE it renders anything, and it renders a subchart's templates before the parent's. A fail() in this chart's templates therefore loses the race against the subchart's own required(), whose message names 'secrets.authSecretRef' and cannot know that the path belongs to the same 1Password item as secrets.redisSecretRef. Measured for Gitea #78 - a guard that cannot fire is the mistake found while testing #77. Set it to the SAME op:// path as secrets.redisSecretRef: the bundled Valkey reads its password from the field 'auth-conf' in that item, whose value must be the complete line 'requirepass <password>'. A different item is allowed; two items then have to be kept in step.",
|
||||
"if": {
|
||||
"required": ["valkeySubchart"],
|
||||
"properties": {
|
||||
"valkeySubchart": {
|
||||
"type": "object",
|
||||
"required": ["enabled"],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"const": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"required": ["valkey"],
|
||||
"properties": {
|
||||
"valkey": {
|
||||
"type": "object",
|
||||
"required": ["secrets"],
|
||||
"properties": {
|
||||
"secrets": {
|
||||
"type": "object",
|
||||
"required": ["authSecretRef"],
|
||||
"properties": {
|
||||
"authSecretRef": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"global": {
|
||||
"description": "Helm's conventional cross-chart values. Unused by this chart, kept open so an umbrella install cannot break on it.",
|
||||
@@ -261,6 +303,21 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"valkeySubchart": {
|
||||
"description": "The dependency condition for the valkey subchart. A key of THIS chart, deliberately outside the 'valkey' subtree: everything under 'valkey:' is handed to the subchart as its values, and this repo's valkey chart has additionalProperties: false with no 'enabled' property, so 'valkey.enabled' is rejected by the subchart itself. Helm skips a disabled subchart's schema validation, so that error would only ever have surfaced for whoever first set it to true. NOT null-safe and 'enabled' is REQUIRED, which is the opposite of this chart's other blocks (issue #99) and is deliberate: Helm treats a condition whose path does not resolve as ENABLED, so an erased 'valkeySubchart:' would switch the subchart ON - measured for Gitea #78, where it surfaced as the subchart's own required() error. An erased block must not flip behaviour, least of all in that direction, so it is rejected here instead.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["enabled"],
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"valkey": {
|
||||
"description": "Values passed through to the valkey subchart - this repo's OWN valkey chart, resolved from the published index. Open on purpose and at every level: the subchart owns this schema (it ships its own, and a stricter one than this), and a closed copy here would reject whatever that chart adds in its next release while duplicating a validation that already happens. This chart reads NONE of these keys; the dependency condition is valkeySubchart.enabled instead. Two shapes that are easy to get wrong: secrets.authSecretRef must be set BY HAND to the same op:// path as secrets.redisSecretRef (a values.yaml is never templated, so a parent cannot default it - Gitea #78), and the item's field 'auth-conf' holds the complete line 'requirepass <password>', not a bare password. values.yaml argues the queue-vs-cache choice and names the three operator traps.",
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
scaleDown: false
|
||||
|
||||
secrets:
|
||||
# op:// path of the item holding the Redis/Valkey connection. Fields:
|
||||
# "redis-connection-url" and "key-prefix" always, plus "auth-conf" when the
|
||||
# bundled Valkey subchart is used - see the valkeySubchart block at the end
|
||||
# of this file. NOTES.txt prints all three.
|
||||
redisSecretRef: null
|
||||
databaseSecretRef: null
|
||||
paperlessSecretRef: null
|
||||
@@ -176,3 +180,172 @@ oidc:
|
||||
# Some providers need this since the allauth update in paperless-ngx 3.0
|
||||
# (login fails at the callback with invalid_client otherwise).
|
||||
tokenAuthMethod: null
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# The bundled Valkey - this repo's own valkey chart as an optional subchart
|
||||
# ---------------------------------------------------------------------------
|
||||
# The switch for the dependency declared in Chart.yaml. Off by default: an
|
||||
# installation that already has a Redis points redis-connection-url at it and
|
||||
# this renders nothing.
|
||||
#
|
||||
# WHY THE KEY IS HERE AND NOT "valkey.enabled": everything under "valkey:" is
|
||||
# handed to the subchart as its values and validated against ITS strict schema,
|
||||
# which has no "enabled" property - so "valkey.enabled" is rejected BY THE
|
||||
# SUBCHART. And because Helm skips a disabled subchart's schema validation, the
|
||||
# error would only ever have appeared for whoever first switched it on.
|
||||
# Chart.yaml carries the exact error text.
|
||||
#
|
||||
# DO NOT ERASE THIS BLOCK. Unlike every other block in this file (issue #99),
|
||||
# "valkeySubchart: null" is not "the default applies" - a null override DELETES
|
||||
# the key, the dependency's condition path then does not resolve, and Helm
|
||||
# treats an unresolvable condition as ENABLED. So erasing the switch turns the
|
||||
# subchart ON, with no password set and only the subchart's own error to show
|
||||
# for it. Measured for Gitea #78; values.schema.json rejects it before anything
|
||||
# renders. An empty block ("valkeySubchart: {}") is fine, because Helm merges
|
||||
# that with the default below.
|
||||
valkeySubchart:
|
||||
enabled: false
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Values passed THROUGH to the valkey subchart
|
||||
# ---------------------------------------------------------------------------
|
||||
# Read as the SUBCHART's own values, so the key names are its schema, not this
|
||||
# chart's. `valkey/values.yaml` in this repo is the reference. Nothing here has
|
||||
# any effect while valkeySubchart.enabled is false.
|
||||
#
|
||||
# What still applies in full: the subchart is invisible to everything
|
||||
# downstream that watches Helm release versions (Chart.yaml has the detail and
|
||||
# the PR-ordering warning - never change valkey/ and this chart in the same
|
||||
# PR), and this chart's scaleDown flag does NOT reach it. scaleDown: true
|
||||
# scales paperless to zero and leaves the Valkey running; that is the right way
|
||||
# round for a queue, because the backlog stays where it is.
|
||||
valkey:
|
||||
secrets:
|
||||
# REQUIRED once the subchart is on, and it has to be set BY HAND to the
|
||||
# SAME op:// path as secrets.redisSecretRef above - because the
|
||||
# "requirepass" line lives in that same item (see the three traps below).
|
||||
#
|
||||
# IT CANNOT DEFAULT TO IT, and that is a property of Helm, not an omission:
|
||||
# a values.yaml is never templated and a parent chart cannot compute a
|
||||
# subchart's value - values are merged statically before any template runs.
|
||||
# Writing "{{ .Values.secrets.redisSecretRef }}" here does not resolve, it
|
||||
# lands verbatim in the subchart's itemPath and fails as a YAML parse error
|
||||
# pointing at the subchart's template, which names neither this value nor
|
||||
# the real cause. Measured; Gitea #78 has the output. So the path is typed
|
||||
# twice, and forgetting it is caught by a conditional rule in
|
||||
# values.schema.json - NOT by a fail() in a template, which cannot work
|
||||
# here: Helm renders a subchart's templates BEFORE the parent's, so the
|
||||
# subchart's own required() always wins that race and reports
|
||||
# "secrets.authSecretRef" instead of this value's real path. The schema runs
|
||||
# earlier than any rendering, which is why the rule lives there.
|
||||
#
|
||||
# MIND THE FIELD, it is not a password. The item must carry a field
|
||||
# "auth-conf" whose value is the COMPLETE configuration line
|
||||
# requirepass <password>
|
||||
# The valkey chart mounts that field as a file and `include`s it, so the
|
||||
# password never reaches the process list, an environment variable, or
|
||||
# Helm's field of view. An init container refuses to start the pod unless
|
||||
# the line is really there, because the alternative failure is an open
|
||||
# server that looks perfectly healthy. A bare password does not work.
|
||||
#
|
||||
# OVERRIDING IT WITH A DIFFERENT ITEM IS ALLOWED and is not a mistake: it
|
||||
# is the way to feed the bundled Valkey from its own item. The cost is that
|
||||
# two items then have to be kept in step instead of one.
|
||||
authSecretRef: null
|
||||
|
||||
# QUEUE, not cache - a decision, with the conflict it does not resolve.
|
||||
#
|
||||
# The valkey chart treats persistence and eviction as a PAIR and warns
|
||||
# against mixing them: QUEUE is persistence.enabled: true + "noeviction"
|
||||
# (its default), CACHE is persistence.enabled: false + "allkeys-lru".
|
||||
# stalwart picked CACHE. paperless-ngx is the other case - which happens to
|
||||
# be the subchart's own default, so the block below changes nothing. It is
|
||||
# written out anyway, for two reasons: the subchart's persistence block is
|
||||
# deliberately NOT null-safe (an erased one renders an invalid PVC), and the
|
||||
# decision belongs where it is argued rather than one chart away. The
|
||||
# eviction policy is NOT restated - valkey.maxmemoryPolicy stays at the
|
||||
# subchart's "noeviction", which is the queue half of the pair. storageClass
|
||||
# stays at the subchart default too (longhorn-encrypted-ns): queue payloads
|
||||
# are the same documents that are in the database, so encrypted at rest.
|
||||
#
|
||||
# Read off the paperless-ngx 3.2.1 source (src/paperless/settings/__init__.py
|
||||
# and settings/custom.py), not assumed: PAPERLESS_REDIS is ONE url, and
|
||||
# parse_redis_url returns it twice for a TCP url, so one instance carries
|
||||
# five consumers:
|
||||
#
|
||||
# 1. CELERY_BROKER_URL - the queue: consume, OCR, index
|
||||
# updates, classifier training, the
|
||||
# scheduled tasks
|
||||
# 2. CELERY_RESULT_BACKEND - also Redis in 3.x (it was the
|
||||
# database before), CELERY_RESULT_EXPIRES
|
||||
# 3600
|
||||
# 3. CHANNEL_LAYERS - channels_redis.pubsub, expiry 15s;
|
||||
# pub/sub, not stored keys
|
||||
# 4. CACHES["default"] - Django cache, recomputable
|
||||
# 5. CACHES["read-cache"] - Cachalot DB read cache, TTL 3600,
|
||||
# off unless
|
||||
# PAPERLESS_DB_READ_CACHE_ENABLED
|
||||
#
|
||||
# WHY QUEUE: "allkeys-lru" would not be a trade here, it would be actively
|
||||
# wrong. LRU evicts across the WHOLE keyspace with no regard for key type,
|
||||
# and a backlog of waiting consume tasks is exactly what LRU reads as cold -
|
||||
# written once, read later. So a cache configuration would preferentially
|
||||
# throw away the work and keep the cache entries. A dropped consume or index
|
||||
# task means a document that is silently never processed: the file stays in
|
||||
# the consume directory although the directory watcher has already fired.
|
||||
# And an evicted Celery result means a task that shows as "started" in the UI
|
||||
# forever.
|
||||
#
|
||||
# THE CONFLICT THAT STAYS, stated rather than smoothed over: two of the five
|
||||
# consumers are caches and they get the policy that does not suit them. When
|
||||
# the instance fills, "noeviction" makes Valkey REFUSE WRITES - which hits
|
||||
# cache writes and NEW TASKS alike, so paperless starts erroring instead of
|
||||
# quietly degrading. That is the loud direction and therefore the right one,
|
||||
# but it is a price and not a side effect, and the answer to it is to SIZE
|
||||
# MEMORY for the working set, never to switch the policy. What makes the
|
||||
# price small: all three cache-like consumers are TTL-bounded (15s, 3600s,
|
||||
# 3600s), so they bound themselves and do not need eviction to stay in check,
|
||||
# and the read cache is off by default.
|
||||
persistence:
|
||||
enabled: true
|
||||
appendonly: true
|
||||
# Sized for a task backlog and its results, not for documents - the
|
||||
# documents are on paperless' own PVC. Grow it if a release regularly
|
||||
# queues thousands of tasks (a PVC can grow, it can never shrink).
|
||||
size: 1Gi
|
||||
|
||||
# networkPolicy and the Valkey resources are left at the subchart's defaults
|
||||
# on purpose: its NetworkPolicy is on and allows the release's own namespace,
|
||||
# which with a subchart is where paperless runs. allowedNamespaces only needs
|
||||
# an entry when the two are in DIFFERENT namespaces, which a subchart rules
|
||||
# out.
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# THE THREE TRAPS OF THE BUNDLED VALKEY - all three are operator work
|
||||
# ---------------------------------------------------------------------------
|
||||
# 1. THE PASSWORD IS IN THE ITEM TWICE: inside redis-connection-url and again
|
||||
# in the "requirepass" line of auth-conf. A rotation has to touch BOTH
|
||||
# fields; touching one leaves a paperless that cannot authenticate against
|
||||
# its own bundled Valkey. The alternative - assembling the url from parts -
|
||||
# would break the secret contract of every running release (a major) and
|
||||
# route the password through a template. Deliberately not chosen; the trap
|
||||
# is named instead.
|
||||
#
|
||||
# 2. WITH THE SUBCHART ON, redis-connection-url MUST POINT AT THE SUBCHART:
|
||||
# redis://:<password>@<release>-valkey-service:6379
|
||||
# The name is determined and confirmed against the rendered output, but the
|
||||
# url lives in the vault, so this is a MANDATORY STEP of the installation
|
||||
# and not a hint. Left pointing at an external Redis, the bundled Valkey
|
||||
# runs along unused and nothing says so. NOTES.txt prints the exact name for
|
||||
# the release at hand.
|
||||
#
|
||||
# 3. A OnePasswordItem MATERIALIZES EVERY FIELD OF THE ITEM. With both CRs
|
||||
# pointing at the same item, the Valkey Secret therefore also carries
|
||||
# redis-connection-url and key-prefix, and this chart's redis Secret also
|
||||
# carries auth-conf. Untidy, harmless, and written down here so nobody reads
|
||||
# it as a leak or a bug and "tidies it up": the keys are unused, and no
|
||||
# container mounts a field it does not reference.
|
||||
#
|
||||
# And one rule that is about this repository rather than about an installation:
|
||||
# changes to valkey/ must not share a pull request with changes to this chart.
|
||||
# Chart.yaml says why; README and the wiki's valkey page carry the long form.
|
||||
Reference in new issue
Block a user