How to Configure Docker Deployment and Reverse Proxy for Open Notebook
Open Notebook requires exposing only port 8502 through your reverse proxy, as the Next.js frontend automatically proxies /api/* requests to the FastAPI backend, but you must set the API_URL environment variable to ensure the UI generates correct HTTPS links.
Open Notebook is a self-hosted AI note-taking application that runs as a multi-container Docker stack. Starting with version 1.1, the architecture simplifies reverse proxy configuration by handling API routing internally between the frontend and backend containers. This guide explains how to deploy the complete stack using the official docker-compose.yml from the lfnovo/open-notebook repository and configure a production-ready reverse proxy for secure HTTPS access.
Architecture Overview
The application consists of three primary services defined in docker-compose.yml. The FastAPI back-end runs on port 5055, the Next.js front-end runs on port 8502, and SurrealDB operates on port 8000. From version 1.1 onward, the frontend automatically proxies all /api/* requests to the backend internally. This means your reverse proxy only needs to expose a single port (8502), significantly reducing the attack surface and simplifying SSL termination.
The containers communicate over an internal Docker network. The frontend handles internal routing to http://localhost:5055 for API calls, while external traffic flows through your reverse proxy to the frontend container.
Environment Configuration
Before deploying, create a .env file in your project directory by copying the template from .env.example. The following variables are required for secure operation:
OPEN_NOTEBOOK_ENCRYPTION_KEY– A secret string used for application-level encryption. Generate a strong random value (e.g., 32+ characters).SURREAL_USERandSURREAL_PASSWORD– Database credentials for SurrealDB authentication.
# .env
OPEN_NOTEBOOK_ENCRYPTION_KEY=your-secure-random-string-minimum-32-chars
SURREAL_USER=root
SURREAL_PASSWORD=secure-database-password
Never commit the .env file to version control. The docker-compose.yml references these variables to configure the Open Notebook and SurrealDB containers at runtime.
Docker Compose Deployment
Create a docker-compose.yml file that pulls the official images and wires the services together. The composition defines volume mounts for persistent data and establishes network dependencies between the database and application layers.
# docker-compose.yml
services:
surrealdb:
image: surrealdb/surrealdb:v2
command: start --log info --user ${SURREAL_USER:-root} --pass ${SURREAL_PASSWORD:-root} rocksdb:/mydata/mydatabase.db
ports: ["8000:8000"]
volumes: ["./surreal_data:/mydata"]
environment:
- SURREAL_EXPERIMENTAL_GRAPHQL=true
restart: always
open-notebook:
image: lfnovo/open_notebook:v1-latest
ports: ["127.0.0.1:8502:8502"] # Bind to localhost for reverse proxy only
environment:
- OPEN_NOTEBOOK_ENCRYPTION_KEY=${OPEN_NOTEBOOK_ENCRYPTION_KEY}
- API_URL=https://notebook.example.com # Critical for reverse proxy
- SURREAL_URL=ws://surrealdb:8000/rpc
- SURREAL_USER=${SURREAL_USER:-root}
- SURREAL_PASSWORD=${SURREAL_PASSWORD:-root}
- SURREAL_NAMESPACE=open_notebook
- SURREAL_DATABASE=open_notebook
volumes: ["./notebook_data:/app/data"]
depends_on: [surrealdb]
restart: always
Deploy the stack by running:
docker-compose up -d
The services will start on localhost:8502 (UI) and localhost:5055 (API), with SurrealDB available on localhost:8000. For integration with external Ollama instances, refer to the variant configuration in examples/docker-compose-ollama.yml.
Reverse Proxy Configuration
Your reverse proxy must forward all traffic to the Next.js container on port 8502. Since the frontend handles internal API routing, you do not need separate upstream definitions for the backend.
Nginx Configuration
Create an nginx.conf that includes WebSocket support for real-time features, generous timeouts for long-running AI operations (such as podcast generation), and sufficient client body size for file uploads.
# nginx.conf
events { worker_connections 1024; }
http {
upstream notebook {
server open-notebook:8502;
}
# HTTP to HTTPS 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;
# Support large file uploads (default 1MB is insufficient)
client_max_body_size 100M;
# 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";
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;
# Extended timeouts for AI generation tasks
proxy_read_timeout 600s;
proxy_connect_timeout 60s;
proxy_send_timeout 600s;
}
}
}
Add the nginx service to your docker-compose.yml:
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
Caddy Configuration
For automatic HTTPS with Let's Encrypt, use this minimal Caddyfile:
notebook.example.com {
reverse_proxy open-notebook:8502 {
transport http {
read_timeout 600s
write_timeout 600s
}
}
}
The full documentation in docs/5-CONFIGURATION/reverse-proxy.md also includes configuration examples for Traefik and other proxy solutions.
Critical API_URL Configuration
When running behind a reverse proxy, you must explicitly set the API_URL environment variable in the open-notebook service definition. This variable overrides automatic detection and ensures the frontend generates correct absolute URLs for API callbacks and OAuth redirects.
Set this to your public HTTPS domain:
environment:
- API_URL=https://notebook.example.com
Without this variable, the application may construct internal http:// links or localhost references, breaking authentication flows and external integrations. The container logs will confirm the runtime configuration with the message: ✅ [Config] Runtime API URL from server: https://notebook.example.com.
Verification and Health Checks
After deployment, verify the stack is functioning correctly:
- Browser validation – Navigate to
https://notebook.example.com. The browser console should show the runtime API URL matching your public domain. - API health check – Run
curl https://notebook.example.com/api/configto receive a JSON response containing"status":"ok". - Container logs – Execute
docker logs open-notebookto confirm both services initialized: "Next.js ready on http://0.0.0.0:8502" and "Uvicorn running on http://0.0.0.0:5055".
If the UI fails to load or shows connection errors, verify that the API_URL environment variable is set and that your reverse proxy headers include X-Forwarded-Proto.
Summary
- Expose only port 8502 – The Next.js frontend in versions 1.1+ handles internal proxying to the FastAPI backend, eliminating the need to expose port 5055 publicly.
- Set
API_URL– This environment variable is mandatory for reverse proxy deployments to ensure correct HTTPS URL generation. - Configure timeouts – Set
proxy_read_timeoutandproxy_send_timeoutto at least 600 seconds in your reverse proxy to accommodate long-running AI tasks. - Allow large uploads – Set
client_max_body_sizeto 100MB or higher in Nginx (or equivalent) to support file attachments. - Reference official docs – The
docs/5-CONFIGURATION/reverse-proxy.mdfile contains platform-specific examples for Nginx, Caddy, and Traefik.
Frequently Asked Questions
Do I need to expose the FastAPI backend (port 5055) through my reverse proxy?
No. Starting with version 1.1, the Next.js frontend automatically proxies all /api/* requests to the FastAPI backend internally. Configure your reverse proxy to forward traffic only to port 8502. The backend should remain accessible only within the Docker network for security.
Why is my Open Notebook UI generating HTTP links instead of HTTPS?
This occurs when the API_URL environment variable is not set or when your reverse proxy fails to forward the X-Forwarded-Proto header. Set API_URL=https://your-domain.com in the open-notebook service environment variables, and ensure your proxy passes X-Forwarded-Proto $scheme to the container.
How do I handle large file uploads through the reverse proxy?
File uploads in Open Notebook can exceed the default 1MB limit of most reverse proxies. In Nginx, set client_max_body_size 100M; in your server block. For Caddy, this is handled automatically, but you may need to adjust the read_timeout settings for slow connections during upload.
Can I deploy Open Notebook without SurrealDB?
No. SurrealDB is a required dependency for the application stack. The docker-compose.yml defines SurrealDB as a service dependency that must be running before the Open Notebook container starts. The database stores all user data, AI conversation history, and application configuration.
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 →