Skip to main content

Configuration

Codex uses YAML configuration files with environment variable overrides. This guide covers all configuration options and best practices.

Configuration File

Codex looks for configuration in the following order:

  1. Path specified via --config flag
  2. codex.yaml in the current directory
  3. Default values
codex serve --config /path/to/codex.yaml

Configuration Priority

Settings can come from multiple sources, with this priority (highest to lowest):

  1. Environment variables (override everything)
  2. Configuration file (YAML)
  3. Database settings (runtime-configurable options)
  4. Hardcoded defaults (fallback)

Database Configuration

Codex supports both SQLite and PostgreSQL databases.

tip

For detailed database setup instructions including installation, user creation, and troubleshooting, see the Database Setup guide.

Best for single-user or small deployments with fewer than 10,000 books.

database:
db_type: sqlite
sqlite:
path: ./data/codex.db
pragmas:
journal_mode: WAL
synchronous: NORMAL

SQLite Pragmas

PragmaOptionsDescription
journal_modeWAL (recommended), DELETE, TRUNCATEWAL provides better concurrency
synchronousNORMAL (recommended), FULL, OFFTrade-off between safety and speed
foreign_keysAlways ONCannot be disabled (data integrity)
WAL Mode

Write-Ahead Logging (WAL) is strongly recommended for SQLite. It provides:

  • Better read/write concurrency
  • Faster writes for most workloads
  • Crash recovery improvements

Best for multi-user environments, large libraries, or horizontal scaling.

database:
db_type: postgres
postgres:
host: localhost
port: 5432
username: codex
password: codex
database_name: codex
ssl_mode: prefer

PostgreSQL SSL Modes

ModeDescription
disableNo SSL (not recommended for production)
allowTry without SSL, use SSL if available
preferTry SSL first, fallback to no SSL (default)
requireSSL required, but don't verify certificate
verify-caSSL required, verify server certificate
verify-fullSSL required, verify certificate and hostname
Production Security

For production deployments, use verify-ca or verify-full SSL mode with proper certificates.

Application Configuration

application:
name: Codex # Server name (displayed in UI)
host: 0.0.0.0 # Bind address (0.0.0.0 for all interfaces)
port: 8080 # Server port
SettingDefaultDescription
nameCodexServer display name
host127.0.0.1Bind address
port8080HTTP port

Authentication Configuration

auth:
jwt_secret: "CHANGE_ME_IN_PRODUCTION"
jwt_expiry_hours: 24
refresh_token_enabled: false
email_confirmation_required: false
argon2_memory_cost: 19456
argon2_time_cost: 2
argon2_parallelism: 1
SettingDefaultDescription
jwt_secretRequiredSecret key for JWT signing
jwt_expiry_hours24Token validity period
refresh_token_enabledfalseEnable refresh tokens
email_confirmation_requiredfalseRequire email verification
argon2_memory_cost19456Argon2 memory cost (KiB)
argon2_time_cost2Argon2 iterations
argon2_parallelism1Argon2 parallelism
JWT Secret

Always change the JWT secret in production! Generate a secure random string:

openssl rand -base64 32

API Configuration

api:
enable_api_docs: false
api_docs_path: "/docs"
cors_enabled: true
max_page_size: 100
SettingDefaultDescription
enable_api_docsfalseEnable API documentation (Scalar)
api_docs_path/docsAPI documentation URL path
cors_enabledtrueEnable CORS
max_page_size100Maximum items per page

Logging Configuration

logging:
level: info
# file: ./logs/codex.log # Uncomment to enable file logging
SettingDefaultDescription
levelinfoLog level: error, warn, info, debug, trace
fileNoneOptional log file path

Task Worker Configuration

These settings require a restart to take effect.

task:
worker_count: 4
SettingDefaultDescription
worker_count4Number of parallel background workers

Scanner Configuration

These settings require a restart to take effect.

scanner:
max_concurrent_scans: 2
SettingDefaultDescription
max_concurrent_scans2Maximum concurrent library scans

Files Configuration

Configuration for file storage directories (thumbnails and uploads).

files:
thumbnail_dir: data/thumbnails
uploads_dir: data/uploads
SettingDefaultDescription
thumbnail_dirdata/thumbnailsDirectory for thumbnail cache
uploads_dirdata/uploadsDirectory for user-uploaded files (covers, etc.)

Additional thumbnail settings are stored in the database and can be changed via the Settings API without restart:

  • thumbnail_max_dimension - Maximum width/height (default: 400px)
  • thumbnail_jpeg_quality - JPEG quality (default: 85%)

Email Configuration (Optional)

For email verification and notifications:

email:
smtp_host: localhost
smtp_port: 587
smtp_username: ""
smtp_password: ""
smtp_from_email: noreply@example.com
smtp_from_name: Codex
verification_token_expiry_hours: 24
verification_url_base: http://localhost:8080

Environment Variables

All configuration options can be overridden with environment variables using the CODEX_ prefix.

Naming Convention

Configuration paths are converted to environment variables:

  • Use uppercase
  • Replace dots with underscores
  • Prefix with CODEX_
Config PathEnvironment Variable
database.db_typeCODEX_DATABASE_DB_TYPE
database.postgres.hostCODEX_DATABASE_POSTGRES_HOST
auth.jwt_secretCODEX_AUTH_JWT_SECRET
logging.levelCODEX_LOGGING_LEVEL

Common Environment Variables

# Database
CODEX_DATABASE_DB_TYPE=postgres
CODEX_DATABASE_POSTGRES_HOST=localhost
CODEX_DATABASE_POSTGRES_PORT=5432
CODEX_DATABASE_POSTGRES_USERNAME=codex
CODEX_DATABASE_POSTGRES_PASSWORD=secret
CODEX_DATABASE_POSTGRES_DATABASE_NAME=codex
CODEX_DATABASE_POSTGRES_SSL_MODE=require

# Application
CODEX_APPLICATION_HOST=0.0.0.0
CODEX_APPLICATION_PORT=8080

# Authentication
CODEX_AUTH_JWT_SECRET=your-secure-secret-key

# Logging
CODEX_LOGGING_LEVEL=debug
CODEX_LOGGING_FILE=/var/log/codex/codex.log

# API
CODEX_API_ENABLE_API_DOCS=true

# Task Workers
CODEX_TASK_WORKER_COUNT=4

# Scanner
CODEX_SCANNER_MAX_CONCURRENT_SCANS=2

# Files (thumbnails and uploads)
CODEX_FILES_THUMBNAIL_DIR=data/thumbnails
CODEX_FILES_UPLOADS_DIR=data/uploads

Runtime vs Startup Settings

Some settings can be changed at runtime via the Settings API, while others require a restart.

Runtime-Configurable (No Restart Required)

These settings are stored in the database and can be changed via /api/v1/admin/settings:

  • Thumbnail max dimension
  • Thumbnail JPEG quality
  • Application name
  • Logging level

Startup-Time (Restart Required)

These settings are read from the config file at startup:

  • Database connection settings
  • Task worker count
  • Scanner concurrent scan limit
  • Thumbnail cache directory
  • JWT secret
  • Server host/port

Example Configurations

Minimal SQLite Configuration

database:
db_type: sqlite
sqlite:
path: ./data/codex.db

application:
host: 127.0.0.1
port: 8080

auth:
jwt_secret: "your-secure-random-secret"

Production PostgreSQL Configuration

database:
db_type: postgres
postgres:
host: db.example.com
port: 5432
username: codex
password: ${DB_PASSWORD}
database_name: codex
ssl_mode: verify-full

application:
name: My Library
host: 0.0.0.0
port: 8080

logging:
level: info
file: /var/log/codex/codex.log

auth:
jwt_secret: ${JWT_SECRET}
jwt_expiry_hours: 12

api:
enable_api_docs: false
cors_enabled: true

task:
worker_count: 8

scanner:
max_concurrent_scans: 4

files:
thumbnail_dir: /var/lib/codex/thumbnails
uploads_dir: /var/lib/codex/uploads

Kubernetes Configuration

For Kubernetes deployments, use environment variables for all sensitive data:

# Minimal config file - most settings come from environment
task:
worker_count: 4

scanner:
max_concurrent_scans: 2

files:
thumbnail_dir: data/thumbnails
uploads_dir: data/uploads

Set these via Kubernetes ConfigMaps and Secrets:

CODEX_DATABASE_DB_TYPE=postgres
CODEX_DATABASE_POSTGRES_HOST=postgres-service
CODEX_DATABASE_POSTGRES_PORT=5432
CODEX_DATABASE_POSTGRES_USERNAME=<from secret>
CODEX_DATABASE_POSTGRES_PASSWORD=<from secret>
CODEX_DATABASE_POSTGRES_DATABASE_NAME=codex
CODEX_AUTH_JWT_SECRET=<from secret>

Configuration Validation

Codex validates configuration at startup. Common errors:

ErrorCauseSolution
Invalid database typedb_type not sqlite or postgresFix the db_type value
Missing database pathSQLite requires a pathAdd sqlite.path
Database connection failedWrong credentials or hostCheck connection settings
Invalid portPort outside 1-65535 rangeUse a valid port number
File permissionsCan't write to pathsCheck directory permissions

Security Best Practices

  1. Use strong JWT secrets - Generate with openssl rand -base64 32
  2. Never commit secrets - Use environment variables or secret managers
  3. Use SSL for PostgreSQL - Set ssl_mode: verify-full in production
  4. Restrict bind address - Use 127.0.0.1 unless needed externally
  5. Disable API docs in production - Set enable_api_docs: false

Next Steps