paperless-ngx soll Valkey optional als Abhängigkeit mitliefern, und das Passwort dafür soll aus demselben 1Password-Item kommen, das schon die Redis-Verbindung trägt. Benutzt wird unser eigener valkey-Chart in der veröffentlichten Fassung.
Es gibt nur einen Paperless-Chart; „die Paperless-Instanzen" sind mehrere Releases davon, die Änderung landet also an einer Stelle und gilt für alle.
Gemessen, nicht angenommen: der Index ist anonym lesbar (GET …/helm/index.yaml → 200, 41 kB) und unser Chart liegt dort als valkey-1.0.0+up9.1.2.alpine.tgz. Es braucht also keine Zugangsdaten in den Pipelines, und ci/helm-dependencies.sh bleibt unverändert.
Warum die veröffentlichte Fassung und nicht file://../valkey: mit einem echten Index greift Renovates eingebauter helmv3-Manager, die Kette aus ytdlp-web-player („KEEP THIS VERSION MOVING" → ci/renovate-bump-chart.sh → Patch-Bump → Publish) bleibt also erhalten. Bei file:// gibt es keine Fernversion zum Vergleichen; der Subchart wäre still veraltet und nichts hätte es gemeldet.
Das Geheimnis: ein drittes Feld im bestehenden Item
Unser valkey-Chart liest secrets.authSecretRef und erwartet im Item ein Feld auth-conf, dessen Wert die vollständige Zeile ist:
requirepass <das Passwort>
Nicht das nackte Passwort — der Chart mountet das Feld als Datei und die Konfiguration includet sie, damit das Passwort nie in der Prozessliste, in einer Umgebungsvariablen oder in Helms Sichtfeld steht. Ein Init-Container prüft auf eine Zeile, die mit requirepass beginnt, und verweigert den Start, wenn sie fehlt; ohne diese Prüfung ergäbe ein leeres oder vertipptes Feld einen Valkey ohne Passwort, der vollkommen gesund aussieht (das Abbild kompiliert protected-mode aus).
Das paperless-Item trägt heute redis-connection-url und key-prefix. Umsetzung:
Das Item bekommt zusätzlichauth-conf.
valkey.secrets.authSecretRef zeigt standardmäßig auf .Values.secrets.redisSecretRef, bleibt aber überschreibbar, falls jemand den mitgelieferten Valkey doch aus einem eigenen Item speisen will.
Am valkey-Chart ist nichts zu ändern.
Drei Fallen, die dokumentiert werden müssen
1. Das Passwort steht zweimal im selben Item — einmal in der Verbindungs-URL, einmal in der requirepass-Zeile. Wer es dreht und nur ein Feld anfasst, bekommt ein paperless, das sich am eigenen mitgelieferten Valkey nicht anmelden kann. Die Alternative wäre, paperless die URL aus Teilen zusammenzusetzen; das bricht den Secret-Vertrag jeder laufenden Instanz (Major) und schleuste das Passwort durch ein Template. Bewusst nicht gewählt, die Falle wird stattdessen benannt.
2. Mit eingeschaltetem Subchart muss die URL im Tresor auf den Subchart-Service zeigen, nämlich <release>-valkey-service:6379. Der Name ist bestimmt und der Chart kennt ihn, aber die URL liegt im Tresor — das ist ein Pflichtschritt der Anleitung, nicht ein Hinweis. Zeigt sie weiter auf einen externen Redis, läuft der mitgelieferte Valkey ungenutzt mit und niemand merkt es.
3. Änderungen an valkey/ und an einem abhängigen Chart dürfen nicht in denselben PR. Die Abhängigkeit löst sich aus dem veröffentlichten Index auf. Wer beides zusammen merged, baut paperless gegen die alte Valkey-Fassung, weil die neue im selben Lauf erst veröffentlicht wird — und der Install-Test prüft dann ebenfalls die alte. Zwei aufeinanderfolgende PRs: erst valkey/, publizieren lassen, dann die Versionszeile hier anheben.
README muss mit
Der Satz in README (Abschnitt zur Registry) „no registry address appears in this repository — not even the owner path segment" wird mit dieser Änderung falsch: die Lese-Adresse des Index steht ab dann in Chart.yaml. Der Satz ist im selben PR auf das zu verengen, was weiter gilt — das Publish-Ziel und die Zugangsdaten kommen aus 1Password und stehen nicht im Repository. Der Host selbst steht ohnehin längst in CLAUDE.md (SSH-Remote, Wiki-URL); neu im Repository ist allein der Pfad /api/packages/jlab-cluster/helm, und er ist nur lesend.
Umfang
Additiv, standardmäßig aus, keine Verhaltensänderung für bestehende Instanzen → Minor: 12.1.3+up3.2.1 → 12.2.0+up3.2.1.
paperless-ngx/Chart.yaml: dependencies-Block mit Kommentar nach dem Muster von ytdlp-web-player — warum eine Abhängigkeit hier zulässig ist, was sie kostet, und die Renovate-Kette
values.yaml: valkey.enabled: false, die Weitergabe von authSecretRef, und die drei Fallen als Kommentar
values.schema.json: der neue Block, streng
NOTES.txt: das neue Feld auth-conf im Tresor-Eintrag und der Pflichtschritt zur URL
ci/paperless-ngx/: Fixtures so erweitern, dass der Pfad mit eingeschaltetem Subchart gerendert und installiert wird
README: der oben genannte Satz, plus die Zeile zum Chart falls nötig
Wiki: Seite paperless-ngx (Werte-Tabelle, die drei Fallen, der Tresor-Eintrag mit dem dritten Feld), und Chart-Style-Guidenur falls aus der Registry-Adresse eine allgemeine Konvention wird
Offen, vor dem Bauen zu klären
Greift Renovates helmv3-Manager auf einem selbst gehosteten Gitea-Index? Vorbild für den Nachweis ist #214, wo es per Dry-Run belegt wurde. Trägt es nicht, ist die Begründung für die veröffentlichte Fassung gegenüber file:// hinfällig und muss neu bewertet werden — nicht stillschweigend stehen bleiben.
Löst Helm die Version mit Build-Metadaten (+up9.1.2.alpine) im Index korrekt auf? Durch ein echtes helm dependency build zu belegen, nicht durch Lesen.
Nicht in diesem Umfang
Die CI-Prüfung für Abhängigkeitsversionen ist gegenstandslos geworden, weil Renovate die Fernabhängigkeit verfolgt. Falls daraus ein Folgevorhaben wird, wäre der sinnvolle Inhalt ein anderer: eine Prüfung, die Falle 3 abfängt, also valkey/-Änderungen gemeinsam mit Änderungen an einem abhängigen Chart im selben PR ablehnt.
NetworkPolicies für paperless: das ist #5. Der mitgelieferte Valkey bringt seine eigene mit, und sie erlaubt Ingress aus der eigenen Namespace — ein Subchart teilt die des Elternteils, es ist also nichts zu verdrahten.
`paperless-ngx` soll Valkey optional als Abhängigkeit mitliefern, und das Passwort dafür soll aus **demselben 1Password-Item** kommen, das schon die Redis-Verbindung trägt. Benutzt wird **unser eigener valkey-Chart in der veröffentlichten Fassung**.
Es gibt nur einen Paperless-Chart; „die Paperless-Instanzen" sind mehrere Releases davon, die Änderung landet also an einer Stelle und gilt für alle.
## Die Abhängigkeit
```yaml
dependencies:
- name: valkey
version: "1.0.0+up9.1.2.alpine"
repository: "https://git.jk-dev.de/api/packages/jlab-cluster/helm"
condition: valkey.enabled
```
Gemessen, nicht angenommen: der Index ist **anonym lesbar** (`GET …/helm/index.yaml` → 200, 41 kB) und unser Chart liegt dort als `valkey-1.0.0+up9.1.2.alpine.tgz`. Es braucht also **keine Zugangsdaten** in den Pipelines, und `ci/helm-dependencies.sh` bleibt unverändert.
**Warum die veröffentlichte Fassung und nicht `file://../valkey`:** mit einem echten Index greift Renovates eingebauter `helmv3`-Manager, die Kette aus `ytdlp-web-player` („KEEP THIS VERSION MOVING" → `ci/renovate-bump-chart.sh` → Patch-Bump → Publish) bleibt also erhalten. Bei `file://` gibt es keine Fernversion zum Vergleichen; der Subchart wäre still veraltet und nichts hätte es gemeldet.
## Das Geheimnis: ein drittes Feld im bestehenden Item
Unser valkey-Chart liest `secrets.authSecretRef` und erwartet im Item **ein Feld `auth-conf`**, dessen Wert die vollständige Zeile ist:
```
requirepass <das Passwort>
```
Nicht das nackte Passwort — der Chart mountet das Feld als Datei und die Konfiguration `include`t sie, damit das Passwort nie in der Prozessliste, in einer Umgebungsvariablen oder in Helms Sichtfeld steht. Ein Init-Container prüft auf eine Zeile, die mit `requirepass ` beginnt, und verweigert den Start, wenn sie fehlt; ohne diese Prüfung ergäbe ein leeres oder vertipptes Feld einen Valkey **ohne Passwort**, der vollkommen gesund aussieht (das Abbild kompiliert protected-mode aus).
Das paperless-Item trägt heute `redis-connection-url` und `key-prefix`. Umsetzung:
- Das Item bekommt **zusätzlich** `auth-conf`.
- `valkey.secrets.authSecretRef` zeigt standardmäßig auf `.Values.secrets.redisSecretRef`, bleibt aber überschreibbar, falls jemand den mitgelieferten Valkey doch aus einem eigenen Item speisen will.
- **Am valkey-Chart ist nichts zu ändern.**
## Drei Fallen, die dokumentiert werden müssen
**1. Das Passwort steht zweimal im selben Item** — einmal in der Verbindungs-URL, einmal in der `requirepass`-Zeile. Wer es dreht und nur ein Feld anfasst, bekommt ein paperless, das sich am eigenen mitgelieferten Valkey nicht anmelden kann. Die Alternative wäre, paperless die URL aus Teilen zusammenzusetzen; das bricht den Secret-Vertrag jeder laufenden Instanz (Major) und schleuste das Passwort durch ein Template. Bewusst nicht gewählt, die Falle wird stattdessen benannt.
**2. Mit eingeschaltetem Subchart muss die URL im Tresor auf den Subchart-Service zeigen**, nämlich `<release>-valkey-service:6379`. Der Name ist bestimmt und der Chart kennt ihn, aber die URL liegt im Tresor — das ist ein Pflichtschritt der Anleitung, nicht ein Hinweis. Zeigt sie weiter auf einen externen Redis, läuft der mitgelieferte Valkey ungenutzt mit und niemand merkt es.
**3. Änderungen an `valkey/` und an einem abhängigen Chart dürfen nicht in denselben PR.** Die Abhängigkeit löst sich aus dem **veröffentlichten** Index auf. Wer beides zusammen merged, baut paperless gegen die *alte* Valkey-Fassung, weil die neue im selben Lauf erst veröffentlicht wird — und der Install-Test prüft dann ebenfalls die alte. Zwei aufeinanderfolgende PRs: erst `valkey/`, publizieren lassen, dann die Versionszeile hier anheben.
## README muss mit
Der Satz in README (Abschnitt zur Registry) „**no registry address appears in this repository — not even the owner path segment**" wird mit dieser Änderung **falsch**: die Lese-Adresse des Index steht ab dann in `Chart.yaml`. Der Satz ist im selben PR auf das zu verengen, was weiter gilt — das **Publish-Ziel und die Zugangsdaten** kommen aus 1Password und stehen nicht im Repository. Der Host selbst steht ohnehin längst in CLAUDE.md (SSH-Remote, Wiki-URL); neu im Repository ist allein der Pfad `/api/packages/jlab-cluster/helm`, und er ist nur lesend.
## Umfang
Additiv, standardmäßig aus, keine Verhaltensänderung für bestehende Instanzen → **Minor**: `12.1.3+up3.2.1` → `12.2.0+up3.2.1`.
- `paperless-ngx/Chart.yaml`: `dependencies`-Block mit Kommentar nach dem Muster von `ytdlp-web-player` — warum eine Abhängigkeit hier zulässig ist, was sie kostet, und die Renovate-Kette
- `values.yaml`: `valkey.enabled: false`, die Weitergabe von `authSecretRef`, und die drei Fallen als Kommentar
- `values.schema.json`: der neue Block, streng
- `NOTES.txt`: das neue Feld `auth-conf` im Tresor-Eintrag und der Pflichtschritt zur URL
- `ci/paperless-ngx/`: Fixtures so erweitern, dass der Pfad mit eingeschaltetem Subchart gerendert und installiert wird
- README: der oben genannte Satz, plus die Zeile zum Chart falls nötig
- Wiki: Seite `paperless-ngx` (Werte-Tabelle, die drei Fallen, der Tresor-Eintrag mit dem dritten Feld), und `Chart-Style-Guide` **nur** falls aus der Registry-Adresse eine allgemeine Konvention wird
## Offen, vor dem Bauen zu klären
- **Greift Renovates `helmv3`-Manager auf einem selbst gehosteten Gitea-Index?** Vorbild für den Nachweis ist #214, wo es per Dry-Run belegt wurde. Trägt es nicht, ist die Begründung für die veröffentlichte Fassung gegenüber `file://` hinfällig und muss neu bewertet werden — nicht stillschweigend stehen bleiben.
- **Löst Helm die Version mit Build-Metadaten (`+up9.1.2.alpine`) im Index korrekt auf?** Durch ein echtes `helm dependency build` zu belegen, nicht durch Lesen.
## Nicht in diesem Umfang
- Die CI-Prüfung für Abhängigkeitsversionen ist **gegenstandslos geworden**, weil Renovate die Fernabhängigkeit verfolgt. Falls daraus ein Folgevorhaben wird, wäre der sinnvolle Inhalt ein anderer: eine Prüfung, die Falle 3 abfängt, also `valkey/`-Änderungen gemeinsam mit Änderungen an einem abhängigen Chart im selben PR ablehnt.
- NetworkPolicies für paperless: das ist #5. Der mitgelieferte Valkey bringt seine eigene mit, und sie erlaubt Ingress aus der eigenen Namespace — ein Subchart teilt die des Elternteils, es ist also nichts zu verdrahten.
Korrektur: die Bedingung heißt valkeySubchart.enabled, nicht valkey.enabled
Der Plan oben nennt condition: valkey.enabled. Das funktioniert nicht, und es fällt nicht beim Bauen auf — belegt in #77, wo dieselbe Abhängigkeit zuerst so geschrieben war.
Alles unter valkey: wird an den Subchart weitergegeben und gegen dessenvalues.schema.json geprüft. Unser valkey-Chart hat dort additionalProperties: false und kennt kein enabled:
valkey: - at '': additional properties 'enabled' not allowed
Gefährlich ist der Zeitpunkt: Helm überspringt die Schema-Prüfung eines abgeschalteten Subcharts. Mit valkey.enabled: false als Vorgabe bleiben Lint, Render und Install-Test also alle grün, und der Fehler wartet auf den ersten Betreiber, der den Subchart einschaltet — also genau auf den Fall, für den der Wert existiert.
Das ist auch die ehrlichere Form, denn enabled war nie ein Valkey-Wert. In values.yaml stehen damit zwei getrennte Dinge: valkeySubchart.enabled als unser Schalter, und valkey: als der Block, der unverändert an den Subchart geht.
Verworfen wurde das naheliegende Gegenmittel, enabled in das Schema des valkey-Charts aufzunehmen: der Chart liest den Schlüssel nicht, es wäre ein Wert, der nichts tut, und es hätte einen eigenen PR samt Veröffentlichung vorher gebraucht.
Beide Punkte unter „Offen, vor dem Bauen zu klären" sind damit erledigt und müssen nicht erneut gemessen werden:
Frage
Ergebnis
Löst Helm die Version mit Build-Metadaten (+up9.1.2.alpine) aus dem Index auf?
Ja, dependency update und build, und zwar mit leerer HELM_REPOSITORY_CONFIG — also im Zustand eines frischen Runners, ohne helm repo add und ohne Zugangsdaten. ci/helm-dependencies.sh bleibt unangetastet. Auf einem echten Runner in Lauf 419 bestätigt.
Greift Renovates helmv3-Manager auf unserem selbst gehosteten Gitea-Index?
Ja. Renovate 44.132.2, Dry-Run mit niedriger gepinnter Abhängigkeit: der Manager traf die Datei, nahm registryUrls aus Chart.yaml und bot newVersion: "1.0.0+up9.1.2.alpine" mit versioning: "helm". Die Begründung für die veröffentlichte Fassung gegenüber file:// steht damit.
Die README-Korrektur („no registry address appears in this repository") ist in #77 enthalten. Dieses Vorhaben findet sie vor, sobald #77 gemergt ist — vorher nicht. Ein Branch von origin/main vor dem Merge müsste sie erneut machen und bekäme einen Konflikt. Also: #77 zuerst mergen.
Die Falle, dass valkey/-Änderungen nicht in denselben PR wie Änderungen an einem abhängigen Chart dürfen, steht schon an drei Wiki-Stellen, darunter valkey.md selbst. Hier ist sie nicht erneut zu dokumentieren, sondern nur in paperless-ngx' eigener Werte-Datei zu erwähnen.
Der Service-Name <release>-valkey-service ist in #77 gegen die gerenderte Ausgabe bestätigt.
# Korrektur: die Bedingung heißt `valkeySubchart.enabled`, nicht `valkey.enabled`
Der Plan oben nennt `condition: valkey.enabled`. **Das funktioniert nicht**, und es fällt nicht beim Bauen auf — belegt in #77, wo dieselbe Abhängigkeit zuerst so geschrieben war.
Alles unter `valkey:` wird an den Subchart weitergegeben und gegen **dessen** `values.schema.json` geprüft. Unser valkey-Chart hat dort `additionalProperties: false` und kennt kein `enabled`:
```
valkey: - at '': additional properties 'enabled' not allowed
```
Gefährlich ist der Zeitpunkt: **Helm überspringt die Schema-Prüfung eines abgeschalteten Subcharts.** Mit `valkey.enabled: false` als Vorgabe bleiben Lint, Render und Install-Test also alle grün, und der Fehler wartet auf den ersten Betreiber, der den Subchart einschaltet — also genau auf den Fall, für den der Wert existiert.
**Richtig ist ein Schlüssel unseres eigenen Charts:**
```yaml
dependencies:
- name: valkey
version: "1.0.0+up9.1.2.alpine"
repository: "https://git.jk-dev.de/api/packages/jlab-cluster/helm"
condition: valkeySubchart.enabled
```
Das ist auch die ehrlichere Form, denn `enabled` war nie ein Valkey-Wert. In `values.yaml` stehen damit zwei getrennte Dinge: `valkeySubchart.enabled` als unser Schalter, und `valkey:` als der Block, der unverändert an den Subchart geht.
Verworfen wurde das naheliegende Gegenmittel, `enabled` in das Schema des valkey-Charts aufzunehmen: der Chart liest den Schlüssel nicht, es wäre ein Wert, der nichts tut, und es hätte einen eigenen PR samt Veröffentlichung **vorher** gebraucht.
## Zwei Belege aus #77, die hier gelten
Beide Punkte unter „Offen, vor dem Bauen zu klären" sind damit erledigt und müssen nicht erneut gemessen werden:
| Frage | Ergebnis |
|---|---|
| Löst Helm die Version mit Build-Metadaten (`+up9.1.2.alpine`) aus dem Index auf? | **Ja**, `dependency update` und `build`, und zwar mit **leerer `HELM_REPOSITORY_CONFIG`** — also im Zustand eines frischen Runners, ohne `helm repo add` und ohne Zugangsdaten. `ci/helm-dependencies.sh` bleibt unangetastet. Auf einem echten Runner in Lauf 419 bestätigt. |
| Greift Renovates `helmv3`-Manager auf unserem selbst gehosteten Gitea-Index? | **Ja.** Renovate 44.132.2, Dry-Run mit niedriger gepinnter Abhängigkeit: der Manager traf die Datei, nahm `registryUrls` aus `Chart.yaml` und bot `newVersion: "1.0.0+up9.1.2.alpine"` mit `versioning: "helm"`. Die Begründung für die veröffentlichte Fassung gegenüber `file://` steht damit. |
## Was #77 bereits erledigt hat
- Die **README-Korrektur** („no registry address appears in this repository") ist in #77 enthalten. Dieses Vorhaben findet sie vor, **sobald #77 gemergt ist** — vorher nicht. Ein Branch von `origin/main` vor dem Merge müsste sie erneut machen und bekäme einen Konflikt. Also: #77 zuerst mergen.
- Die **Falle, dass `valkey/`-Änderungen nicht in denselben PR wie Änderungen an einem abhängigen Chart dürfen**, steht schon an drei Wiki-Stellen, darunter `valkey.md` selbst. Hier ist sie nicht erneut zu dokumentieren, sondern nur in `paperless-ngx`' eigener Werte-Datei zu erwähnen.
- Der Service-Name `<release>-valkey-service` ist in #77 gegen die gerenderte Ausgabe bestätigt.
Anhalten: ein Punkt des Plans ist so nicht baubar — valkey.secrets.authSecretRef kann keinen Vorgabewert aus secrets.redisSecretRef haben
Der Plan nennt drei Punkte unter „Das Geheimnis: ein drittes Feld im bestehenden Item". Der erste und der dritte tragen. Der zweite trägt nicht:
valkey.secrets.authSecretRef zeigt standardmäßig auf .Values.secrets.redisSecretRef, bleibt aber überschreibbar […] Am valkey-Chart ist nichts zu ändern.
Diese beiden Sätze widersprechen sich. Eine Helm-values.yaml wird nie getemplatet, und ein Elternchart kann einen Subchart-Wert nicht berechnen: die Werte werden vor dem Rendern statisch gemerged. Ein Vorgabewert, der auf einen anderen Wert zeigt, existiert in Helm nicht — es gibt nur import-values (Kind → Eltern, also die falsche Richtung) und global (das unser valkey-Chart nicht liest, es liest .Values.secrets.authSecretRef).
Gemessen, nicht gelesen
Gegen stalwart auf main (dieselbe Abhängigkeit, Subchart eingeschaltet), Werte-Datei mit
Error: YAML parse error on stalwart/charts/valkey/templates/valkey.secret.yaml:
error converting YAML to JSON: yaml: invalid map key:
map[interface {}]interface {}{".Values.secrets.dataStoreSecretRef":interface {}(nil)}
Die Zeichenkette wird also nicht ausgewertet, sondern landet wörtlich in itemPath: — wo {{ von YAML als Flow-Map gelesen wird. Das ist die Bestätigung in der unangenehmsten Form: nicht „funktioniert nicht", sondern „scheitert mit einer Meldung, die auf die Vorlage des Subcharts zeigt und den eigentlichen Grund nicht nennt".
Dazu passt, dass stalwart — in #77 gebaut und reviewt — genau diesen Vorgabewert nicht hat: dort steht valkey.secrets.authSecretRef: null mit dem Kommentar „REQUIRED once the subchart is on — the subchart's own required() aborts the render without it". Das war keine Auslassung, das ist die einzige Form, die geht.
Die drei Auswege, und welcher mir der richtige scheint
A — Die Form von #77, nur besser beschriftet (meine Empfehlung). valkey.secrets.authSecretRef: null, und in values.yaml steht, dass hier derselbe op://-Pfad wie in secrets.redisSecretRef einzutragen ist, weil das auth-conf-Feld in genau diesem Item liegt. Zusätzlich ein fail im Elternchart, das bei valkeySubchart.enabled: true und leerem valkey.secrets.authSecretRef beide Werte-Pfade namentlich nennt — damit kommt die Meldung vor der generischen required()-Meldung des Subcharts und nennt den Zusammenhang, den der Subchart nicht kennen kann.
Kosten: der Pfad steht zweimal in der Werte-Datei. Das ist eine Zeile Tipparbeit und ein lautes Scheitern, wenn sie fehlt — nichts davon ist still.
Nicht wählbar ist dabei ein fail, das Gleichheit der beiden Pfade erzwingt: „bleibt überschreibbar" ist ausdrücklich gewollt, und ein eigenes Item für den mitgelieferten Valkey ist ein legitimer Fall. Höchstens ein Hinweis in NOTES.txt, wenn die beiden Pfade auseinanderfallen.
B — Wie A, aber ohne den fail im Elternchart. Billiger, und die Meldung ist dann die des Subcharts: „You must provide an auth Secret Reference (secrets.authSecretRef)". Die nennt secrets.authSecretRef, nicht valkey.secrets.authSecretRef, und sagt nichts über das Redis-Item — wer sie zum ersten Mal sieht, sucht sie im falschen Chart.
C — Der Vorgabewert mechanisch, mit einer Änderung am valkey-Chart. Entweder itemPath durch tpl rendern oder im valkey-Chart einen global-Rückfall einbauen. Das ist die einzige Variante, in der der Plan buchstäblich umsetzbar wird — und sie verletzt „am valkey-Chart ist nichts zu ändern", braucht einen eigenen, vorher gemergten und veröffentlichten PR an valkey/ (Falle 3 dieses Issues) und fügt dem valkey-Chart eine Indirektion hinzu, die nur ein Elternchart nutzt. Mein Eindruck: der Preis ist höher als die eingesparte Zeile, aber das ist eine Entscheidung und nicht meine.
Ich baue nichts, bis entschieden ist, welcher Weg gilt.
Zwei Zwischenergebnisse, damit sie nicht verloren gehen
1. QUEUE, nicht CACHE — und der Konflikt, der dabei bleibt
Der Plan verlangt eine begründete Entscheidung. Gegen den Quelltext von paperless-ngx v3.2.1 (src/paperless/settings/__init__.py, settings/custom.py) gelesen, nicht aus dem Gedächtnis: PAPERLESS_REDIS ist eine URL, und parse_redis_url gibt für eine TCP-URL zweimal dieselbe zurück. Diese eine Instanz trägt fünf Dinge:
PAPERLESS_DB_READ_CACHE_ENABLED, Vorgabe no, TTL 3600
neu berechenbar, standardmäßig aus
Bemerkenswert und gegen die ältere Annahme: das Result-Backend liegt in 3.x in Redis, nicht mehr in der Datenbank.
Entscheidung: QUEUE — persistence.enabled: true, valkey.maxmemoryPolicy: noeviction. Nicht nur, weil der Broker die Warteschlange ist, sondern weil allkeys-lru hier aktiv falsch wäre: LRU räumt über den gesamten Schlüsselraum ohne Rücksicht auf den Typ, und ein Rückstau wartender Consume-Aufträge ist genau die Art Daten, die LRU als „kalt" sieht — einmal geschrieben, später gelesen. Eine Cache-Konfiguration würde also bevorzugt die Arbeit wegwerfen und die Cache-Einträge behalten. Dazu kommt das Result-Backend: ein verdrängtes Ergebnis heißt ein Auftrag, der in der Oberfläche für immer „gestartet" bleibt. Und der Verlust ist still — ein verlorener Consume-Auftrag heißt eine Datei, die im Consume-Verzeichnis liegen bleibt, obwohl der Verzeichniswächter schon ausgelöst hat.
Der Konflikt, der dabei bleibt, statt ihn zu glätten: zwei der fünf Verbraucher sind Caches, und sie bekommen mit noeviction die Richtlinie, die nicht zu ihnen passt. Läuft die Instanz voll, verweigert Valkey Schreibzugriffe, und das trifft Cache-Schreibvorgänge und neue Aufträge gleichermaßen — paperless fängt an zu Fehlern, statt leise schlechter zu werden. Das ist die laute Richtung und damit die richtige, aber es ist ein Preis und kein Nebeneffekt. Die Gegenmaßnahme ist Speicher nach dem Arbeitsvorrat zu bemessen, nicht die Richtlinie zu wechseln. Entlastend: alle drei Cache-artigen Verbraucher sind TTL-begrenzt (15 s, 3600 s, 3600 s) und begrenzen sich dadurch selbst — sie brauchen die Verdrängung nicht, um nicht zu wachsen. Der Lesecache ist überdies standardmäßig aus.
2. Zwei Namen gegen die gerenderte Ausgabe bestätigt
helm template myrelease stalwart mit eingeschaltetem Subchart (Abhängigkeit aus dem veröffentlichten Index geholt, HELM_REPOSITORY_CONFIG leer, Rückgabewert 0):
Service: myrelease-valkey-service — bestätigt Falle 2, die URL im Tresor muss auf <release>-valkey-service:6379 zeigen.
OnePasswordItem/Secret: myrelease-valkey-secret — der Name, auf den die CI-Fixture lauten muss.
Was ich nicht prüfen konnte
In diesem Coder-Workspace gibt es kein k3d und keinen laufenden Docker-Daemon (/var/run/docker.sock existiert nicht). Der im Plan erbetene Install-Test mit eingeschaltetem Subchart ist hier also lokal nicht fahrbar; er läuft erst in der PR-Pipeline auf einem ubuntu-docker-Runner. Die Fixtures dafür lassen sich schreiben, das Ergebnis kann ich erst am PR berichten.
# Anhalten: ein Punkt des Plans ist so nicht baubar — `valkey.secrets.authSecretRef` kann keinen Vorgabewert aus `secrets.redisSecretRef` haben
Der Plan nennt drei Punkte unter „Das Geheimnis: ein drittes Feld im bestehenden Item". Der erste und der dritte tragen. Der zweite trägt nicht:
> `valkey.secrets.authSecretRef` zeigt standardmäßig auf `.Values.secrets.redisSecretRef`, bleibt aber überschreibbar […]
> **Am valkey-Chart ist nichts zu ändern.**
Diese beiden Sätze widersprechen sich. Eine Helm-`values.yaml` wird **nie** getemplatet, und ein Elternchart kann einen Subchart-Wert nicht berechnen: die Werte werden vor dem Rendern statisch gemerged. Ein Vorgabewert, der auf einen anderen Wert *zeigt*, existiert in Helm nicht — es gibt nur `import-values` (Kind → Eltern, also die falsche Richtung) und `global` (das unser valkey-Chart nicht liest, es liest `.Values.secrets.authSecretRef`).
## Gemessen, nicht gelesen
Gegen `stalwart` auf `main` (dieselbe Abhängigkeit, Subchart eingeschaltet), Werte-Datei mit
```yaml
valkey:
secrets:
authSecretRef: "{{ .Values.secrets.dataStoreSecretRef }}"
```
`helm template` bricht ab:
```
Error: YAML parse error on stalwart/charts/valkey/templates/valkey.secret.yaml:
error converting YAML to JSON: yaml: invalid map key:
map[interface {}]interface {}{".Values.secrets.dataStoreSecretRef":interface {}(nil)}
```
Die Zeichenkette wird also **nicht ausgewertet**, sondern landet wörtlich in `itemPath:` — wo `{{` von YAML als Flow-Map gelesen wird. Das ist die Bestätigung in der unangenehmsten Form: nicht „funktioniert nicht", sondern „scheitert mit einer Meldung, die auf die Vorlage des Subcharts zeigt und den eigentlichen Grund nicht nennt".
Dazu passt, dass `stalwart` — in #77 gebaut und reviewt — genau diesen Vorgabewert **nicht** hat: dort steht `valkey.secrets.authSecretRef: null` mit dem Kommentar „REQUIRED once the subchart is on — the subchart's own `required()` aborts the render without it". Das war keine Auslassung, das ist die einzige Form, die geht.
## Die drei Auswege, und welcher mir der richtige scheint
**A — Die Form von #77, nur besser beschriftet (meine Empfehlung).**
`valkey.secrets.authSecretRef: null`, und in `values.yaml` steht, dass hier **derselbe `op://`-Pfad** wie in `secrets.redisSecretRef` einzutragen ist, weil das `auth-conf`-Feld in genau diesem Item liegt. Zusätzlich ein `fail` im **Elternchart**, das bei `valkeySubchart.enabled: true` und leerem `valkey.secrets.authSecretRef` beide Werte-Pfade namentlich nennt — damit kommt die Meldung *vor* der generischen `required()`-Meldung des Subcharts und nennt den Zusammenhang, den der Subchart nicht kennen kann.
Kosten: der Pfad steht zweimal in der Werte-Datei. Das ist eine Zeile Tipparbeit und ein lautes Scheitern, wenn sie fehlt — nichts davon ist still.
Nicht wählbar ist dabei ein `fail`, das *Gleichheit* der beiden Pfade erzwingt: „bleibt überschreibbar" ist ausdrücklich gewollt, und ein eigenes Item für den mitgelieferten Valkey ist ein legitimer Fall. Höchstens ein Hinweis in `NOTES.txt`, wenn die beiden Pfade auseinanderfallen.
**B — Wie A, aber ohne den `fail` im Elternchart.** Billiger, und die Meldung ist dann die des Subcharts: „You must provide an auth Secret Reference (secrets.authSecretRef)". Die nennt `secrets.authSecretRef`, nicht `valkey.secrets.authSecretRef`, und sagt nichts über das Redis-Item — wer sie zum ersten Mal sieht, sucht sie im falschen Chart.
**C — Der Vorgabewert mechanisch, mit einer Änderung am valkey-Chart.** Entweder `itemPath` durch `tpl` rendern oder im valkey-Chart einen `global`-Rückfall einbauen. Das ist die einzige Variante, in der der Plan buchstäblich umsetzbar wird — und sie verletzt „am valkey-Chart ist nichts zu ändern", braucht einen **eigenen, vorher gemergten und veröffentlichten** PR an `valkey/` (Falle 3 dieses Issues) und fügt dem valkey-Chart eine Indirektion hinzu, die nur ein Elternchart nutzt. Mein Eindruck: der Preis ist höher als die eingesparte Zeile, aber das ist eine Entscheidung und nicht meine.
Ich baue **nichts**, bis entschieden ist, welcher Weg gilt.
---
## Zwei Zwischenergebnisse, damit sie nicht verloren gehen
### 1. QUEUE, nicht CACHE — und der Konflikt, der dabei bleibt
Der Plan verlangt eine begründete Entscheidung. Gegen den Quelltext von paperless-ngx **v3.2.1** (`src/paperless/settings/__init__.py`, `settings/custom.py`) gelesen, nicht aus dem Gedächtnis: `PAPERLESS_REDIS` ist **eine** URL, und `parse_redis_url` gibt für eine TCP-URL zweimal dieselbe zurück. Diese eine Instanz trägt **fünf** Dinge:
| Verbraucher | Einstellung | Charakter |
| --- | --- | --- |
| Celery-Broker | `CELERY_BROKER_URL` | **Warteschlange**, Arbeitsvorrat |
| Celery-Result-Backend | `CELERY_RESULT_BACKEND = _CELERY_REDIS_URL`, `CELERY_RESULT_EXPIRES = 3600` | Zustand laufender Aufträge, TTL 1 h |
| Websocket-Kanalschicht | `channels_redis.pubsub.RedisPubSubChannelLayer`, `expiry: 15` | Pub/Sub, keine gespeicherten Schlüssel |
| Django-Cache `default` | `django.core.cache.backends.redis.RedisCache` | neu berechenbar |
| Cachalot-Lesecache `read-cache` | `PAPERLESS_DB_READ_CACHE_ENABLED`, Vorgabe `no`, TTL 3600 | neu berechenbar, standardmäßig aus |
Bemerkenswert und gegen die ältere Annahme: **das Result-Backend liegt in 3.x in Redis**, nicht mehr in der Datenbank.
**Entscheidung: QUEUE** — `persistence.enabled: true`, `valkey.maxmemoryPolicy: noeviction`. Nicht nur, weil der Broker die Warteschlange ist, sondern weil `allkeys-lru` hier *aktiv falsch* wäre: LRU räumt über den gesamten Schlüsselraum ohne Rücksicht auf den Typ, und ein Rückstau wartender Consume-Aufträge ist genau die Art Daten, die LRU als „kalt" sieht — einmal geschrieben, später gelesen. Eine Cache-Konfiguration würde also bevorzugt die Arbeit wegwerfen und die Cache-Einträge behalten. Dazu kommt das Result-Backend: ein verdrängtes Ergebnis heißt ein Auftrag, der in der Oberfläche für immer „gestartet" bleibt. Und der Verlust ist still — ein verlorener Consume-Auftrag heißt eine Datei, die im Consume-Verzeichnis liegen bleibt, obwohl der Verzeichniswächter schon ausgelöst hat.
**Der Konflikt, der dabei bleibt, statt ihn zu glätten:** zwei der fünf Verbraucher sind Caches, und sie bekommen mit `noeviction` die Richtlinie, die nicht zu ihnen passt. Läuft die Instanz voll, **verweigert Valkey Schreibzugriffe**, und das trifft Cache-Schreibvorgänge und neue Aufträge gleichermaßen — paperless fängt an zu Fehlern, statt leise schlechter zu werden. Das ist die laute Richtung und damit die richtige, aber es ist ein Preis und kein Nebeneffekt. Die Gegenmaßnahme ist Speicher nach dem Arbeitsvorrat zu bemessen, nicht die Richtlinie zu wechseln. Entlastend: alle drei Cache-artigen Verbraucher sind TTL-begrenzt (15 s, 3600 s, 3600 s) und begrenzen sich dadurch selbst — sie brauchen die Verdrängung nicht, um nicht zu wachsen. Der Lesecache ist überdies standardmäßig aus.
### 2. Zwei Namen gegen die gerenderte Ausgabe bestätigt
`helm template myrelease stalwart` mit eingeschaltetem Subchart (Abhängigkeit aus dem veröffentlichten Index geholt, `HELM_REPOSITORY_CONFIG` leer, Rückgabewert 0):
- Service: `myrelease-valkey-service` — bestätigt Falle 2, die URL im Tresor muss auf `<release>-valkey-service:6379` zeigen.
- OnePasswordItem/Secret: `myrelease-valkey-secret` — der Name, auf den die CI-Fixture lauten muss.
### Was ich nicht prüfen konnte
In diesem Coder-Workspace gibt es **kein k3d und keinen laufenden Docker-Daemon** (`/var/run/docker.sock` existiert nicht). Der im Plan erbetene Install-Test mit eingeschaltetem Subchart ist hier also lokal nicht fahrbar; er läuft erst in der PR-Pipeline auf einem `ubuntu-docker`-Runner. Die Fixtures dafür lassen sich schreiben, das Ergebnis kann ich erst am PR berichten.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
paperless-ngxsoll Valkey optional als Abhängigkeit mitliefern, und das Passwort dafür soll aus demselben 1Password-Item kommen, das schon die Redis-Verbindung trägt. Benutzt wird unser eigener valkey-Chart in der veröffentlichten Fassung.Es gibt nur einen Paperless-Chart; „die Paperless-Instanzen" sind mehrere Releases davon, die Änderung landet also an einer Stelle und gilt für alle.
Die Abhängigkeit
Gemessen, nicht angenommen: der Index ist anonym lesbar (
GET …/helm/index.yaml→ 200, 41 kB) und unser Chart liegt dort alsvalkey-1.0.0+up9.1.2.alpine.tgz. Es braucht also keine Zugangsdaten in den Pipelines, undci/helm-dependencies.shbleibt unverändert.Warum die veröffentlichte Fassung und nicht
file://../valkey: mit einem echten Index greift Renovates eingebauterhelmv3-Manager, die Kette ausytdlp-web-player(„KEEP THIS VERSION MOVING" →ci/renovate-bump-chart.sh→ Patch-Bump → Publish) bleibt also erhalten. Beifile://gibt es keine Fernversion zum Vergleichen; der Subchart wäre still veraltet und nichts hätte es gemeldet.Das Geheimnis: ein drittes Feld im bestehenden Item
Unser valkey-Chart liest
secrets.authSecretRefund erwartet im Item ein Feldauth-conf, dessen Wert die vollständige Zeile ist:Nicht das nackte Passwort — der Chart mountet das Feld als Datei und die Konfiguration
includet sie, damit das Passwort nie in der Prozessliste, in einer Umgebungsvariablen oder in Helms Sichtfeld steht. Ein Init-Container prüft auf eine Zeile, die mitrequirepassbeginnt, und verweigert den Start, wenn sie fehlt; ohne diese Prüfung ergäbe ein leeres oder vertipptes Feld einen Valkey ohne Passwort, der vollkommen gesund aussieht (das Abbild kompiliert protected-mode aus).Das paperless-Item trägt heute
redis-connection-urlundkey-prefix. Umsetzung:auth-conf.valkey.secrets.authSecretRefzeigt standardmäßig auf.Values.secrets.redisSecretRef, bleibt aber überschreibbar, falls jemand den mitgelieferten Valkey doch aus einem eigenen Item speisen will.Drei Fallen, die dokumentiert werden müssen
1. Das Passwort steht zweimal im selben Item — einmal in der Verbindungs-URL, einmal in der
requirepass-Zeile. Wer es dreht und nur ein Feld anfasst, bekommt ein paperless, das sich am eigenen mitgelieferten Valkey nicht anmelden kann. Die Alternative wäre, paperless die URL aus Teilen zusammenzusetzen; das bricht den Secret-Vertrag jeder laufenden Instanz (Major) und schleuste das Passwort durch ein Template. Bewusst nicht gewählt, die Falle wird stattdessen benannt.2. Mit eingeschaltetem Subchart muss die URL im Tresor auf den Subchart-Service zeigen, nämlich
<release>-valkey-service:6379. Der Name ist bestimmt und der Chart kennt ihn, aber die URL liegt im Tresor — das ist ein Pflichtschritt der Anleitung, nicht ein Hinweis. Zeigt sie weiter auf einen externen Redis, läuft der mitgelieferte Valkey ungenutzt mit und niemand merkt es.3. Änderungen an
valkey/und an einem abhängigen Chart dürfen nicht in denselben PR. Die Abhängigkeit löst sich aus dem veröffentlichten Index auf. Wer beides zusammen merged, baut paperless gegen die alte Valkey-Fassung, weil die neue im selben Lauf erst veröffentlicht wird — und der Install-Test prüft dann ebenfalls die alte. Zwei aufeinanderfolgende PRs: erstvalkey/, publizieren lassen, dann die Versionszeile hier anheben.README muss mit
Der Satz in README (Abschnitt zur Registry) „no registry address appears in this repository — not even the owner path segment" wird mit dieser Änderung falsch: die Lese-Adresse des Index steht ab dann in
Chart.yaml. Der Satz ist im selben PR auf das zu verengen, was weiter gilt — das Publish-Ziel und die Zugangsdaten kommen aus 1Password und stehen nicht im Repository. Der Host selbst steht ohnehin längst in CLAUDE.md (SSH-Remote, Wiki-URL); neu im Repository ist allein der Pfad/api/packages/jlab-cluster/helm, und er ist nur lesend.Umfang
Additiv, standardmäßig aus, keine Verhaltensänderung für bestehende Instanzen → Minor:
12.1.3+up3.2.1→12.2.0+up3.2.1.paperless-ngx/Chart.yaml:dependencies-Block mit Kommentar nach dem Muster vonytdlp-web-player— warum eine Abhängigkeit hier zulässig ist, was sie kostet, und die Renovate-Kettevalues.yaml:valkey.enabled: false, die Weitergabe vonauthSecretRef, und die drei Fallen als Kommentarvalues.schema.json: der neue Block, strengNOTES.txt: das neue Feldauth-confim Tresor-Eintrag und der Pflichtschritt zur URLci/paperless-ngx/: Fixtures so erweitern, dass der Pfad mit eingeschaltetem Subchart gerendert und installiert wirdpaperless-ngx(Werte-Tabelle, die drei Fallen, der Tresor-Eintrag mit dem dritten Feld), undChart-Style-Guidenur falls aus der Registry-Adresse eine allgemeine Konvention wirdOffen, vor dem Bauen zu klären
helmv3-Manager auf einem selbst gehosteten Gitea-Index? Vorbild für den Nachweis ist #214, wo es per Dry-Run belegt wurde. Trägt es nicht, ist die Begründung für die veröffentlichte Fassung gegenüberfile://hinfällig und muss neu bewertet werden — nicht stillschweigend stehen bleiben.+up9.1.2.alpine) im Index korrekt auf? Durch ein echteshelm dependency buildzu belegen, nicht durch Lesen.Nicht in diesem Umfang
valkey/-Änderungen gemeinsam mit Änderungen an einem abhängigen Chart im selben PR ablehnt.Korrektur: die Bedingung heißt
valkeySubchart.enabled, nichtvalkey.enabledDer Plan oben nennt
condition: valkey.enabled. Das funktioniert nicht, und es fällt nicht beim Bauen auf — belegt in #77, wo dieselbe Abhängigkeit zuerst so geschrieben war.Alles unter
valkey:wird an den Subchart weitergegeben und gegen dessenvalues.schema.jsongeprüft. Unser valkey-Chart hat dortadditionalProperties: falseund kennt keinenabled:Gefährlich ist der Zeitpunkt: Helm überspringt die Schema-Prüfung eines abgeschalteten Subcharts. Mit
valkey.enabled: falseals Vorgabe bleiben Lint, Render und Install-Test also alle grün, und der Fehler wartet auf den ersten Betreiber, der den Subchart einschaltet — also genau auf den Fall, für den der Wert existiert.Richtig ist ein Schlüssel unseres eigenen Charts:
Das ist auch die ehrlichere Form, denn
enabledwar nie ein Valkey-Wert. Invalues.yamlstehen damit zwei getrennte Dinge:valkeySubchart.enabledals unser Schalter, undvalkey:als der Block, der unverändert an den Subchart geht.Verworfen wurde das naheliegende Gegenmittel,
enabledin das Schema des valkey-Charts aufzunehmen: der Chart liest den Schlüssel nicht, es wäre ein Wert, der nichts tut, und es hätte einen eigenen PR samt Veröffentlichung vorher gebraucht.Zwei Belege aus #77, die hier gelten
Beide Punkte unter „Offen, vor dem Bauen zu klären" sind damit erledigt und müssen nicht erneut gemessen werden:
+up9.1.2.alpine) aus dem Index auf?dependency updateundbuild, und zwar mit leererHELM_REPOSITORY_CONFIG— also im Zustand eines frischen Runners, ohnehelm repo addund ohne Zugangsdaten.ci/helm-dependencies.shbleibt unangetastet. Auf einem echten Runner in Lauf 419 bestätigt.helmv3-Manager auf unserem selbst gehosteten Gitea-Index?registryUrlsausChart.yamlund botnewVersion: "1.0.0+up9.1.2.alpine"mitversioning: "helm". Die Begründung für die veröffentlichte Fassung gegenüberfile://steht damit.Was #77 bereits erledigt hat
origin/mainvor dem Merge müsste sie erneut machen und bekäme einen Konflikt. Also: #77 zuerst mergen.valkey/-Änderungen nicht in denselben PR wie Änderungen an einem abhängigen Chart dürfen, steht schon an drei Wiki-Stellen, daruntervalkey.mdselbst. Hier ist sie nicht erneut zu dokumentieren, sondern nur inpaperless-ngx' eigener Werte-Datei zu erwähnen.<release>-valkey-serviceist in #77 gegen die gerenderte Ausgabe bestätigt.Anhalten: ein Punkt des Plans ist so nicht baubar —
valkey.secrets.authSecretRefkann keinen Vorgabewert aussecrets.redisSecretRefhabenDer Plan nennt drei Punkte unter „Das Geheimnis: ein drittes Feld im bestehenden Item". Der erste und der dritte tragen. Der zweite trägt nicht:
Diese beiden Sätze widersprechen sich. Eine Helm-
values.yamlwird nie getemplatet, und ein Elternchart kann einen Subchart-Wert nicht berechnen: die Werte werden vor dem Rendern statisch gemerged. Ein Vorgabewert, der auf einen anderen Wert zeigt, existiert in Helm nicht — es gibt nurimport-values(Kind → Eltern, also die falsche Richtung) undglobal(das unser valkey-Chart nicht liest, es liest.Values.secrets.authSecretRef).Gemessen, nicht gelesen
Gegen
stalwartaufmain(dieselbe Abhängigkeit, Subchart eingeschaltet), Werte-Datei mithelm templatebricht ab:Die Zeichenkette wird also nicht ausgewertet, sondern landet wörtlich in
itemPath:— wo{{von YAML als Flow-Map gelesen wird. Das ist die Bestätigung in der unangenehmsten Form: nicht „funktioniert nicht", sondern „scheitert mit einer Meldung, die auf die Vorlage des Subcharts zeigt und den eigentlichen Grund nicht nennt".Dazu passt, dass
stalwart— in #77 gebaut und reviewt — genau diesen Vorgabewert nicht hat: dort stehtvalkey.secrets.authSecretRef: nullmit dem Kommentar „REQUIRED once the subchart is on — the subchart's ownrequired()aborts the render without it". Das war keine Auslassung, das ist die einzige Form, die geht.Die drei Auswege, und welcher mir der richtige scheint
A — Die Form von #77, nur besser beschriftet (meine Empfehlung).
valkey.secrets.authSecretRef: null, und invalues.yamlsteht, dass hier derselbeop://-Pfad wie insecrets.redisSecretRefeinzutragen ist, weil dasauth-conf-Feld in genau diesem Item liegt. Zusätzlich einfailim Elternchart, das beivalkeySubchart.enabled: trueund leeremvalkey.secrets.authSecretRefbeide Werte-Pfade namentlich nennt — damit kommt die Meldung vor der generischenrequired()-Meldung des Subcharts und nennt den Zusammenhang, den der Subchart nicht kennen kann.Kosten: der Pfad steht zweimal in der Werte-Datei. Das ist eine Zeile Tipparbeit und ein lautes Scheitern, wenn sie fehlt — nichts davon ist still.
Nicht wählbar ist dabei ein
fail, das Gleichheit der beiden Pfade erzwingt: „bleibt überschreibbar" ist ausdrücklich gewollt, und ein eigenes Item für den mitgelieferten Valkey ist ein legitimer Fall. Höchstens ein Hinweis inNOTES.txt, wenn die beiden Pfade auseinanderfallen.B — Wie A, aber ohne den
failim Elternchart. Billiger, und die Meldung ist dann die des Subcharts: „You must provide an auth Secret Reference (secrets.authSecretRef)". Die nenntsecrets.authSecretRef, nichtvalkey.secrets.authSecretRef, und sagt nichts über das Redis-Item — wer sie zum ersten Mal sieht, sucht sie im falschen Chart.C — Der Vorgabewert mechanisch, mit einer Änderung am valkey-Chart. Entweder
itemPathdurchtplrendern oder im valkey-Chart einenglobal-Rückfall einbauen. Das ist die einzige Variante, in der der Plan buchstäblich umsetzbar wird — und sie verletzt „am valkey-Chart ist nichts zu ändern", braucht einen eigenen, vorher gemergten und veröffentlichten PR anvalkey/(Falle 3 dieses Issues) und fügt dem valkey-Chart eine Indirektion hinzu, die nur ein Elternchart nutzt. Mein Eindruck: der Preis ist höher als die eingesparte Zeile, aber das ist eine Entscheidung und nicht meine.Ich baue nichts, bis entschieden ist, welcher Weg gilt.
Zwei Zwischenergebnisse, damit sie nicht verloren gehen
1. QUEUE, nicht CACHE — und der Konflikt, der dabei bleibt
Der Plan verlangt eine begründete Entscheidung. Gegen den Quelltext von paperless-ngx v3.2.1 (
src/paperless/settings/__init__.py,settings/custom.py) gelesen, nicht aus dem Gedächtnis:PAPERLESS_REDISist eine URL, undparse_redis_urlgibt für eine TCP-URL zweimal dieselbe zurück. Diese eine Instanz trägt fünf Dinge:CELERY_BROKER_URLCELERY_RESULT_BACKEND = _CELERY_REDIS_URL,CELERY_RESULT_EXPIRES = 3600channels_redis.pubsub.RedisPubSubChannelLayer,expiry: 15defaultdjango.core.cache.backends.redis.RedisCacheread-cachePAPERLESS_DB_READ_CACHE_ENABLED, Vorgabeno, TTL 3600Bemerkenswert und gegen die ältere Annahme: das Result-Backend liegt in 3.x in Redis, nicht mehr in der Datenbank.
Entscheidung: QUEUE —
persistence.enabled: true,valkey.maxmemoryPolicy: noeviction. Nicht nur, weil der Broker die Warteschlange ist, sondern weilallkeys-lruhier aktiv falsch wäre: LRU räumt über den gesamten Schlüsselraum ohne Rücksicht auf den Typ, und ein Rückstau wartender Consume-Aufträge ist genau die Art Daten, die LRU als „kalt" sieht — einmal geschrieben, später gelesen. Eine Cache-Konfiguration würde also bevorzugt die Arbeit wegwerfen und die Cache-Einträge behalten. Dazu kommt das Result-Backend: ein verdrängtes Ergebnis heißt ein Auftrag, der in der Oberfläche für immer „gestartet" bleibt. Und der Verlust ist still — ein verlorener Consume-Auftrag heißt eine Datei, die im Consume-Verzeichnis liegen bleibt, obwohl der Verzeichniswächter schon ausgelöst hat.Der Konflikt, der dabei bleibt, statt ihn zu glätten: zwei der fünf Verbraucher sind Caches, und sie bekommen mit
noevictiondie Richtlinie, die nicht zu ihnen passt. Läuft die Instanz voll, verweigert Valkey Schreibzugriffe, und das trifft Cache-Schreibvorgänge und neue Aufträge gleichermaßen — paperless fängt an zu Fehlern, statt leise schlechter zu werden. Das ist die laute Richtung und damit die richtige, aber es ist ein Preis und kein Nebeneffekt. Die Gegenmaßnahme ist Speicher nach dem Arbeitsvorrat zu bemessen, nicht die Richtlinie zu wechseln. Entlastend: alle drei Cache-artigen Verbraucher sind TTL-begrenzt (15 s, 3600 s, 3600 s) und begrenzen sich dadurch selbst — sie brauchen die Verdrängung nicht, um nicht zu wachsen. Der Lesecache ist überdies standardmäßig aus.2. Zwei Namen gegen die gerenderte Ausgabe bestätigt
helm template myrelease stalwartmit eingeschaltetem Subchart (Abhängigkeit aus dem veröffentlichten Index geholt,HELM_REPOSITORY_CONFIGleer, Rückgabewert 0):myrelease-valkey-service— bestätigt Falle 2, die URL im Tresor muss auf<release>-valkey-service:6379zeigen.myrelease-valkey-secret— der Name, auf den die CI-Fixture lauten muss.Was ich nicht prüfen konnte
In diesem Coder-Workspace gibt es kein k3d und keinen laufenden Docker-Daemon (
/var/run/docker.sockexistiert nicht). Der im Plan erbetene Install-Test mit eingeschaltetem Subchart ist hier also lokal nicht fahrbar; er läuft erst in der PR-Pipeline auf einemubuntu-docker-Runner. Die Fixtures dafür lassen sich schreiben, das Ergebnis kann ich erst am PR berichten.