Config keys
About 950 wordsAbout 3 min
config.php is the file-based fallback for runtime configuration. Env vars take priority — SPORA_* env vars are read first, then config.php, then built-in defaults. On a shared host, the operator typically edits config.php; on Docker / VPS, env vars are the canonical source.
For the canonical env-var list (the source of truth), see Environment variables. This page covers the config.php keys that map to those env vars.
Resolution priority
OS environment variable (SPORA_FOO)
→ .env file (loaded by vlucas/phpdotenv)
→ config.php (the 'foo' key, if present)
→ built-in default (in ContainerDefinitions)If SPORA_DB_HOST is set in .env, it wins. If config.php has 'db_host' => '127.0.0.1' but no env var, the config wins. The default in ContainerDefinitions.php is the last resort.
System mail (SMTP)
Set SPORA_MAIL_DRIVER=smtp to send Spora’s system messages through an SMTP submission server. Keep SPORA_MAIL_HOST as a hostname only; do not include smtp:// or ssl://.
| Variable | Description |
|---|---|
SPORA_MAIL_HOST | SMTP server hostname |
SPORA_MAIL_PORT | SMTP port; normally 587 for STARTTLS or 465 for implicit TLS |
SPORA_MAIL_USERNAME | SMTP username |
SPORA_MAIL_PASSWORD | SMTP password or provider app password |
SPORA_MAIL_ENCRYPTION | tls for STARTTLS, or ssl for implicit TLS |
SPORA_MAIL_FROM | Sender address |
SPORA_MAIL_FROM_NAME | Sender display name |
| SMTP port | Encryption | Connection mode |
|---|---|---|
587 | tls | SMTP greeting, then STARTTLS upgrade |
465 | ssl | TLS established immediately (SMTPS) |
Do not use ssl on port 587: the server expects an SMTP greeting before STARTTLS, so an immediate TLS handshake fails with OpenSSL’s wrong version number.
Example for STARTTLS:
SPORA_MAIL_DRIVER=smtp
SPORA_MAIL_HOST=smtp.example.com
SPORA_MAIL_PORT=587
SPORA_MAIL_USERNAME=user@example.com
SPORA_MAIL_PASSWORD=app-password
SPORA_MAIL_ENCRYPTION=tls
SPORA_MAIL_FROM=user@example.com
SPORA_MAIL_FROM_NAME=SporaExample for implicit TLS:
SPORA_MAIL_DRIVER=smtp
SPORA_MAIL_HOST=smtp.example.com
SPORA_MAIL_PORT=465
SPORA_MAIL_USERNAME=user@example.com
SPORA_MAIL_PASSWORD=app-password
SPORA_MAIL_ENCRYPTION=ssl
SPORA_MAIL_FROM=user@example.com
SPORA_MAIL_FROM_NAME=Spora| Key | Env var | Default | Purpose |
|---|---|---|---|
app_url | SPORA_APP_URL | auto-detected | Public URL of the instance (used for email links). Precedence: config.php app_url → SPORA_APP_URL env var → web-server HTTP_HOST/SERVER_NAME → http://localhost. See Environment variables for the resolution order and the no-X-Forwarded-* trust guarantee. Set via config.php for shared hosting where the env var is harder to manage. |
app_prefix | SPORA_APP_PREFIX | /spora | Path prefix Spora is mounted under. Default is /spora because the admin UI ships under public/spora/ and plugins ship under public/plugins/<name>/ — the host root is reserved for operators who develop their own frontend. Normalised: leading/trailing slashes stripped, bare / collapses to empty. Set SPORA_APP_PREFIX="" to opt out and run at the host root. Used for verification / password-reset email links. Set via config.php (app_prefix => '/spora') for shared hosting. |
app_env | SPORA_APP_ENV | development | development or production. Affects error reporting. |
allow_registration | SPORA_ALLOW_REGISTRATION | true | Whether POST /api/v1/auth/register is open. |
secret_key | SPORA_SECRET_KEY | — | Base64 32-byte master key for encrypting tool credentials. Required in production. |
key_path | SPORA_KEY_PATH | storage/secret.key (auto-generated) | Path to the key file (alternative to inline secret_key). |
db_driver | SPORA_DB_DRIVER | sqlite | sqlite or mysql. |
db_host | SPORA_DB_HOST | 127.0.0.1 | MySQL/MariaDB host. |
db_port | SPORA_DB_PORT | 3306 | MySQL/MariaDB port. |
db_name | SPORA_DB_NAME | spora | Database name. |
db_user | SPORA_DB_USER | spora | Database user. |
db_password | SPORA_DB_PASSWORD | — | Database password. |
sqlite_busy_timeout | SPORA_SQLITE_BUSY_TIMEOUT | 5000 | SQLite wait time when locked. |
worker_mode | SPORA_SYNC_MODE | true | true = inline (sync), false = queued (worker). |
worker_stale_minutes | SPORA_WORKER_STALE_MINUTES | 60 | Minutes before a RUNNING task is treated as orphaned. |
max_workers | SPORA_MAX_WORKERS | 0 (unlimited) | Max concurrent child processes in daemon mode. |
llm_timeout | SPORA_LLM_TIMEOUT | 300 | Seconds for LLM API calls. |
tool_http_timeout | SPORA_TOOL_HTTP_TIMEOUT | 30 | Seconds for tool HTTP requests. |
mercure_url | SPORA_MERCURE_URL | — | Public Mercure hub URL for SSE. |
mercure_publish_url | SPORA_MERCURE_PUBLISH_URL | falls back to mercure_url | Publisher endpoint (override for Docker internal vs public). |
mercure_jwt_key | SPORA_MERCURE_JWT_KEY | — | HS256 shared secret for Mercure. |
log_level | SPORA_LOG_LEVEL | warning | debug, info, warning, error. |
log_path | SPORA_LOG_PATH | storage/spora.log | Log file path. stdout for supervisor / container logging. |
notifications_email_enabled | SPORA_NOTIFICATIONS_EMAIL_ENABLED | false | Send email when scheduled run completes. |
plugin_install_enabled | SPORA_PLUGIN_INSTALL_ENABLED | false | Enable Web UI for plugin install / uninstall / update. |
composer_binary | SPORA_COMPOSER_BINARY | composer | Path to the composer executable used by the plugin manager. Absolute paths ending in .phar are auto-prefixed with php. |
plugin_catalog_enabled | SPORA_PLUGIN_CATALOG_ENABLED | true | Show the Browse tab in /apps/plugins and enable GET /api/v1/plugins/catalog. |
plugin_catalog_ttl | SPORA_PLUGIN_CATALOG_TTL | 3600 | Cache TTL (seconds) for the on-disk Packagist cache. |
For per-tool settings (e.g. Tavily api_key, Anthropic api_key), see Concepts → Tool system → Setting cascade.
Example config.php
<?php
declare(strict_types=1);
return [
'app_env' => 'production',
'allow_registration' => false,
'db_driver' => 'mysql',
'db_host' => '127.0.0.1',
'db_port' => 3306,
'db_name' => 'spora',
'db_user' => 'spora',
'db_password' => 'set-via-env-or-fail-loudly',
'worker_mode' => false,
'worker_stale_minutes' => 90,
'mercure_url' => 'https://mercure.example.com/.well-known/mercure',
'mercure_jwt_key' => 'set-via-env-or-fail-loudly',
'log_level' => 'info',
'log_path' => 'storage/spora.log',
'plugin_install_enabled' => true,
];Anything not set falls back to the built-in default from app/Core/ContainerDefinitions.php. Anything set via SPORA_* env vars wins over the file.
Docker-only variables
The following have no config.php mapping — FrankenPHP / Caddy reads them directly (not the SPORA_* resolver) and only applies them in container deployments.
| Env var | Default | Purpose |
|---|---|---|
SERVER_NAME | — | Caddy listens on this address and auto-issues Let’s Encrypt when it’s a public domain. Set localhost:80 for development, your public domain for production. |
See Environment variables → SERVER_NAME and the Docker deploy guides for context.
Editing config.php after install
config.php is read on every request via the config() helper. Changes take effect immediately — no php bin/spora command needed. For long-running worker daemons, the running process keeps the old config in memory; restart the worker (supervisorctl restart spora-worker) to pick up changes.
What’s next
- Environment variables — the canonical env-var reference (this page maps to it)
- Plugin schema — the
plugin.jsonmanifest spec - CLI reference — every
bin/sporacommand - REST API reference — the HTTP surface