# How to Configure Password Authentication Middleware for Production in Open Notebook

> Secure your Open Notebook API in production by configuring password authentication middleware. Set environment variables or mount secrets to enforce secure bearer token access. Learn how to protect your API now.

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

---

**To secure the Open Notebook API in production, set the `OPEN_NOTEBOOK_PASSWORD` environment variable or mount a secret file to `OPEN_NOTEBOOK_PASSWORD_FILE`, then restart the service so the `PasswordAuthMiddleware` enforces `Authorization: Bearer <password>` on all incoming requests.**

Open Notebook uses a lightweight `PasswordAuthMiddleware` to protect its HTTP API from unauthorized access. While development mode allows unrestricted access when the password is unset, production deployments require explicit configuration of the `OPEN_NOTEBOOK_PASSWORD` environment variable. This guide explains how to configure password authentication middleware for production using the source code from the `lfnovo/open-notebook` repository.

## How the Password Authentication Middleware Works

The authentication layer is implemented in [`api/auth.py`](https://github.com/lfnovo/open-notebook/blob/main/api/auth.py) as `PasswordAuthMiddleware`, which is registered in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) at lines 73-86. The middleware intercepts every HTTP request and validates the `Authorization: Bearer <token>` header against a secret value retrieved via `get_secret_from_env` in [`open_notebook/utils/encryption.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/encryption.py) (lines 29-59).

This utility function first checks for a `<VAR>_FILE` pattern to support Docker Secrets and Kubernetes secret mounts, then falls back to plain environment variables. If the password is not configured, the middleware permits all requests, making it safe for local development but requiring explicit secrets for production.

## Production Configuration Steps

### Set the OPEN_NOTEBOOK_PASSWORD Environment Variable

Create a strong, random password and export it as an environment variable. This value is read once at process startup, so changes require a restart.

### Mount Secrets in Docker or Kubernetes

For containerized environments, use the `OPEN_NOTEBOOK_PASSWORD_FILE` variable to reference a mounted secret file rather than exposing the password in environment variables. This pattern supports Docker Swarm secrets and Kubernetes secrets mounted as volumes.

### Restart the API Service

The middleware reads the password during application initialization in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py). Any change to the secret requires restarting the container to reload the `PasswordAuthMiddleware` with the new credentials.

### Update Client Authorization Headers

Clients must include `Authorization: Bearer <password>` in all HTTP requests. The built-in [`api/client.py`](https://github.com/lfnovo/open-notebook/blob/main/api/client.py) automatically injects this header when `OPEN_NOTEBOOK_PASSWORD` is present in the environment.

## Production Deployment Examples

### Docker Compose with Secrets

Store the password as a Docker secret file to avoid exposing it in environment variables:

```yaml
services:
  api:
    image: lfnovo/open-notebook:latest
    env_file: .env.production
    secrets:
      - open_notebook_password
    ports:
      - "5055:5055"

secrets:
  open_notebook_password:
    file: ./secrets/open_notebook_password.txt

```

### Environment Configuration File

Reference the secret file in your `.env.production` or use a plain environment variable:

```dotenv

# Option 1: File-based secret (recommended for Docker/Kubernetes)

# OPEN_NOTEBOOK_PASSWORD_FILE is set automatically by Docker secret mount

# Option 2: Direct environment variable

# OPEN_NOTEBOOK_PASSWORD=SuperSecretProdPass

CORS_ORIGINS=https://notebook.example.com

```

### Python Client Authentication

The [`api/client.py`](https://github.com/lfnovo/open-notebook/blob/main/api/client.py) wrapper automatically adds the authorization header when the environment variable is set:

```python
import os
from api.client import OpenNotebookClient

# Ensure the password env var is visible to the process

os.environ["OPEN_NOTEBOOK_PASSWORD"] = "SuperSecretProdPass"

client = OpenNotebookClient(base_url="https://api.example.com")

# All subsequent calls will include:

#   Authorization: Bearer SuperSecretProdPass

```

### FastAPI Route Protection

For fine-grained control within specific routes, use the optional dependency from [`api/auth.py`](https://github.com/lfnovo/open-notebook/blob/main/api/auth.py):

```python
from fastapi import APIRouter, Depends, HTTPException
from api.auth import check_api_password

router = APIRouter()

@router.get("/admin/status")
async def admin_status(auth_ok: bool = Depends(check_api_password)):
    if not auth_ok:
        raise HTTPException(status_code=401, detail="Unauthorized")
    return {"msg": "All systems nominal"}

```

## Security Architecture and Middleware Ordering

The `app.add_middleware(PasswordAuthMiddleware, ...)` call in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) places authentication before CORS middleware processing. This architectural choice ensures that unauthenticated requests are rejected prior to any CORS handling, preventing information leakage through preflight responses and ensuring that only authenticated traffic reaches your business logic.

The middleware configuration excludes specific public paths—including health check endpoints, OpenAPI documentation, and internal status routes—allowing monitoring tools and API discovery to remain accessible without credentials while protecting sensitive operations.

## Summary

- **Set `OPEN_NOTEBOOK_PASSWORD`** or `OPEN_NOTEBOOK_PASSWORD_FILE` to enable production protection
- **Configure secrets via Docker or Kubernetes** for secure credential management compatible with `get_secret_from_env`
- **Restart the API** after changing passwords to reload the middleware initialized in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py)
- **Include `Authorization: Bearer <password>` headers** in client requests, or use [`api/client.py`](https://github.com/lfnovo/open-notebook/blob/main/api/client.py) for automatic handling
- **Public endpoints remain accessible** for health checks and documentation as configured in the middleware exclusions

## Frequently Asked Questions

### What happens if OPEN_NOTEBOOK_PASSWORD is not set?

According to the source code in [`open_notebook/utils/encryption.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/encryption.py), the middleware falls back to a "no password" mode that permits all requests. This configuration is only safe for development environments and leaves production deployments vulnerable to unauthorized access.

### How do I rotate the password in a running container?

Password changes require a container restart because `get_secret_from_env` is called once during middleware initialization in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) (lines 73-86). Update the secret file or environment variable, then restart the process to load the new value into `PasswordAuthMiddleware`.

### Which endpoints bypass password authentication?

The middleware configuration in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) excludes specific public paths including health check endpoints, OpenAPI schema documents, and Swagger UI routes. This allows monitoring tools and API documentation to remain accessible without credentials while protecting business logic routes.

### Can I use Kubernetes secrets with this middleware?

Yes. Mount your Kubernetes secret as a file in the container and set `OPEN_NOTEBOOK_PASSWORD_FILE` to the mount path. The utility function in [`open_notebook/utils/encryption.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/encryption.py) (lines 29-59) automatically detects the `_FILE` suffix and reads the file-based secret, making it compatible with Kubernetes secret volumes.