CORS Strategy for OCapistaine
Overview
OCapistaine uses two CORS strategies depending on the environment:
- Production (Render): Static allowed origins configured in
render.yaml - Development (ngrok): Dynamic origins generated by
scripts/set_streamlit_env.py
Architecture
Production:
render.yaml → STREAMLIT_SERVER_ALLOWED_ORIGINS (static)
Vaettir Nginx → Render (ocapistaine.onrender.com)
Development:
.env → set_streamlit_env.py → STREAMLIT_SERVER_ALLOWED_ORIGINS (dynamic)
Vaettir Nginx → ngrok → localhost:8502
Production CORS
On Render, origins are configured statically in render.yaml:
- key: STREAMLIT_SERVER_ALLOWED_ORIGINS
value: "https://ocapistaine.onrender.com,https://ocapistaine.vaettir.locki.io,https://vaettir.locki.io"
No scripts or dynamic configuration needed. The Vaettir nginx proxy passes requests through with the correct headers, and Streamlit validates the origin against this list.
Development CORS
For local development via ngrok, the set_streamlit_env.py script auto-generates allowed origins.
Configuration
Edit .env:
NGROK_DOMAIN=your-dev-tunnel.ngrok-free.app
STREAMLIT_PORT=8502
# Optional: additional origins
# STREAMLIT_CUSTOM_ORIGINS=https://custom.com
Usage
# Option A: Convenience script
./scripts/run_streamlit.sh
# Option B: Manual
eval $(python scripts/set_streamlit_env.py)
streamlit run app/front.py
Generated Origins
The script builds the origin list from:
| Source | Origin | When |
|---|---|---|
| Always | http://localhost:{STREAMLIT_PORT} | Always |
| Always | http://127.0.0.1:{STREAMLIT_PORT} | Always |
.env | https://{NGROK_DOMAIN} | If NGROK_DOMAIN is set |
| Hardcoded | https://ocapistaine-dev.vaettir.locki.io | Always (dev proxy) |
| Hardcoded | https://ocapistaine.vaettir.locki.io | Always (production proxy) |
| Hardcoded | https://vaettir.locki.io | Always |
.env | Custom origins | If STREAMLIT_CUSTOM_ORIGINS is set |
Verification
python scripts/set_streamlit_env.py
# Output shows all configured origins
echo $STREAMLIT_SERVER_ALLOWED_ORIGINS
# Comma-separated list
Environment Variables
Streamlit CORS Variables
| Variable | Description | Set By |
|---|---|---|
STREAMLIT_SERVER_ENABLE_CORS | Enable CORS checking | render.yaml / script |
STREAMLIT_SERVER_ENABLE_XSRF_PROTECTION | XSRF protection (disabled behind proxy) | render.yaml / script |
STREAMLIT_SERVER_ALLOWED_ORIGINS | Comma-separated allowed origins | render.yaml / script |
STREAMLIT_BROWSER_SERVER_ADDRESS | Public domain for browser | Optional |
STREAMLIT_BROWSER_SERVER_PORT | Public port (443 for HTTPS) | Optional |
Input Variables
| Variable | Description | Example |
|---|---|---|
NGROK_DOMAIN | ngrok tunnel domain (no protocol) | my-tunnel.ngrok-free.app |
STREAMLIT_PORT | Local Streamlit port | 8502 |
STREAMLIT_CUSTOM_ORIGINS | Additional origins (comma-separated) | https://custom.com |
Troubleshooting
CORS Errors in Production
Check that render.yaml includes the requesting domain in STREAMLIT_SERVER_ALLOWED_ORIGINS. Redeploy after changes.
CORS Errors in Development
# Verify origins are set
echo $STREAMLIT_SERVER_ALLOWED_ORIGINS
# If empty, run the script
eval $(python scripts/set_streamlit_env.py)
# Quick test with wildcard
export STREAMLIT_SERVER_ALLOWED_ORIGINS="*"
streamlit run app/front.py
Origin Not in Allowed List
If the browser shows origin X not in allowed origins:
- Check the exact origin (including protocol and port)
- Add it to
STREAMLIT_CUSTOM_ORIGINSin.env(dev) orrender.yaml(prod)
Related
- Streamlit Setup - Full setup guide