How to Configure a Reverse Proxy for Production with Open Notebook
Expose only port 8502 through your TLS-terminating reverse proxy and set the API_URL environment variable to your public domain so Open Notebook correctly routes frontend and API traffic in production.
Open Notebook is a three-tier open-source application that requires careful proxy configuration before facing the public internet. Since version 1.1, the Next.js frontend automatically forwards /api/* requests to the FastAPI backend, which means you can configure a reverse proxy for production using a single upstream port. This guide walks through the exact responsibilities, headers, timeouts, and working examples derived from the lfnovo/open-notebook source code.
Architecture and Port Requirements
Open Notebook runs three services internally: a Next.js frontend on port 8502, a FastAPI backend on port 5055, and SurrealDB on port 8000. According to the lfnovo/open-notebook source code, the frontend—configured in frontend/next.config.ts—rewrites any request under /api/* to the backend service automatically. Because of this internal routing, a production reverse proxy only needs to expose port 8502 publicly; traffic to /api/* is proxied internally from the frontend container to the FastAPI entry point in api/main.py.
Reverse Proxy Responsibilities
A production reverse proxy sitting in front of Open Notebook should handle four specific jobs:
- Terminate TLS — Provide HTTPS for the public domain and offload encryption from the application containers.
- Forward traffic — Send all requests to
http://open-notebook:8502(or the equivalent container hostname and port). - Handle time-outs and large uploads — Set generous
proxy_*_timeoutandclient_max_body_sizevalues because operations like podcast generation can run for several minutes. - Set proper headers — Forward
Host,X-Forwarded-Proto,X-Real-IP, and related headers so the frontend can correctly auto-detect the public URL or use the explicitly setAPI_URLenvironment variable.
Production Configuration Examples
Nginx (Recommended)
The documentation in docs/5-CONFIGURATION/reverse-proxy.md provides a complete Nginx example that terminates TLS and forwards traffic to the Next.js frontend.
# /etc/nginx/nginx.conf (or a site-specific file)
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;
# Allow large file uploads (up to 100 MiB)
client_max_body_size 100M;
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;
# Long-running operations timeout (600 s)
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
}
# HTTP -> HTTPS redirect
server {
listen 80;
server_name notebook.example.com;
return 301 https://$server_name$request_uri;
}
Caddy (Automatic HTTPS)
Caddy handles certificate management automatically. The following Caddyfile targets port 8502 and extends read and write timeouts to accommodate long-running Open Notebook tasks.
notebook.example.com {
reverse_proxy open-notebook:8502 {
transport http {
read_timeout 600s
write_timeout 600s
}
}
}
Traefik (Docker-Compose Integration)
If you orchestrate containers with Docker Compose, Traefik labels can route public HTTPS traffic directly to the frontend without exposing additional host ports.
services:
open-notebook:
image: lfnovo/open_notebook:v1-latest
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"
- "traefik.http.services.notebook.loadbalancer.responseforwarding.flushinterval=100ms"
Docker Compose (Single-Service Setup)
For co-located deployments, bind the Open Notebook container to localhost and place Nginx on the public edge.
services:
open-notebook:
image: lfnovo/open_notebook:v1-latest
environment:
- API_URL=https://notebook.example.com
ports:
- "127.0.0.1:8502:8502" # Only expose to the reverse proxy
restart: unless-stopped
nginx:
image: nginx:alpine
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
Critical Environment Variables
API_URL
Set API_URL to the full public URL including the scheme, for example https://notebook.example.com. The Open Notebook frontend uses this value to build correct absolute API calls. Do not append /api to this variable because the system adds the path automatically when rewriting requests to the backend.
Summary
- Open Notebook exposes a single public port (
8502) in production because the Next.js frontend infrontend/next.config.tsinternally proxies/api/*traffic to the FastAPI backend. - Configure a reverse proxy for production by terminating TLS, setting generous time-outs, allowing large upload bodies, and forwarding
X-Forwarded-*headers. - Always define
API_URLas the public domain without/apiso the frontend generates valid absolute URLs. - Use Nginx, Caddy, or Traefik examples from
docs/5-CONFIGURATION/reverse-proxy.mddepending on your infrastructure preferences.
Frequently Asked Questions
Do I need to expose port 5055 or 8000 to the internet?
You should leave both the FastAPI backend on port 5055 and SurrealDB on port 8000 unexposed to the public internet. Since version 1.1, the Next.js frontend automatically proxies /api/* requests to the backend internally, which means your reverse proxy only needs to forward traffic to port 8502. Exposing the other ports directly introduces unnecessary security risk.
What happens if I do not set the API_URL environment variable?
The frontend relies on API_URL to build correct absolute API calls for public links and external resources. Without it, the application may generate broken URLs that point to internal hostnames instead of your public domain. Set it to the full scheme and domain, such as https://notebook.example.com, and do not append /api because the frontend rewrite logic handles that path automatically.
How do I handle long-running requests like podcast generation?
Operations like podcast generation can take several minutes, so your reverse proxy must tolerate slow responses. In Nginx, set proxy_read_timeout 600s and proxy_send_timeout 600s; in Caddy, configure read_timeout 600s and write_timeout 600s in the transport block. These values prevent the proxy from closing the connection before the FastAPI backend in api/main.py finishes processing.
Can I route /api/* directly to the backend instead of through the frontend?
This is only necessary if you want to expose the API directly for external integrations bypassing the frontend. In that advanced setup, route /api/* to port 5055 while sending all other traffic to port 8502. For standard deployments, proxying everything through port 8502 is simpler and fully supported by the rewrite rules in frontend/next.config.ts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →