The sync seeds each member's gateway key into LibreChat's per-user key store, but it can only seed a user that already exists — and LibreChat creates that row on first login. Ten minutes therefore left a new member's very first message to fail against a key-less endpoint. At one minute the window is at most 60 seconds. Zero would mean patching LibreChat's login path, which is not worth a fork for this.
Not deployed. Diffed against the official 1.4.5 manifest: version, changelog and
the base-image tag were the only differences, so this copy now matches official
field-for-field except dockerImage (+ our scheduler block).
The risk is the overlay, not the bump: every build-time patch runs against a new
base layer, and they are all non-fatal by design, so a silent no-op is the failure
mode. Verify on the rendered DOM. Rollback = repoint dockerImage to
20261023-65a38bb.
Ready to build, not yet deployed — deploying the repointed scheduler command
without the new image would break the seed on schedule, which is why this sits on
a branch with the ordering written down.
- Dockerfile: COPY sync-keys.js /app/code/sync-keys.js; rule 3 in the header now
states the one exception (operational scripts that must not depend on a volume).
- CloudronManifest.json: scheduler command repointed to /app/code/sync-keys.js.
- README: ordering (build -> deploy -> verify -> delete the volume copy), and the
table row moved from the volume layer to the image layer.
After deploy: delete /app/data/sync-keys.js, but keep it until you are past the
rollback window — the previous image tag still runs the volume copy.
The per-member key seed ran from a steward cron on the co-op agent VM, shelling
into this app over the Cloudron API. That made a member-facing function depend on
a separate machine's uptime and paths (it went silently stale once, exiting 127
on schedule while the job looked healthy).
- CloudronManifest.json: addons.scheduler gains librechat_key_sync
(cd /app/code/librechat/api && node /app/data/sync-keys.js, */10 * * * *).
Official addon set (postgresql, mongodb, localstorage, oidc, sendmail) and the
dockerImage pin are untouched.
- sync-keys.js: refuse to write unless CREDS_KEY can first decrypt an existing
key row, and unless each fresh ciphertext round-trips back to the plaintext.
Scheduled runs get a different environment than an interactive exec, so a wrong
or absent CREDS_KEY must fail loudly instead of overwriting working member keys.
- CloudronManifest.json: byte-identical copy of the OFFICIAL appstore manifest
(the hand-edited one stripped addons and crash-looped the app on 2026-10-18)
- Dockerfile: pinned base (202610150224320000), brand assets only + title sed
- librechat.yaml: schema 1.3.17; chat models only in picker (qwen-image moved
to the agent image tool); speech via gateway with capped key refs; SearXNG
web search; inference-docs MCP server; forward-compatible interface.theme
- mcp/server.py: docs MCP server (stdio, stdlib-only, tool search_docs)
- assets/: co-op logo + favicons/PWA icons