open-notebook/docs/5-CONFIGURATION/reverse-proxy.md
LUIS NOVO e13e4a2d8b docs: restructure documentation with new organized layout
- Replace old docs structure with new comprehensive documentation
- Organize into 8 major sections (0-START-HERE through 7-DEVELOPMENT)
- Convert CONFIGURATION.md, CONTRIBUTING.md, MAINTAINER_GUIDE.md to redirects
- Remove outdated MIGRATION.md and DESIGN_PRINCIPLES.md
- Fix all internal documentation links and cross-references
- Add progressive disclosure paths for different user types
- Include 44 focused guides covering all features
- Update README.md to remove v1.0 breaking changes notice
2026-01-03 20:10:24 -03:00

327 lines
7.7 KiB
Markdown

# Reverse Proxy Configuration
Deploy Open Notebook behind nginx, Caddy, Traefik, or other reverse proxies with custom domains and HTTPS.
---
## Simplified Setup (v1.1+)
Starting with v1.1, Open Notebook uses Next.js rewrites to simplify configuration. **You only need to proxy to one port** - Next.js handles internal API routing automatically.
### How It Works
```
Browser → Reverse Proxy → Port 8502 (Next.js)
↓ (internal proxy)
Port 5055 (FastAPI)
```
Next.js automatically forwards `/api/*` requests to the FastAPI backend, so your reverse proxy only needs one port!
---
## Quick Configuration Examples
### Nginx (Recommended)
```nginx
server {
listen 443 ssl http2;
server_name notebook.example.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
# Single location block - that's it!
location / {
proxy_pass http://open-notebook:8502;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
}
# HTTP to HTTPS redirect
server {
listen 80;
server_name notebook.example.com;
return 301 https://$server_name$request_uri;
}
```
### Caddy
```caddy
notebook.example.com {
reverse_proxy open-notebook:8502
}
```
That's it! Caddy handles HTTPS automatically.
### Traefik
```yaml
services:
open-notebook:
image: lfnovo/open_notebook:v1-latest-single
environment:
- API_URL=https://notebook.example.com
labels:
- "traefik.enable=true"
- "traefik.http.routers.notebook.rule=Host(`notebook.example.com`)"
- "traefik.http.routers.notebook.entrypoints=websecure"
- "traefik.http.routers.notebook.tls.certresolver=myresolver"
- "traefik.http.services.notebook.loadbalancer.server.port=8502"
networks:
- traefik-network
```
### Coolify
1. Create new service with `lfnovo/open_notebook:v1-latest-single`
2. Set port to **8502**
3. Add environment: `API_URL=https://your-domain.com`
4. Enable HTTPS in Coolify
5. Done!
---
## Environment Variables
```bash
# Required for reverse proxy setups
API_URL=https://your-domain.com
# Optional: For multi-container deployments
# INTERNAL_API_URL=http://api-service:5055
```
**Important**: Set `API_URL` to your public URL (with https://).
---
## Complete Docker Compose Example
```yaml
services:
open-notebook:
image: lfnovo/open_notebook:v1-latest-single
container_name: open-notebook
environment:
- API_URL=https://notebook.example.com
- OPENAI_API_KEY=${OPENAI_API_KEY}
- OPEN_NOTEBOOK_PASSWORD=${OPEN_NOTEBOOK_PASSWORD}
volumes:
- ./notebook_data:/app/data
- ./surreal_data:/mydata
# Only expose to localhost (nginx handles public access)
ports:
- "127.0.0.1:8502:8502"
restart: unless-stopped
nginx:
image: nginx:alpine
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- open-notebook
restart: unless-stopped
```
---
## Full Nginx Configuration
```nginx
events {
worker_connections 1024;
}
http {
upstream notebook {
server open-notebook:8502;
}
# HTTP redirect
server {
listen 80;
server_name notebook.example.com;
return 301 https://$server_name$request_uri;
}
# HTTPS server
server {
listen 443 ssl http2;
server_name notebook.example.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
# Proxy settings
location / {
proxy_pass http://notebook;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
# Timeouts for long-running operations (podcasts, etc.)
proxy_read_timeout 300s;
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
}
}
}
```
---
## Direct API Access (Optional)
If external scripts or integrations need direct API access, route `/api/*` directly:
```nginx
# Direct API access (for external integrations)
location /api/ {
proxy_pass http://open-notebook:5055/api/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Frontend (handles all other traffic)
location / {
proxy_pass http://open-notebook:8502;
# ... same headers as above
}
```
**Note**: This is only needed for external API integrations. Browser traffic works fine with single-port setup.
---
## SSL Certificates
### Let's Encrypt with Certbot
```bash
# Install certbot
sudo apt install certbot python3-certbot-nginx
# Get certificate
sudo certbot --nginx -d notebook.example.com
# Auto-renewal (usually configured automatically)
sudo certbot renew --dry-run
```
### Let's Encrypt with Caddy
Caddy handles SSL automatically - no configuration needed!
### Self-Signed (Development Only)
```bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout ssl/privkey.pem \
-out ssl/fullchain.pem \
-subj "/CN=localhost"
```
---
## Troubleshooting
### "Unable to connect to server"
1. **Check API_URL is set**:
```bash
docker exec open-notebook env | grep API_URL
```
2. **Verify reverse proxy reaches container**:
```bash
curl -I http://localhost:8502
```
3. **Check browser console** (F12):
- Look for connection errors
- Check what URL it's trying to reach
### Mixed Content Errors
Frontend using HTTPS but trying to reach HTTP API:
```bash
# Ensure API_URL uses https://
API_URL=https://notebook.example.com # Not http://
```
### WebSocket Issues
Ensure your proxy supports WebSocket upgrades:
```nginx
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
```
### 502 Bad Gateway
1. Check container is running: `docker ps`
2. Check container logs: `docker logs open-notebook`
3. Verify nginx can reach container (same network)
### Timeout Errors
Increase timeouts for long operations (podcast generation):
```nginx
proxy_read_timeout 300s;
proxy_send_timeout 300s;
```
---
## Best Practices
1. **Always use HTTPS** in production
2. **Set API_URL explicitly** when using reverse proxies
3. **Bind to localhost** (`127.0.0.1:8502`) and let proxy handle public access
4. **Enable security headers** (HSTS, X-Frame-Options, etc.)
5. **Set up certificate renewal** for Let's Encrypt
6. **Test your configuration** before going live
---
## Related
- **[Security Configuration](security.md)** - Password protection and hardening
- **[Server Configuration](server.md)** - Ports and API settings
- **[Troubleshooting](../6-TROUBLESHOOTING/connection-issues.md)** - Connection problems