Skip to content

0.9.64

Choose a tag to compare

@cevheri cevheri released this 31 Jul 13:24
Immutable release. Only release title and notes can be modified.

A too-short JWT_SECRET now stops the app instead of failing every login

A JWT_SECRET under 32 characters used to pass every startup path untouched. The zero-config bootstrap only fills in a missing secret, nothing validated one that was set explicitly, and GET /api/db/health answered healthy regardless. The result was the worst kind of failure: a deployment that looks fine from the outside while every single login returns 503.

That is not hypothetical. The Cosmos one-click servapp shipped broken for three weeks this way - Cosmos generates 24-character passwords and its template passed one straight into JWT_SECRET.

Startup now runs an auth-config preflight after bootstrap. A secret that is set but too short prints an operator-facing banner (its length, never the value) and the process exits:

 LibreDB Studio cannot start: JWT_SECRET is too short
 Got 24 characters; the minimum is 32.
   1. Set a strong secret: JWT_SECRET=$(openssl rand -base64 32)
   2. Unset JWT_SECRET and let the first run generate one

Refusing to start is deliberate, rather than reporting it through the health check: /api/db/health is the Kubernetes livenessProbe and the Docker/PaaS health check, so failing it would restart the pod forever without fixing anything - and would hide the login screen's actionable 503 behind CrashLoopBackOff. Refusing costs nothing, because a too-short secret can sign no session at all: no working deployment can regress into this. The preflight runs on standalone boot only, so embedding @libredb/studio in a host app is unaffected.

The same trap was in our own README: the Koyeb one-click button prefilled a 17-character JWT_SECRET, which would have produced exactly the Cosmos failure for anyone deploying without editing it. Fixed.

Helm chart: 0.1.26

Chart 0.1.26 tracks this app release. The behaviour changes landed in 0.1.25, published earlier today, and are live for anyone on the chart repo:

  • Strict mode stopped demanding an admin password OIDC never uses. secrets.adminPassword is now required only while authProvider=local, and the ADMIN_PASSWORD secretKeyRef is mandatory only for strict + local - an existingSecret built for OIDC has no admin-password key, and the hard reference kept the pod from starting.
  • persistence.emptyDirSizeLimit caps the /app/data emptyDir used when persistence is off. Empty (the default) keeps it unlimited, as before.
  • persistence.fixPermissions chowns a mounted volume to runAsUser:fsGroup in a short root init container, for the hostPath and statically provisioned volumes the kubelet does not apply fsGroup to. Off by default, and rendering refuses the combination with OpenShift's security-context adaptation rather than emitting a manifest that cannot work there.
  • The admin-email Secret key is written only when secrets.adminEmail is set, like every sibling key. Both e-mail values now accept "", which hands the default back to the app.
  • Retrieving generated credentials is documented for the cases where the banner is not in the current pod log: kubectl logs --previous, reading /app/data/auth-bootstrap.json, and the arbitrary pod that kubectl logs deployment/... picks when there is more than one replica.

The chart README is now the single canonical description of bootstrap behaviour; HELM_CHART.md, DISTRIBUTION.md and RANCHER.md link to it instead of restating it - that drift had already left a wrong claim in the docs. DOCKERHUB.md no longer marks the auth variables as required, which contradicted the zero-config default.

Full changelog: 0.9.63...0.9.64