github marketcalls/openalgo openalgo-minor-docker-fix
v2.0.0.9

8 hours ago

1st May 2026
Patch: Manual-Rotation Guidance Hardened — Never Recommend Rotating API_KEY_PEPPER on a Populated Database
This is a single-commit patch release on top of v2.0.0.8's Docker upgrade hotfix. The auto-rotation in utils/env_check.py already gates API_KEY_PEPPER rotation on database state — it only rotates the pepper on a fresh install with no users, because rotating it on a populated DB would invalidate every Argon2 password hash and every Fernet-encrypted broker auth/feed token / TradingView API key, none of which can be recovered. But the fallback error-path messaging — printed when the rotation cannot write to .env (e.g. read-only mount, permission denied) — was still telling users to manually regenerate both values. A user with a populated DB who followed that recipe would brick their deployment. Same problem in the start.sh pre-flight banner added in v2.0.0.8. v2.0.0.9 makes the user-facing manual-rotation guidance match the auto-rotation gating.

Highlights
Error path now DB-aware — utils/env_check.py branches the manual-rotation message on db_populated. Populated DB → instructs only APP_KEY rotation, with an explicit "DO NOT change API_KEY_PEPPER" warning and a pointer to upgrade/rotate_pepper.py. Fresh DB → both can be safely regenerated.
start.sh pre-flight banner rewritten — Default advice is APP_KEY-only. A second prominent block warns against regenerating API_KEY_PEPPER with the reasoning, and points to upgrade/rotate_pepper.py for the controlled path.

Security
b9301b7 — fix(security): never recommend rotating API_KEY_PEPPER on populated DB
The auto-rotation logic in utils/env_check.py:329-412 is correct: on a populated DB, only APP_KEY is rotated; API_KEY_PEPPER is deliberately left alone because rotating the pepper invalidates:
Every Argon2 password hash in database/user_db.py (one-way, cannot be migrated).
Every Fernet-encrypted broker auth/feed token in database/auth_db.py.
Every Fernet-encrypted TradingView API key.
But the fallback error-path — taken when the rotation can't write .env.tmp (read-only mount, EACCES) — printed:
Detected publicly-known APP_KEY/API_KEY_PEPPER in .env, but
could not rewrite the file (...).

Generate fresh values manually and paste them into .env:
python -c "import secrets; print(secrets.token_hex(32))"
That advice is safe on a fresh install, fatal on a populated one. Same issue in the start.sh pre-flight banner added in v2.0.0.8 — it instructed users to sed-replace both APP_KEY and API_KEY_PEPPER.
Fixes shipped:
utils/env_check.py — error message branches on db_populated. Populated DB prints APP_KEY-only instructions plus an explicit, bold "DO NOT change API_KEY_PEPPER on this populated install" warning, with the reasoning and a pointer to upgrade/rotate_pepper.py for the controlled rotation path that handles re-encryption + password reset. Fresh DB prints the original "both can be regenerated" guidance.
start.sh — pre-flight banner rewritten. Default action is APP_KEY-only:
APP_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")
sed -i "s|^APP_KEY =.|APP_KEY = '$APP_KEY'|" .env
sudo chown 1000:1000 .env
sudo chmod 600 .env
A second prominent banner block — [OpenAlgo] DO NOT regenerate API_KEY_PEPPER — explains why and points to the rotate_pepper.py migration. PEPPER rotation is only safe on installs with no users; on any other install, leave it alone and let the auto-rotation's silent fast path take over once APP_KEY is no longer compromised.
The _generate_keys_on_first_run decision matrix (already documented in utils/env_check.py:332-345) is unchanged. v2.0.0.9 only tightens the user-facing manual-rotation guidance to mirror the same gating.
Safe upgrade procedure for users on a populated install hitting the v2.0.0.6 → v2.0.0.8 Docker crash:
docker compose down
APP_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")
sed -i "s|^APP_KEY =.|APP_KEY = '$APP_KEY'|" .env

Do NOT touch API_KEY_PEPPER on a populated DB.

sudo chown 1000:1000 .env
sudo chmod 600 .env
docker compose up -d
After this, _generate_keys_on_first_run takes the silent fast path for APP_KEY (no longer in COMPROMISED_APP_KEYS). The pepper remains in the compromised set, but db_populated=True gates the rotation off — only a single warning line, no startup block. Browser sessions need to log in again — by-design, that's how APP_KEY rotation prevents anyone with the leaked sample key from forging your sessions.

Contributors
@marketcalls (Rajandran) — security hardening of manual-rotation guidance; PEPPER-safety review against the populated-DB upgrade path.

Links
Repository: https://github.com/marketcalls/openalgo
Documentation: https://docs.openalgo.in/
Discord: https://www.openalgo.in/discord
YouTube: https://www.youtube.com/@openalgo
Issue tracker: https://github.com/marketcalls/openalgo/issues

Don't miss a new openalgo release

NewReleases is sending notifications on new releases.