Where Is the Encryption Key for Securing API Credentials Stored in SurrealDB?
The encryption key for securing API credentials is not stored inside SurrealDB; instead, it is supplied at runtime via the OPEN_NOTEBOOK_ENCRYPTION_KEY environment variable or a Docker secret file, while only encrypted Fernet tokens persist in the database.
Open Notebook manages sensitive API credentials by keeping the encryption key entirely outside the database. In the lfnovo/open-notebook repository, the system uses an environment-based secret to encrypt credentials before they ever touch SurrealDB. This architecture ensures that even if the database is compromised, the API keys remain unreadable without the external encryption key.
How the Encryption Key Is Managed Outside SurrealDB
The encryption key is never written to the credential table or any other SurrealDB collection. According to the source code in open_notebook/utils/encryption.py, the application retrieves the secret from the process environment at runtime using the get_secret_from_env utility.
Environment Variable and Docker Secret Configuration
The system checks for the OPEN_NOTEBOOK_ENCRYPTION_KEY environment variable. It also supports Docker secrets by looking for a file path specified in OPEN_NOTEBOOK_ENCRYPTION_KEY_FILE. As implemented in open_notebook/utils/encryption.py (lines 62-79), the utility reads the value directly from the environment or from the referenced file, ensuring the key lives only in memory and never touches the disk in plain text within the database directory.
Where Encrypted Credentials Live in SurrealDB
While the encryption key remains external, the encrypted API credentials themselves are stored in the credential table of SurrealDB. The api_key column contains Fernet-encrypted tokens rather than plain text.
The Credential Domain Model
In open_notebook/domain/credential.py (lines 4-6), the Credential model defines the structure for stored credentials. When a record is saved, the plain-text API key is encrypted using encrypt_value() before insertion. When retrieving records (lines 55-69), the application calls decrypt_value() to restore the original API key in memory, leaving the database copy encrypted.
Validating and Using the Encryption Key
Before any credential operations occur, the application validates that the encryption key is properly configured.
Startup Validation in the Credentials Service
The require_encryption_key function in api/credentials_service.py (lines 199-204) acts as a guard. It calls get_secret_from_env("OPEN_NOTEBOOK_ENCRYPTION_KEY") and raises a ValueError if the key is missing. This guarantees that any write operation, such as POST /credentials, fails fast when the encryption environment is not configured.
Encryption and Decryption Functions
The open_notebook/utils/encryption.py module provides the core cryptography functions. The encrypt_value() function generates a Fernet token from the plain-text input, while decrypt_value() reverses the process using the same runtime-derived key. These functions ensure that only encrypted data traverses the network to SurrealDB.
Practical Implementation Example
The following examples demonstrate how the encryption key is used to secure API credentials before they reach SurrealDB.
First, configure the encryption key in your environment:
# .env file or Docker secret
OPEN_NOTEBOOK_ENCRYPTION_KEY=my-super-secret-passphrase
Then, encrypt values before storage and decrypt them on retrieval:
from open_notebook.utils.encryption import encrypt_value, decrypt_value
# Encrypt before storing in SurrealDB
plain_api_key = "sk-abc123"
encrypted_token = encrypt_value(plain_api_key)
# encrypted_token is now stored in credential.api_key
# Decrypt when reading from SurrealDB
decrypted_key = decrypt_value(encrypted_token)
# Returns: "sk-abc123"
When the application starts, the require_encryption_key() guard ensures the OPEN_NOTEBOOK_ENCRYPTION_KEY is present; otherwise, it raises a clear error to prevent unsecured credential storage.
Summary
- The encryption key is external: Open Notebook stores the
OPEN_NOTEBOOK_ENCRYPTION_KEYonly in the environment or a Docker secret file, never in SurrealDB. - Encrypted tokens persist: The
credentialtable holds Fernet-encrypted values in theapi_keycolumn, not plain text. - Validation is strict: The
require_encryption_keyfunction inapi/credentials_service.pyprevents any credential operations if the encryption key is missing. - Memory-only decryption: The
Credentialmodel inopen_notebook/domain/credential.pydecrypts values only when loaded into memory, keeping the database copy secure.
Frequently Asked Questions
Does Open Notebook store the encryption key in SurrealDB?
No. The encryption key is explicitly kept outside of SurrealDB. It is provided via the OPEN_NOTEBOOK_ENCRYPTION_KEY environment variable or a Docker secret file referenced by OPEN_NOTEBOOK_ENCRYPTION_KEY_FILE. The database only stores encrypted Fernet tokens produced by the encrypt_value() function.
What happens if the encryption key is missing when the application starts?
The application will raise a ValueError immediately. The require_encryption_key function in api/credentials_service.py (lines 199-204) validates the presence of the key before any credential write operations, causing a fast failure that prevents unsecured storage.
Which SurrealDB table stores the encrypted API credentials?
Encrypted API credentials are stored in the credential table. Specifically, the api_key column contains the encrypted Fernet tokens, while the encryption key remains in the runtime environment.
How does the Credential model decrypt values when reading from the database?
The Credential model in open_notebook/domain/credential.py (lines 55-69) calls decrypt_value() after loading a record from SurrealDB. This function uses the same OPEN_NOTEBOOK_ENCRYPTION_KEY from the environment to decrypt the token, returning the plain-text API key only in memory while leaving the database copy encrypted.
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 →