# How to Configure CORS for Production Deployments in Open Notebook

> Secure your Open Notebook production deployment by configuring CORS. Set CORS_ORIGINS to your frontend domains to prevent cross-origin attacks and security warnings.

- Repository: [Luis Novo/open-notebook](https://github.com/lfnovo/open-notebook)
- Tags: how-to-guide
- Published: 2026-06-29

---

**Set the `CORS_ORIGINS` environment variable to a comma-separated list of your frontend domains (e.g., `https://app.example.com`) before starting the API; if unset, Open Notebook defaults to allowing all origins (`*`), which triggers a security warning at startup and leaves your production deployment vulnerable to cross-origin attacks.**

Open Notebook is an open-source knowledge management platform built on FastAPI. Properly configuring CORS for production deployments ensures that only your trusted frontend domains can communicate with the API, preventing unauthorized cross-origin requests while maintaining seamless browser interactions.

## Understanding CORS in Open Notebook

Open Notebook's API layer, defined in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py), implements cross-origin resource sharing through FastAPI's `CORSMiddleware`. The system uses the `CORS_ORIGINS` environment variable to determine which domains may access API resources from browser contexts.

### The CORS_ORIGINS Environment Variable

The application parses `CORS_ORIGINS` using the internal `_parse_cors_origins` function, which converts comma-separated origin strings into a Python list. This list is injected directly into FastAPI's `CORSMiddleware` as the `allow_origins` parameter. The same origin list is referenced by the custom `_cors_headers` error handler, ensuring that CORS policy is enforced even on API error responses.

### Default Behavior and Security Warnings

When `CORS_ORIGINS` is unset, the API defaults to `allow_origins=["*"]`, permitting requests from any domain. During startup (typically around lines 63-70 in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py)), the application logs a warning reminding administrators to configure explicit origins for production use. According to the project's security documentation in [`docs/5-CONFIGURATION/security.md`](https://github.com/lfnovo/open-notebook/blob/main/docs/5-CONFIGURATION/security.md), this permissive default is intended only for local development.

## Configuring CORS for Production

To secure your deployment, restrict CORS to only the specific origins hosting your frontend applications.

### 1. Identify Your Frontend Origins

Determine the exact HTTPS origins of your production frontend(s), including protocol and domain. For example: `https://app.example.com` or `https://notebook.example.com`.

### 2. Set the CORS_ORIGINS Variable

Export the environment variable as a comma-separated list without spaces:

```bash
export CORS_ORIGINS="https://app.example.com,https://admin.example.com"

```

The API reads this value only at process startup, so the variable must be present before the server initializes.

### 3. Restart the API Service

Restart your Open Notebook instance to load the new CORS configuration. The API will now:

- Reflect the `Access-Control-Allow-Origin` header only for requests from listed origins
- Omit the header entirely for requests from unauthorized domains
- Apply these restrictions consistently across both successful responses and error states

## Production Deployment Examples

### Docker Compose Configuration

When deploying via Docker Compose, set `CORS_ORIGINS` in the environment section of your service definition:

```yaml
services:
  open_notebook:
    image: lfnovo/open_notebook:v1-latest
    ports:
      - "8502:8502"
      - "5055:5055"
    environment:
      - OPEN_NOTEBOOK_ENCRYPTION_KEY=change-me-to-a-secret-string
      - CORS_ORIGINS=https://app.example.com,https://admin.example.com
      - SURREAL_URL=ws://surrealdb:8000/rpc
      - SURREAL_USER=root
      - SURREAL_PASSWORD=root
      - SURREAL_NAMESPACE=open_notebook
      - SURREAL_DATABASE=open_notebook

```

### Standalone Uvicorn Deployment

For manual deployments using Uvicorn:

```bash
export CORS_ORIGINS="https://app.example.com"
uvicorn api.main:app --host 0.0.0.0 --port 5055

```

### Verifying CORS Configuration with curl

Test that unauthorized origins are blocked while permitted origins receive proper headers:

```bash

# Request from authorized origin - should include CORS header

curl -i -H "Origin: https://app.example.com" http://localhost:5055/health

# Expected: Access-Control-Allow-Origin: https://app.example.com

# Request from unauthorized origin - should omit CORS header

curl -i -H "Origin: https://malicious.com" http://localhost:5055/health

# Expected: No Access-Control-Allow-Origin header

```

## Summary

- Open Notebook's CORS policy is controlled by the **`CORS_ORIGINS`** environment variable, parsed at startup in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py).
- The default value of `*` (allow all origins) triggers a security warning and is unsafe for production use.
- Set `CORS_ORIGINS` to a comma-separated list of your frontend domains before starting the API.
- The configuration applies to both successful API responses and error responses via the `_cors_headers` handler.
- Changes require a process restart to take effect.

## Frequently Asked Questions

### What happens if I don't set CORS_ORIGINS in production?

If `CORS_ORIGINS` is unset, Open Notebook defaults to allowing all origins (`*`), which exposes your API to cross-origin requests from any domain. The application logs a warning at startup (visible in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) around lines 63-70) alerting you that the permissive default should not be used in production environments.

### How do I configure multiple allowed origins?

Set `CORS_ORIGINS` to a comma-separated list without spaces: `https://app.example.com,https://admin.example.com`. The internal `_parse_cors_origins` function in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) splits this string into a list that FastAPI's `CORSMiddleware` uses to validate incoming requests.

### Why are CORS headers missing from error responses?

If you see CORS headers on successful requests but not on errors, ensure `CORS_ORIGINS` is properly set. Open Notebook implements a custom `_cors_headers` error handler that consults the same origin list used by the middleware; when the origin is not in the allowed list, the header is intentionally omitted to prevent information leakage across origins.

### Does the CORS configuration require an API restart?

Yes. The `CORS_ORIGINS` value is read only once during process initialization in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py). Any changes to the environment variable require restarting the Open Notebook API service to take effect.