423 lines
10 KiB
Markdown
423 lines
10 KiB
Markdown
|
|
# 🔧 Environment Variables
|
||
|
|
|
||
|
|
NoteDiscovery supports environment variables to override configuration settings, allowing different behavior in different deployment environments (local, staging, production).
|
||
|
|
|
||
|
|
## 📋 Available Environment Variables
|
||
|
|
|
||
|
|
### Core Settings
|
||
|
|
|
||
|
|
| Variable | Type | Default | Description |
|
||
|
|
|----------|------|---------|-------------|
|
||
|
|
| `PORT` | integer | `8000` | HTTP port for the application (Docker, run.py) |
|
||
|
|
|
||
|
|
> **Note**: Advanced server settings (CORS origins, debug mode) are configured via `config.yaml` only, not via environment variables. See [config.yaml](#advanced-server-configuration) for details.
|
||
|
|
|
||
|
|
### Authentication
|
||
|
|
|
||
|
|
| Variable | Type | Default | Description |
|
||
|
|
|----------|------|---------|-------------|
|
||
|
|
| `AUTHENTICATION_ENABLED` | boolean | `config.yaml` | Enable/disable authentication |
|
||
|
|
| `AUTHENTICATION_PASSWORD_HASH` | string | `config.yaml` | Bcrypt password hash |
|
||
|
|
| `AUTHENTICATION_SECRET_KEY` | string | `config.yaml` | Session secret key (for session security) |
|
||
|
|
|
||
|
|
### Demo Mode
|
||
|
|
|
||
|
|
| Variable | Type | Default | Description |
|
||
|
|
|----------|------|---------|-------------|
|
||
|
|
| `DEMO_MODE` | boolean | `false` | Enable demo mode (enables rate limiting and other demo restrictions) |
|
||
|
|
|
||
|
|
## 🎯 Configuration Priority
|
||
|
|
|
||
|
|
Configuration is loaded in this order (later overrides earlier):
|
||
|
|
|
||
|
|
1. **`config.yaml`** - Default configuration file
|
||
|
|
2. **Environment Variables** - Runtime overrides
|
||
|
|
3. **Command Line** - Highest priority (if applicable)
|
||
|
|
|
||
|
|
## 💡 Common Use Cases
|
||
|
|
|
||
|
|
### Use Case 1: Local Development (No Auth)
|
||
|
|
|
||
|
|
**Local setup:**
|
||
|
|
```bash
|
||
|
|
# No environment variables needed
|
||
|
|
# Uses config.yaml defaults (auth disabled)
|
||
|
|
python run.py
|
||
|
|
```
|
||
|
|
|
||
|
|
**`config.yaml`:**
|
||
|
|
```yaml
|
||
|
|
authentication:
|
||
|
|
enabled: false
|
||
|
|
```
|
||
|
|
|
||
|
|
**Result:** ✅ No authentication, quick local testing
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Use Case 2: Public Demo (Auth + Rate Limiting)
|
||
|
|
|
||
|
|
**Render deployment:**
|
||
|
|
```yaml
|
||
|
|
# render.yaml
|
||
|
|
envVars:
|
||
|
|
- key: DEMO_MODE
|
||
|
|
value: "true"
|
||
|
|
- key: AUTHENTICATION_ENABLED
|
||
|
|
value: "true"
|
||
|
|
```
|
||
|
|
|
||
|
|
**`config.yaml`:**
|
||
|
|
```yaml
|
||
|
|
authentication:
|
||
|
|
enabled: false # Overridden by AUTHENTICATION_ENABLED=true
|
||
|
|
```
|
||
|
|
|
||
|
|
**Result:** ✅ Demo mode enabled (rate limiting + restrictions), authentication enabled
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Use Case 3: Private Demo (Custom Password & Secret Key)
|
||
|
|
|
||
|
|
**Generate password hash and secret key:**
|
||
|
|
```bash
|
||
|
|
# Generate password hash
|
||
|
|
python generate_password.py
|
||
|
|
# Enter password: mysecurepassword
|
||
|
|
# Generated hash: $2b$12$...
|
||
|
|
|
||
|
|
# Generate secret key
|
||
|
|
python -c "import secrets; print(secrets.token_hex(32))"
|
||
|
|
# Generated key: a1b2c3d4e5f6...
|
||
|
|
```
|
||
|
|
|
||
|
|
**Render deployment:**
|
||
|
|
```yaml
|
||
|
|
envVars:
|
||
|
|
- key: AUTHENTICATION_ENABLED
|
||
|
|
value: "true"
|
||
|
|
- key: AUTHENTICATION_PASSWORD_HASH
|
||
|
|
value: "$2b$12$..." # Your generated hash
|
||
|
|
- key: AUTHENTICATION_SECRET_KEY
|
||
|
|
value: "a1b2c3d4e5f6..." # Your generated key
|
||
|
|
```
|
||
|
|
|
||
|
|
**Result:** ✅ Custom password and secure session key for production demo
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Use Case 4: Docker Compose (Local Development)
|
||
|
|
|
||
|
|
**`docker-compose.yml`:**
|
||
|
|
```yaml
|
||
|
|
services:
|
||
|
|
notediscovery:
|
||
|
|
image: ghcr.io/gamosoft/notediscovery:latest
|
||
|
|
ports:
|
||
|
|
- "8000:8000"
|
||
|
|
environment:
|
||
|
|
- AUTHENTICATION_ENABLED=false
|
||
|
|
- DEMO_MODE=false
|
||
|
|
volumes:
|
||
|
|
- ./data:/app/data
|
||
|
|
```
|
||
|
|
|
||
|
|
**Result:** ✅ Local deployment without restrictions (no auth, no rate limiting)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Use Case 5: Custom Port
|
||
|
|
|
||
|
|
**Run on port 3000 instead of 8000:**
|
||
|
|
|
||
|
|
**Local (run.py):**
|
||
|
|
```bash
|
||
|
|
PORT=3000 python run.py
|
||
|
|
# → Runs on http://localhost:3000
|
||
|
|
```
|
||
|
|
|
||
|
|
**Docker:**
|
||
|
|
```bash
|
||
|
|
docker run -p 3000:3000 -e PORT=3000 ghcr.io/gamosoft/notediscovery:latest
|
||
|
|
```
|
||
|
|
|
||
|
|
**Docker Compose:**
|
||
|
|
```yaml
|
||
|
|
services:
|
||
|
|
notediscovery:
|
||
|
|
image: ghcr.io/gamosoft/notediscovery:latest
|
||
|
|
ports:
|
||
|
|
- "3000:3000" # Host:Container
|
||
|
|
environment:
|
||
|
|
- PORT=3000
|
||
|
|
```
|
||
|
|
|
||
|
|
**Result:** ✅ App runs on custom port
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 🔐 Authentication Examples
|
||
|
|
|
||
|
|
### Example 1: Enable Auth via Environment
|
||
|
|
|
||
|
|
**Without environment variables:**
|
||
|
|
```bash
|
||
|
|
# Uses config.yaml defaults
|
||
|
|
🔐 Authentication DISABLED (from config.yaml)
|
||
|
|
✅ Production mode - Rate limiting disabled
|
||
|
|
```
|
||
|
|
|
||
|
|
**With environment variables (demo mode):**
|
||
|
|
```bash
|
||
|
|
export DEMO_MODE=true
|
||
|
|
export AUTHENTICATION_ENABLED=true
|
||
|
|
python run.py
|
||
|
|
|
||
|
|
# Output:
|
||
|
|
🎭 DEMO MODE enabled - Rate limiting active
|
||
|
|
🔐 Authentication ENABLED (from AUTHENTICATION_ENABLED env var)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Example 2: Demo Deployment
|
||
|
|
|
||
|
|
**Public demo with restrictions:**
|
||
|
|
```bash
|
||
|
|
export DEMO_MODE=true
|
||
|
|
export AUTHENTICATION_ENABLED=true
|
||
|
|
export AUTHENTICATION_PASSWORD_HASH='$2b$12$custom_hash'
|
||
|
|
export AUTHENTICATION_SECRET_KEY='your_random_secret_key'
|
||
|
|
python run.py
|
||
|
|
|
||
|
|
# Output:
|
||
|
|
🎭 DEMO MODE enabled - Rate limiting active
|
||
|
|
🔐 Authentication ENABLED (from AUTHENTICATION_ENABLED env var)
|
||
|
|
🔑 Password hash loaded from AUTHENTICATION_PASSWORD_HASH env var
|
||
|
|
🔐 Secret key loaded from AUTHENTICATION_SECRET_KEY env var
|
||
|
|
```
|
||
|
|
|
||
|
|
**Private instance (no restrictions):**
|
||
|
|
```bash
|
||
|
|
# No environment variables needed
|
||
|
|
python run.py
|
||
|
|
|
||
|
|
# Output:
|
||
|
|
✅ Production mode - Rate limiting disabled
|
||
|
|
🔐 Authentication DISABLED (from config.yaml)
|
||
|
|
```
|
||
|
|
|
||
|
|
## 📝 Boolean Values
|
||
|
|
|
||
|
|
Environment variables accept multiple formats for boolean values:
|
||
|
|
|
||
|
|
**True values:**
|
||
|
|
- `true`, `True`, `TRUE`
|
||
|
|
- `1`
|
||
|
|
- `yes`, `Yes`, `YES`
|
||
|
|
|
||
|
|
**False values:**
|
||
|
|
- `false`, `False`, `FALSE`
|
||
|
|
- `0`
|
||
|
|
- `no`, `No`, `NO`
|
||
|
|
- Not set (uses config.yaml default)
|
||
|
|
|
||
|
|
**Examples:**
|
||
|
|
```bash
|
||
|
|
AUTHENTICATION_ENABLED=true # ✅ Enabled
|
||
|
|
AUTHENTICATION_ENABLED=1 # ✅ Enabled
|
||
|
|
AUTHENTICATION_ENABLED=yes # ✅ Enabled
|
||
|
|
AUTHENTICATION_ENABLED=false # ❌ Disabled
|
||
|
|
AUTHENTICATION_ENABLED=0 # ❌ Disabled
|
||
|
|
# Not set # Uses config.yaml
|
||
|
|
```
|
||
|
|
|
||
|
|
## 🚀 Deployment Scenarios
|
||
|
|
|
||
|
|
### Scenario 1: Same Codebase, Different Environments
|
||
|
|
|
||
|
|
**Repository structure:**
|
||
|
|
```
|
||
|
|
config.yaml # Default: auth disabled (for local dev)
|
||
|
|
render.yaml # Render: AUTHENTICATION_ENABLED=true
|
||
|
|
docker-compose.yml # Docker: AUTHENTICATION_ENABLED=false (or not set)
|
||
|
|
```
|
||
|
|
|
||
|
|
**Benefits:**
|
||
|
|
- ✅ Single codebase
|
||
|
|
- ✅ No code changes between environments
|
||
|
|
- ✅ Environment-specific security
|
||
|
|
|
||
|
|
### Scenario 2: Team Collaboration
|
||
|
|
|
||
|
|
**Team workflow:**
|
||
|
|
```bash
|
||
|
|
# Developer 1 (local, no auth)
|
||
|
|
git clone repo
|
||
|
|
python run.py
|
||
|
|
# → No auth needed for local testing
|
||
|
|
|
||
|
|
# Developer 2 (local, testing auth)
|
||
|
|
AUTHENTICATION_ENABLED=true python run.py
|
||
|
|
# → Tests authentication locally
|
||
|
|
|
||
|
|
# Production (Render)
|
||
|
|
# → AUTHENTICATION_ENABLED=true in render.yaml
|
||
|
|
# → Always requires authentication
|
||
|
|
```
|
||
|
|
|
||
|
|
### Scenario 3: CI/CD Pipeline
|
||
|
|
|
||
|
|
**GitHub Actions:**
|
||
|
|
```yaml
|
||
|
|
- name: Test with auth disabled
|
||
|
|
run: |
|
||
|
|
export AUTHENTICATION_ENABLED=false
|
||
|
|
pytest tests/
|
||
|
|
|
||
|
|
- name: Test with auth enabled
|
||
|
|
run: |
|
||
|
|
export AUTHENTICATION_ENABLED=true
|
||
|
|
pytest tests/auth/
|
||
|
|
```
|
||
|
|
|
||
|
|
## 🔍 Checking Current Configuration
|
||
|
|
|
||
|
|
The application prints its configuration on startup:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
python run.py
|
||
|
|
|
||
|
|
# Output:
|
||
|
|
🎭 DEMO MODE enabled - Rate limiting active
|
||
|
|
🔐 Authentication ENABLED (from AUTHENTICATION_ENABLED env var)
|
||
|
|
🔑 Password hash loaded from AUTHENTICATION_PASSWORD_HASH env var
|
||
|
|
🔐 Secret key loaded from AUTHENTICATION_SECRET_KEY env var
|
||
|
|
```
|
||
|
|
|
||
|
|
## ⚙️ Advanced: All Environment Variables
|
||
|
|
|
||
|
|
**Full demo deployment example:**
|
||
|
|
```bash
|
||
|
|
export PORT=8080
|
||
|
|
export DEMO_MODE=true
|
||
|
|
export AUTHENTICATION_ENABLED=true
|
||
|
|
export AUTHENTICATION_PASSWORD_HASH='$2b$12$...'
|
||
|
|
export AUTHENTICATION_SECRET_KEY='your_random_secret_key_here'
|
||
|
|
|
||
|
|
python run.py
|
||
|
|
```
|
||
|
|
|
||
|
|
**Docker example:**
|
||
|
|
```dockerfile
|
||
|
|
ENV PORT=8000
|
||
|
|
ENV DEMO_MODE=true
|
||
|
|
ENV AUTHENTICATION_ENABLED=true
|
||
|
|
ENV AUTHENTICATION_PASSWORD_HASH='$2b$12$...'
|
||
|
|
ENV AUTHENTICATION_SECRET_KEY='your_random_secret_key_here'
|
||
|
|
```
|
||
|
|
|
||
|
|
## 📊 Quick Reference Table
|
||
|
|
|
||
|
|
| Scenario | `DEMO_MODE` | `AUTHENTICATION_ENABLED` | Behavior |
|
||
|
|
|----------|-------------|---------------|----------|
|
||
|
|
| **Local Dev** | Not set | Not set | No restrictions, quick testing |
|
||
|
|
| **Local Auth Testing** | Not set | `true` | Auth only, no rate limits |
|
||
|
|
| **Public Demo** | `true` | `true` | Full restrictions + auth |
|
||
|
|
| **Private Instance** | Not set | `true` | Auth only, self-hosted |
|
||
|
|
| **Read-Only Demo** | `true` | Not set | Rate limited, no auth |
|
||
|
|
|
||
|
|
## 🆘 Troubleshooting
|
||
|
|
|
||
|
|
### "Authentication not working"
|
||
|
|
|
||
|
|
**Check startup logs:**
|
||
|
|
```
|
||
|
|
🔐 Authentication DISABLED (from config.yaml)
|
||
|
|
```
|
||
|
|
|
||
|
|
**Fix:** Set environment variable
|
||
|
|
```bash
|
||
|
|
export AUTHENTICATION_ENABLED=true
|
||
|
|
```
|
||
|
|
|
||
|
|
### "Wrong password accepted"
|
||
|
|
|
||
|
|
**Check if password hash is loaded:**
|
||
|
|
```
|
||
|
|
🔑 Password hash loaded from AUTHENTICATION_PASSWORD_HASH env var
|
||
|
|
```
|
||
|
|
|
||
|
|
**If not shown:** Environment variable not set, using `config.yaml`
|
||
|
|
|
||
|
|
### "Can't disable auth in Render"
|
||
|
|
|
||
|
|
**Option 1:** Remove from `render.yaml`
|
||
|
|
```yaml
|
||
|
|
# Remove or comment out:
|
||
|
|
# - key: AUTHENTICATION_ENABLED
|
||
|
|
# value: "true"
|
||
|
|
```
|
||
|
|
|
||
|
|
**Option 2:** Explicitly disable
|
||
|
|
```yaml
|
||
|
|
- key: AUTHENTICATION_ENABLED
|
||
|
|
value: "false"
|
||
|
|
```
|
||
|
|
|
||
|
|
## 🔧 Advanced Server Configuration
|
||
|
|
|
||
|
|
The following settings are available in `config.yaml` only (not via environment variables):
|
||
|
|
|
||
|
|
### CORS (Cross-Origin Resource Sharing)
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
server:
|
||
|
|
# List of allowed origins for CORS
|
||
|
|
# Default: ["*"] allows all origins (fine for self-hosted)
|
||
|
|
# Production: specify your domains
|
||
|
|
allowed_origins: ["*"]
|
||
|
|
|
||
|
|
# Examples for production:
|
||
|
|
# allowed_origins: ["http://localhost:8000", "https://yourdomain.com"]
|
||
|
|
# allowed_origins: ["https://*.yourdomain.com"] # Wildcard subdomain
|
||
|
|
```
|
||
|
|
|
||
|
|
**Security Note:**
|
||
|
|
- `["*"]` is **safe for self-hosted** deployments on private networks
|
||
|
|
- For **public deployments**, specify exact origins to prevent unauthorized API access
|
||
|
|
- This prevents CSRF attacks when authentication is enabled
|
||
|
|
|
||
|
|
### Debug Mode
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
server:
|
||
|
|
# Enable detailed error messages in API responses
|
||
|
|
# Default: false (production-safe)
|
||
|
|
# Set to true for development/troubleshooting
|
||
|
|
debug: false
|
||
|
|
```
|
||
|
|
|
||
|
|
**⚠️ CRITICAL**: Never enable `debug: true` in production!
|
||
|
|
|
||
|
|
When `debug: true`:
|
||
|
|
- Full error stack traces are returned to users
|
||
|
|
- Internal paths and system details are exposed
|
||
|
|
- Security vulnerabilities may be revealed
|
||
|
|
|
||
|
|
When `debug: false` (recommended):
|
||
|
|
- Generic error messages are returned
|
||
|
|
- Full error details are logged server-side only
|
||
|
|
- Production-safe error handling
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 📚 Related Documentation
|
||
|
|
|
||
|
|
- **Authentication**: [AUTHENTICATION.md](AUTHENTICATION.md)
|
||
|
|
- **Render Deployment**: [DEPLOYMENT_RENDER.md](DEPLOYMENT_RENDER.md)
|
||
|
|
- **API Rate Limiting**: [API.md](API.md#rate-limiting)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Pro Tip:** Use environment variables for **deployment-specific** settings, and `config.yaml` for **application defaults**. This keeps your configuration flexible and maintainable! 🎯
|
||
|
|
|