8.7 KiB
Reverse Proxy Configuration
This guide helps you deploy Open Notebook behind a reverse proxy (nginx, Caddy, Traefik, etc.) or with a custom domain.
The API_URL Environment Variable
Starting with v1.0+, Open Notebook supports runtime configuration of the API URL through the API_URL environment variable. This means you can use the same Docker image in different deployment scenarios without rebuilding.
How It Works
The frontend uses a three-tier priority system to determine the API URL:
- Runtime Configuration (Highest Priority):
API_URLenvironment variable set at container runtime - Build-time Configuration:
NEXT_PUBLIC_API_URLbaked into the Docker image - Auto-detection (Fallback): Infers from the incoming HTTP request headers
Auto-detection details:
- The Next.js frontend analyzes the incoming HTTP request
- Extracts the hostname from the
hostheader - Respects the
X-Forwarded-Protoheader (for HTTPS behind reverse proxies) - Constructs the API URL as
{protocol}://{hostname}:5055 - Example: Request to
http://10.20.30.20:8502→ API URL becomeshttp://10.20.30.20:5055
Common Scenarios
Scenario 1: Docker on Localhost (Default)
No configuration needed! The system auto-detects.
docker run -d \
--name open-notebook \
-p 8502:8502 -p 5055:5055 \
-v ./notebook_data:/app/data \
-v ./surreal_data:/mydata \
lfnovo/open_notebook:v1-latest-single
Scenario 2: Docker on Remote Server (LAN/VPS)
Access via IP address - auto-detection works, but you can be explicit:
docker run -d \
--name open-notebook \
-p 8502:8502 -p 5055:5055 \
-e API_URL=http://192.168.1.100:5055 \
-v ./notebook_data:/app/data \
-v ./surreal_data:/mydata \
lfnovo/open_notebook:v1-latest-single
Note: Don't include
/apiat the end - the system adds this automatically!
Scenario 3: Behind Reverse Proxy with Custom Domain
This is where API_URL is essential. Your reverse proxy handles HTTPS and routing.
Important: If your reverse proxy forwards
/apirequests to the backend, setAPI_URLto just the domain (without/apisuffix). The frontend will append/apiautomatically.
Example: nginx + Docker Compose
docker-compose.yml:
version: '3.8'
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}
volumes:
- ./notebook_data:/app/data
- ./surreal_data:/mydata
ports:
- "8502:8502" # Frontend
- "5055:5055" # API
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
nginx.conf:
http {
upstream frontend {
server open-notebook:8502;
}
upstream api {
server open-notebook:5055;
}
server {
listen 80;
server_name notebook.example.com;
return 301 https://$server_name$request_uri;
}
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;
# Frontend
location / {
proxy_pass http://frontend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_cache_bypass $http_upgrade;
}
# API
location /api/ {
proxy_pass http://api/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;
}
}
}
Scenario 4: Behind Reverse Proxy with Subdomain
If you want API on a separate subdomain:
docker-compose.yml:
services:
open-notebook:
image: lfnovo/open_notebook:v1-latest-single
environment:
- API_URL=https://api.notebook.example.com
# ... other env vars
nginx.conf:
# Frontend server
server {
listen 443 ssl http2;
server_name notebook.example.com;
location / {
proxy_pass http://open-notebook:8502;
# ... proxy headers
}
}
# API server
server {
listen 443 ssl http2;
server_name api.notebook.example.com;
location / {
proxy_pass http://open-notebook:5055;
# ... proxy headers
}
}
Scenario 5: Traefik
docker-compose.yml:
version: '3.8'
services:
open-notebook:
image: lfnovo/open_notebook:v1-latest-single
environment:
- API_URL=https://notebook.example.com
labels:
# Frontend
- "traefik.enable=true"
- "traefik.http.routers.notebook-frontend.rule=Host(`notebook.example.com`)"
- "traefik.http.routers.notebook-frontend.entrypoints=websecure"
- "traefik.http.routers.notebook-frontend.tls.certresolver=myresolver"
- "traefik.http.services.notebook-frontend.loadbalancer.server.port=8502"
# API
- "traefik.http.routers.notebook-api.rule=Host(`notebook.example.com`) && PathPrefix(`/api`)"
- "traefik.http.routers.notebook-api.entrypoints=websecure"
- "traefik.http.routers.notebook-api.tls.certresolver=myresolver"
- "traefik.http.services.notebook-api.loadbalancer.server.port=5055"
networks:
- traefik-network
networks:
traefik-network:
external: true
Scenario 6: Caddy
Caddyfile:
notebook.example.com {
# Frontend
reverse_proxy / open-notebook:8502
# API
reverse_proxy /api/* open-notebook:5055
}
docker-compose.yml:
services:
open-notebook:
image: lfnovo/open_notebook:v1-latest-single
environment:
- API_URL=https://notebook.example.com
# No need to expose ports if using Caddy in same network
Troubleshooting
Connection Error: Unable to connect to server
Symptoms: Frontend displays "Unable to connect to server. Please check if the API is running."
Possible Causes:
-
API_URL not set correctly for your reverse proxy setup
- Check browser console (F12) for connection errors
- Look for logs showing what URL the frontend is trying
-
Reverse proxy not forwarding to correct port
- API should be accessible at the URL specified in
API_URL - Test:
curl https://your-domain.com/api/configshould return JSON
- API should be accessible at the URL specified in
-
CORS issues
- Ensure
X-Forwarded-ProtoandX-Forwarded-Forheaders are set in proxy config - Check API logs for CORS errors
- Ensure
-
SSL/TLS certificate issues
- Ensure your reverse proxy has valid SSL certificates
- Mixed content errors (HTTPS frontend trying to reach HTTP API)
How to Debug
-
Check browser console (F12 → Console tab):
- Look for messages starting with
🔧 [Config] - These show the configuration detection process
- You'll see which API URL is being used
- Look for messages starting with
-
Test API directly:
# Should return JSON config curl https://your-domain.com/api/config -
Check Docker logs:
docker logs open-notebook- Look for frontend and API startup messages
- Check for connection errors
-
Verify environment variable:
docker exec open-notebook env | grep API_URL
Missing Authorization Header
Symptoms: API returns {"detail": "Missing authorization header"}
This happens when:
- You have set
OPEN_NOTEBOOK_PASSWORDfor authentication - You're trying to access
/api/configdirectly without logging in first
Solution: This is expected behavior! The frontend handles this automatically. Just access the frontend URL and log in through the UI.
Best Practices
- Always use HTTPS in production with reverse proxies
- Set
API_URLexplicitly when using reverse proxies to avoid auto-detection issues - Use environment files (
.envordocker.env) to manage configuration - Test your setup by accessing the frontend and checking browser console logs
- Keep ports 5055 and 8502 accessible from your reverse proxy container