How Environment Variable Fallbacks Work for Database Credentials in Open Notebook
Open Notebook implements cascading fallback logic in open_notebook/database/repository.py that checks legacy variable names like SURREAL_PASS and constructs database URLs from address/port components when SURREAL_URL is unset.
Open Notebook connects to SurrealDB through environment variable configuration that prioritizes modern naming conventions while maintaining backward compatibility with legacy deployments. Understanding how these environment variable fallbacks for database credentials function helps operators migrate configurations without breaking existing connections. The fallback logic resides entirely within the Python repository layer, specifically in the database connection utilities that resolve credentials at runtime.
Fallback Logic for Database URL Construction
When SURREAL_URL is not present in the environment, Open Notebook automatically constructs the WebSocket connection string from component variables. In open_notebook/database/repository.py, the get_database_url() function implements this cascade:
- Primary check:
SURREAL_URLis read directly viaos.environ.get() - Fallback construction: If unset, the code combines
SURREAL_ADDRESS(defaulting tolocalhost) andSURREAL_PORT(defaulting to8000) into the formatws://<address>/rpc:<port>
This ensures older deployments using split address/port configuration continue functioning without modification while new deployments can use the consolidated URL format.
Password Variable Aliasing
The codebase maintains compatibility with older password environment variable names through a priority lookup. The get_database_password() function in open_notebook/database/repository.py checks variables in this order:
SURREAL_PASSWORD(modern naming)SURREAL_PASS(legacy naming)
The function returns the first non-empty value encountered, allowing gradual migration from legacy variable names without immediate breaking changes.
Required Variables Without Fallbacks
Certain connection parameters must be explicitly defined, as no fallback alternatives exist. These are read directly with os.environ.get() and passed to AsyncSurreal.use():
SURREAL_USER: Authentication usernameSURREAL_NAMESPACE: SurrealDB namespace selectionSURREAL_DATABASE: Database name selection
These variables are mandatory for establishing a functional connection, and missing values will cause connection failures since no default values or legacy aliases are provided according to the implementation in open_notebook/database/repository.py.
Connection Flow Implementation
The db_connection context manager in open_notebook/database/repository.py orchestrates the credential resolution:
from open_notebook.database.repository import db_connection
async def health_check():
async with db_connection() as db:
# Simple query to verify the connection works
await db.query("SELECT * FROM info::schema;")
Behind the scenes, the context manager:
- Creates an
AsyncSurrealclient using the resolved URL fromget_database_url() - Authenticates via
signinwith the username and password obtained through the fallback logic - Selects the namespace and database using the
usemethod
Configuration Examples
Modern Configuration (Preferred)
Set the complete connection string explicitly:
import os
os.environ.update({
"SURREAL_URL": "ws://surrealdb:8000/rpc",
"SURREAL_USER": "root",
"SURREAL_PASSWORD": "my-secret",
"SURREAL_NAMESPACE": "open_notebook",
"SURREAL_DATABASE": "open_notebook",
})
Legacy Configuration
Using component variables and legacy password naming:
import os
os.environ.update({
"SURREAL_ADDRESS": "surrealdb", # No SURREAL_URL set
"SURREAL_PORT": "8000",
"SURREAL_USER": "root",
"SURREAL_PASS": "my-secret", # Legacy password name
"SURREAL_NAMESPACE": "open_notebook",
"SURREAL_DATABASE": "open_notebook",
})
In this scenario, get_database_url() returns "ws://surrealdb/rpc:8000" and get_database_password() returns "my-secret".
Summary
open_notebook/database/repository.pycontains theget_database_url()andget_database_password()functions that implement fallback logic for legacy environment variables.SURREAL_URLtakes precedence, but if unset, the system constructs the URL fromSURREAL_ADDRESS(defaultlocalhost) andSURREAL_PORT(default8000).SURREAL_PASSWORDis checked before falling back to the legacySURREAL_PASSvariable.- Required variables (
SURREAL_USER,SURREAL_NAMESPACE,SURREAL_DATABASE) have no fallbacks and must be explicitly set. - The
db_connectioncontext manager handles the complete connection lifecycle using these resolved credentials.
Frequently Asked Questions
What happens if I set both SURREAL_URL and SURREAL_ADDRESS?
The get_database_url() function prioritizes SURREAL_URL and ignores SURREAL_ADDRESS entirely. Only when SURREAL_URL is undefined will the system fall back to constructing the URL from address and port components.
Is SURREAL_PASS still supported in new versions?
Yes. The get_database_password() function in open_notebook/database/repository.py checks SURREAL_PASS as a fallback when SURREAL_PASSWORD is unavailable. However, new deployments should use SURREAL_PASSWORD as documented in docs/5-CONFIGURATION/environment-reference.md.
Do I need to specify a port if using SURREAL_ADDRESS?
Only if you want a non-standard port. The fallback logic defaults SURREAL_PORT to 8000 when constructing the WebSocket URL from component parts. If using SURREAL_URL directly, you must include the port in the URL string if required.
Where is the source of truth for required environment variables?
While the fallback logic exists in code within open_notebook/database/repository.py, the canonical documentation in docs/5-CONFIGURATION/environment-reference.md lists SURREAL_URL, SURREAL_USER, SURREAL_PASSWORD, SURREAL_NAMESPACE, and SURREAL_DATABASE as the required variables for new deployments.
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 →