paperless-ngx: Valkey optional als Abhaengigkeit, Passwort aus dem Redis-Item #78

Closed
opened 2026-10-02 22:24:09 +02:00 by jlab-bot · 2 comments
Member

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

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 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ä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.
`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.
Author
Member

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:

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.
# 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.
Author
Member

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

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.

# 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.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jlab-cluster/helm-charts#78