Configuration
Modulo is configured through environment variables. All config lives in a .env file in the backend/ directory.
Required
| Variable | Description |
|---|---|
DATABASE_URL |
Async database connection string |
SECRET_KEY |
At least 32 bytes, used for JSON Web Token (JWT) signing. Known placeholder values are rejected at startup. |
FERNET_KEY |
Fernet-compatible key for credential encryption |
Database
DATABASE_URL=postgresql+asyncpg://user:password@host:5432/modulo
By default, the Docker Compose setup publishes Postgres on port 5432. The development Compose file (docker-compose.local.yml) also publishes it on port 5434, so use 5434 there when a local Postgres already occupies 5432.
MODULO_DB selects the backend and defaults to postgres. The accepted values are postgres, sqlite, mariadb, and mysql; MariaDB and MySQL use the aiomysql driver. Choosing sqlite disables the Postgres-specific security features (row-level security, advisory locks, and flood protection), so tenant isolation falls back to filtering in the object-relational mapping (ORM) layer. See Database Abstraction for what each backend supports.
Authentication
# Static users for local development (comma-separated, user:pass format)
MODULO_USERS=admin:admin,dev:dev
Credential encryption
# Generate your own. Do not use the example key in production.
FERNET_KEY=replace-with-your-generated-key
Generate one:
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
Public URL and licensing
Two settings tell Modulo how it is reached and which features are unlocked:
| Variable | Description |
|---|---|
MODULO_PUBLIC_URL |
The externally reachable base URL of your instance. Modulo builds absolute links from it: OIDC callback URLs, MCP server URLs, and the run links in HITL webhook payloads. Defaults to http://localhost:8000; set it to your instance’s public host before exposing Modulo beyond local use. |
MODULO_LICENSE_KEY |
A Team-tier license key. It unlocks the paid feature gates, such as Single Sign-On and SCIM provisioning. Leave it unset in the Community tier. |
MODULO_FRONTEND_URL overrides where the browser lands after login and defaults to MODULO_PUBLIC_URL; you only need it when the frontend is served from a different origin than the API. See Single Sign-On.
Connectors
Connector credentials are configured per connector instance in the Connector Hub (for example, a GitHub personal access token), not through environment variables. See Connectors for example configurations and Secrets for how credentials are handled.
CORS (Cross-Origin Resource Sharing)
CORS_ORIGINS=http://localhost:5173,https://modulo.run
Logging
MODULO_LOG_LEVEL=INFO
Log output is always structured JSON, so there is no format setting. MODULO_LOG_LEVEL sets the global level and defaults to INFO. To change one module only, set a per-module override named MODULO_LOG_LEVEL_<MODULE>, with dots replaced by underscores. For example, MODULO_LOG_LEVEL_MODULO_CONNECTORS=DEBUG raises the level for modulo.connectors alone, and takes precedence over the global value.
OpenTelemetry
Telemetry is off by default. Set MODULO_TELEMETRY_ENABLED=true to turn it on.
MODULO_TELEMETRY_ENABLED=true
# OTLP (OpenTelemetry Protocol) collector endpoint
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
# Service name reported in the telemetry; defaults to "modulo"
MODULO_OTEL_SERVICE_NAME=modulo
When telemetry is enabled, spans always export to stdout for local debugging. The OpenTelemetry Protocol (OTLP) exporter is added only when OTEL_EXPORTER_OTLP_ENDPOINT is set, so leaving that variable unset keeps tracing on stdout without sending anything off the host. An administrator can also toggle telemetry at runtime through the runtime config store without a restart.
Redis
REDIS_URL=redis://localhost:6379/0
Redis is required. Modulo uses it for event coordination, rate limiting, caching, and session state, so an empty REDIS_URL fails startup with an explicit error rather than degrading to a reduced feature set. The variable defaults to redis://localhost:6379/0, so a local Redis on the default port needs no configuration.
The default docker-compose.yml publishes Redis on port 6379. The development Compose file (docker-compose.local.yml) publishes it on port 6380.
Within Redis, Modulo uses a WebSocket event broker for live run-event streaming and a run event ring buffer for recent event replay after a reconnect.
Feature-specific settings
The variables below configure one feature each, so they are documented in full where that feature lives. They are set in the same .env file as the settings above.
| Variable | What it sets | Documented in |
|---|---|---|
MODULO_MAX_LOCAL_CONCURRENCY |
Concurrent agent subprocesses for the local runtime provider (default 2) |
Execution Environments, Concurrency and capacity sizing |
MODULO_DOCKER_HOST (or DOCKER_HOST) |
The Docker engine the runner_docker provider connects to |
Execution Environments |
MODULO_E2B_API_KEY |
Registers the E2B runtime provider | Execution Environments |
MODULO_RUNNER_MACHINE_ID |
Distinguishes two deployments that share one Docker engine | Execution Environments |
MODULO_KUBERNETES_ENABLED, MODULO_KUBERNETES_NAMESPACE, MODULO_KUBERNETES_SERVICE_ACCOUNT |
Register and scope the Kubernetes runtime provider | Kubernetes |
MODULO_SCHEMA_VALIDATOR_MODE |
First-boot seed for the schema validation mode: lenient (default) or strict |
Bring Your Own Agent |
MODULO_SCIM_TOKEN |
The bearer token SCIM provisioning requests authenticate with | SCIM Provisioning |
MODULO_SSO_DEFAULT_ROLE |
Role granted to a user provisioned through SSO (default runner) |
Single Sign-On (SSO) |
MODULO_SAML_IDP_METADATA_URL, MODULO_SAML_IDP_METADATA_XML |
IdP metadata for the legacy single-tenant SAML endpoints | Single Sign-On (SSO) |
SAQ_WORKER_CONCURRENCY, SAQ_REDIS_POOL_SIZE, SAQ_WORKER_DB_POOL_SIZE |
Worker throughput and the database and Redis connection pools each worker holds | Concurrency and capacity sizing |
TRIGGER_BACKPRESSURE_MAX_AGE_SECONDS |
Age at which the trigger backpressure guard refuses new fires (default 3600) | Concurrency and capacity sizing |
DB_CAPACITY_BYTES, DB_CAPACITY_PATH, DB_CAPACITY_HARD_STOP_PCT |
Database storage guard thresholds | Concurrency and capacity sizing |
Related
- Connectors: tool integrations for pipeline nodes
- Cost Management: token spend tracking and limits
- SCIM Provisioning: user and group lifecycle management
- Secrets: how the signing and encryption keys protect stored credentials