README: document the in-app key-sync scheduling, the creds file, and the fail-closed guards
This commit is contained in:
1 parent
e544dc4a11
commit
2d66ea212d
1 file changed
+47
-6
@@ -299,10 +299,49 @@ member's own portal-provisioned key automatically:
|
|||||||
`customUserVars` config so image generation bills to the member's own
|
`customUserVars` config so image generation bills to the member's own
|
||||||
team.
|
team.
|
||||||
Encryption uses LibreChat's own scheme (`CREDS_KEY`/`CREDS_IV`, AES-256-CBC
|
Encryption uses LibreChat's own scheme (`CREDS_KEY`/`CREDS_IV`, AES-256-CBC
|
||||||
via `@librechat/data-schemas` `encrypt()`), read from the app process env
|
via `@librechat/data-schemas` `encrypt()`).
|
||||||
(`/proc/1/environ`) because `cloudron exec` sessions don't inherit it.
|
4. Members who haven't logged in to the sandbox yet are skipped; the next run
|
||||||
4. Members who haven't logged in to the sandbox yet are skipped; the next
|
seeds them.
|
||||||
run seeds them. Run hourly or nightly:
|
|
||||||
|
### Scheduling (in this app, since 2026-10-25)
|
||||||
|
|
||||||
|
`CloudronManifest.json` declares the task in `addons.scheduler`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"scheduler": {
|
||||||
|
"librechat_key_sync": {
|
||||||
|
"schedule": "*/10 * * * *",
|
||||||
|
"command": "cd /app/code/librechat/api && node /app/data/sync-keys.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Seeding therefore depends on nothing outside this app — it previously ran from a
|
||||||
|
steward cron on another machine, which made a member-facing function depend on
|
||||||
|
that machine's uptime and paths.
|
||||||
|
|
||||||
|
Two consequences of how the scheduler addon works, both learned the hard way:
|
||||||
|
|
||||||
|
- **Each task runs in its own container.** The app's process env is absent there,
|
||||||
|
and `/proc/1/environ` belongs to the task launcher, not to LibreChat — so
|
||||||
|
`CREDS_KEY`/`CREDS_IV` come from `/app/data/.librechat-creds` (root:cloudron
|
||||||
|
`0640`), written from the live app env:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cloudron --server my.inference.coop --token "$CLOUDRON_TOKEN" exec \
|
||||||
|
--app 4023ccbf-d57a-4500-97df-14de9cf3516e \
|
||||||
|
-- sh -c 'umask 077; tr "\0" "\n" < /proc/1/environ | grep -E "^CREDS_(KEY|IV)=" > /app/data/.librechat-creds; chown root:cloudron /app/data/.librechat-creds; chmod 640 /app/data/.librechat-creds'
|
||||||
|
```
|
||||||
|
|
||||||
|
If the app's key is ever rotated, re-run that. A stale key does not corrupt
|
||||||
|
anything — the guard below refuses to write.
|
||||||
|
- **It fails closed.** `sync-keys.js` writes nothing unless `CREDS_KEY` first
|
||||||
|
decrypts an existing key row (proof it is the app's real key) and unless each
|
||||||
|
fresh ciphertext round-trips back to the plaintext. A credential problem exits
|
||||||
|
non-zero, logs `FATAL: ...`, and writes `/app/data/key-sync-diag.txt` (uid, cwd,
|
||||||
|
which env sources were readable) instead of overwriting working member keys.
|
||||||
|
|
||||||
|
Manual run (unchanged, useful after an onboarding wave):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cloudron --server my.inference.coop --token "$CLOUDRON_TOKEN" exec \
|
cloudron --server my.inference.coop --token "$CLOUDRON_TOKEN" exec \
|
||||||
@@ -310,8 +349,10 @@ cloudron --server my.inference.coop --token "$CLOUDRON_TOKEN" exec \
|
|||||||
-- bash -c "cd /app/code/librechat/api && node /app/data/sync-keys.js"
|
-- bash -c "cd /app/code/librechat/api && node /app/data/sync-keys.js"
|
||||||
```
|
```
|
||||||
|
|
||||||
Idempotent. Verify with the DB probe: `keys` and `pluginauths` counts should
|
Idempotent. Verify: the app log shows the task's output
|
||||||
equal the number of members who have logged in to the sandbox.
|
(`creds check: decrypt-ok …` / `portal feed: N active member key(s)` /
|
||||||
|
`done: N seeded, M skipped`), and `keys` / `pluginauths` counts should equal the
|
||||||
|
number of members who have logged in to the sandbox.
|
||||||
|
|
||||||
> **Output-redaction gotcha:** terminal output renders values after
|
> **Output-redaction gotcha:** terminal output renders values after
|
||||||
> `apiKey:` as `***` even when the file contains `user_provided` or
|
> `apiKey:` as `***` even when the file contains `user_provided` or
|
||||||
|
|||||||
Reference in new issue
Block a user