Neuer Chart: convertx (Datei-Umwandlung mit Weboberflaeche) 1.0.0+upv0.19.0 #60

Open
opened 2026-09-30 17:10:53 +02:00 by jlab-bot · 0 comments
Member

Ein Chart für ConvertX (C4illin/ConvertX), eine selbstgehostete Datei-Umwandlung mit Weboberfläche. Grundlage ist die docker-compose.yml aus der Upstream-Doku.

Dieser Text ist der freigegebene Plan; ein eigener Plan-Kommentar entfällt.

Verifizierte Fakten

Gegen die Registry und den Upstream-Quelltext geprüft, nicht aus der Erinnerung:

Abbild ghcr.io/c4illin/convertx
Tags versioniert vorhanden: v0.19.0 ist die neueste und trägt denselben Digest wie latest (sha256:8590a21a…). Daneben wandernde Tags latest, main und pr-<n>
Größe 1468 MiB komprimiert, davon eine Schicht mit 1354 MiB — LibreOffice, ImageMagick, ffmpeg, Calibre und weitere Werkzeuge stecken darin
Form WORKDIR /app, ExposedPorts 3000/tcp, ENTRYPOINT ["/entrypoint.sh"], CMD ["bun","run","dist/src/index.js"], kein deklariertes Volume
Benutzer kein USER — das Abbild startet als root. Das Dockerfile legt convertx mit uid/gid 1000 an
Daten /app/data — Datenbank und Dateien

Der Entrypoint ist die entscheidende Stelle. Er läuft mit set -e, sorgt dafür, dass /home/convertx existiert und dem Zielbenutzer gehört, chownt /app/data rekursiv, wenn die Eigentümerschaft abweicht, und wechselt per gosu convertx, sobald PUID gesetzt ist. Als Nicht-Root scheitert er sofort, weil chown, usermod und gosu Root verlangen.

Entschieden

  1. Non-root, unter Umgehung des Entrypoints. Das Chart setzt command auf bun run dist/src/index.js und startet als uid/gid 1000; fsGroup erledigt die Rechte am Volume — also genau das, was der Entrypoint per chown täte, nur von Kubernetes. Damit bleibt die Härtungs-Baseline des Repos intakt.

    Das Risiko gehört benannt: Legt upstream später Logik in den Entrypoint — Migrationen etwa —, übergehen wir sie stillschweigend. Bei jedem App-Update ist der Entrypoint deshalb mitzulesen. Das gehört als Kommentar an die command-Stelle, nicht nur in diesen Text.

  2. appVersion: v0.19.0, Chart 1.0.0+upv0.19.0.

  3. Install-Test: ja, mit erhöhtem INSTALL_TIMEOUT. Rund fünf Minuten allein für den Pull (Vergleichswert vom Runner: 96 MB in 17,5 s). Das kostet in jedem PR, der das Chart ändert, und im Rundumtest — aber ein Chart, das als root startet und dessen Startweg wir umbauen, ist genau das, bei dem ein Laufzeitnachweis am meisten wert ist.

  4. Beide Öffnungs-Schalter als Werte, Vorgabe false: ACCOUNT_REGISTRATION und ALLOW_UNAUTHENTICATED. Upstream warnt ausdrücklich davor, sie im Internet zu aktivieren; die Warnung gehört als Kommentar in values.yaml und in NOTES.txt.

Aufbau

  • StatefulSet, eine Kopie, Service, PVC unter /app/data (Datenbank und umgewandelte Dateien). scaleDown, replicas, strenges values.schema.json, null-sichere Fallbacks, additiver env-Block.
  • Ingress nach Standard, ingress.domain und ingress.clusterIssuer erforderlich, TLS-Secret tls-<release>-convertx-ingress.
  • Hochlade-Grenze: ConvertX kennt keine eigene Größenbeschränkung, also ist die proxy-body-size-Annotation des Ingress die einzige Grenze. Als Wert führen, großzügig vorgeben und den Zusammenhang kommentieren — nach dem Muster von outline, wo zwei Grenzen um Faktor zehn auseinanderlagen.
  • Secret: JWT_SECRET als OnePasswordItem (secrets.jwtSecretRef), mit required(). Ohne den Wert erzeugt die Anwendung bei jedem Start eine zufällige UUID — alle Sitzungen wären nach jedem Neustart ungültig. Feldname in NOTES.txt benennen.
  • HTTP_ALLOWED als Wert, Vorgabe false: Hinter unserem TLS-terminierenden Ingress spricht der Browser https, nur die Anwendung sieht http. Der Schalter ist nur nötig, wenn ohne TLS ausgeliefert wird — mit Kommentar, wie bei outlines forceHttps.
  • AUTO_DELETE_EVERY_N_HOURS als Wert (Vorgabe 24, 0 schaltet ab). Das entscheidet über Datenhaltung auf dem Volume und gehört sichtbar dokumentiert.
  • Härtung: readOnlyRootFilesystem: true, Capabilities weg, seccompProfile: RuntimeDefault im Pod-Kontext. Schreibpfade als emptyDir — mindestens /tmp und /home/convertx (LibreOffice und fontconfig brauchen ein beschreibbares HOME). Welche Pfade tatsächlich nötig sind, ist zu messen, nicht zu raten.
  • Ressourcen nach Konvention: Requests als Vorgabe, Limits berechnet, kein CPU-Limit. Umwandlungen sind lastintensiv; die Vorgaben sind zu begründen.
  • Renovate: eigener Block. Die wandernden Tags latest, main und pr-<n> müssen außerhalb des Musters bleiben — auf dem v-Präfix verankern, wie es ytdlp-web-player vormacht.

Was gemessen werden muss, nicht angenommen

  1. Startet die Anwendung als uid 1000 ohne den Entrypoint? Das ist die eigentliche Wette dieses Charts. Scheitert es, ist der Rückfallweg root mit PUID=1000 als dokumentierte Abweichung — dann aber mit Beleg.
  2. Welche Pfade müssen beschreibbar sein? Aus den tatsächlichen Fehlern ableiten, nicht vorsorglich emptyDirs streuen.
  3. Antwortet / mit 2xx oder 3xx, und taugt es als Readiness-Probe? Es gibt keinen dokumentierten Health-Endpunkt. Was hinter dem Pfad steckt, ist am laufenden Dienst zu prüfen — nicht am Pfadnamen.
  4. Wie lange dauert der Install-Test wirklich? Der Wert gehört in die PR-Beschreibung, weil er die Erwartung für den Rundumtest aus Gitea #52 verschiebt.

Wiring

publish-convertx.yml, Eintrag in change-app-version.yml, ci/convertx/ mit test-values.yaml und settings.env, Block in renovate.json5, README-Zeile, Wiki-Seite plus Eintrag in Charts und _Sidebar.

Ein Chart für **ConvertX** (`C4illin/ConvertX`), eine selbstgehostete Datei-Umwandlung mit Weboberfläche. Grundlage ist die `docker-compose.yml` aus der Upstream-Doku. Dieser Text ist der freigegebene Plan; ein eigener Plan-Kommentar entfällt. ## Verifizierte Fakten Gegen die Registry und den Upstream-Quelltext geprüft, nicht aus der Erinnerung: | | | |---|---| | Abbild | `ghcr.io/c4illin/convertx` | | Tags | versioniert vorhanden: **`v0.19.0`** ist die neueste und trägt **denselben Digest wie `latest`** (`sha256:8590a21a…`). Daneben wandernde Tags `latest`, `main` und `pr-<n>` | | Größe | **1468 MiB komprimiert**, davon eine Schicht mit 1354 MiB — LibreOffice, ImageMagick, ffmpeg, Calibre und weitere Werkzeuge stecken darin | | Form | `WORKDIR /app`, `ExposedPorts 3000/tcp`, `ENTRYPOINT ["/entrypoint.sh"]`, `CMD ["bun","run","dist/src/index.js"]`, kein deklariertes Volume | | Benutzer | **kein `USER`** — das Abbild startet als root. Das Dockerfile legt `convertx` mit uid/gid 1000 an | | Daten | `/app/data` — Datenbank und Dateien | **Der Entrypoint ist die entscheidende Stelle.** Er läuft mit `set -e`, sorgt dafür, dass `/home/convertx` existiert und dem Zielbenutzer gehört, chownt `/app/data` rekursiv, wenn die Eigentümerschaft abweicht, und wechselt per `gosu convertx`, sobald `PUID` gesetzt ist. **Als Nicht-Root scheitert er sofort**, weil `chown`, `usermod` und `gosu` Root verlangen. ## Entschieden 1. **Non-root, unter Umgehung des Entrypoints.** Das Chart setzt `command` auf `bun run dist/src/index.js` und startet als uid/gid 1000; `fsGroup` erledigt die Rechte am Volume — also genau das, was der Entrypoint per `chown` täte, nur von Kubernetes. Damit bleibt die Härtungs-Baseline des Repos intakt. **Das Risiko gehört benannt:** Legt upstream später Logik in den Entrypoint — Migrationen etwa —, übergehen wir sie stillschweigend. Bei jedem App-Update ist der Entrypoint deshalb mitzulesen. Das gehört als Kommentar an die `command`-Stelle, nicht nur in diesen Text. 2. **`appVersion: v0.19.0`**, Chart `1.0.0+upv0.19.0`. 3. **Install-Test: ja, mit erhöhtem `INSTALL_TIMEOUT`.** Rund fünf Minuten allein für den Pull (Vergleichswert vom Runner: 96 MB in 17,5 s). Das kostet in jedem PR, der das Chart ändert, und im Rundumtest — aber ein Chart, das als root startet und dessen Startweg wir umbauen, ist genau das, bei dem ein Laufzeitnachweis am meisten wert ist. 4. **Beide Öffnungs-Schalter als Werte, Vorgabe `false`:** `ACCOUNT_REGISTRATION` und `ALLOW_UNAUTHENTICATED`. Upstream warnt ausdrücklich davor, sie im Internet zu aktivieren; die Warnung gehört als Kommentar in `values.yaml` und in `NOTES.txt`. ## Aufbau - **StatefulSet**, eine Kopie, Service, PVC unter `/app/data` (Datenbank **und** umgewandelte Dateien). `scaleDown`, `replicas`, strenges `values.schema.json`, null-sichere Fallbacks, additiver `env`-Block. - **Ingress** nach Standard, `ingress.domain` und `ingress.clusterIssuer` erforderlich, TLS-Secret `tls-<release>-convertx-ingress`. - **Hochlade-Grenze:** ConvertX kennt keine eigene Größenbeschränkung, also ist die `proxy-body-size`-Annotation des Ingress die **einzige** Grenze. Als Wert führen, großzügig vorgeben und den Zusammenhang kommentieren — nach dem Muster von outline, wo zwei Grenzen um Faktor zehn auseinanderlagen. - **Secret:** `JWT_SECRET` als `OnePasswordItem` (`secrets.jwtSecretRef`), mit `required()`. Ohne den Wert erzeugt die Anwendung bei **jedem Start** eine zufällige UUID — alle Sitzungen wären nach jedem Neustart ungültig. Feldname in `NOTES.txt` benennen. - **`HTTP_ALLOWED`** als Wert, Vorgabe `false`: Hinter unserem TLS-terminierenden Ingress spricht der Browser https, nur die Anwendung sieht http. Der Schalter ist nur nötig, wenn ohne TLS ausgeliefert wird — mit Kommentar, wie bei outlines `forceHttps`. - **`AUTO_DELETE_EVERY_N_HOURS`** als Wert (Vorgabe 24, `0` schaltet ab). Das entscheidet über Datenhaltung auf dem Volume und gehört sichtbar dokumentiert. - **Härtung:** `readOnlyRootFilesystem: true`, Capabilities weg, `seccompProfile: RuntimeDefault` im Pod-Kontext. Schreibpfade als emptyDir — mindestens `/tmp` und `/home/convertx` (LibreOffice und fontconfig brauchen ein beschreibbares HOME). **Welche Pfade tatsächlich nötig sind, ist zu messen, nicht zu raten.** - **Ressourcen** nach Konvention: Requests als Vorgabe, Limits berechnet, kein CPU-Limit. Umwandlungen sind lastintensiv; die Vorgaben sind zu begründen. - **Renovate:** eigener Block. Die wandernden Tags `latest`, `main` und `pr-<n>` müssen **außerhalb** des Musters bleiben — auf dem `v`-Präfix verankern, wie es `ytdlp-web-player` vormacht. ## Was gemessen werden muss, nicht angenommen 1. **Startet die Anwendung als uid 1000 ohne den Entrypoint?** Das ist die eigentliche Wette dieses Charts. Scheitert es, ist der Rückfallweg root mit `PUID=1000` als dokumentierte Abweichung — dann aber mit Beleg. 2. **Welche Pfade müssen beschreibbar sein?** Aus den tatsächlichen Fehlern ableiten, nicht vorsorglich emptyDirs streuen. 3. **Antwortet `/` mit 2xx oder 3xx, und taugt es als Readiness-Probe?** Es gibt keinen dokumentierten Health-Endpunkt. Was hinter dem Pfad steckt, ist am laufenden Dienst zu prüfen — nicht am Pfadnamen. 4. **Wie lange dauert der Install-Test wirklich?** Der Wert gehört in die PR-Beschreibung, weil er die Erwartung für den Rundumtest aus Gitea #52 verschiebt. ## Wiring `publish-convertx.yml`, Eintrag in `change-app-version.yml`, `ci/convertx/` mit `test-values.yaml` und `settings.env`, Block in `renovate.json5`, README-Zeile, Wiki-Seite plus Eintrag in `Charts` und `_Sidebar`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jlab-cluster/helm-charts#60