Skip to content

Environment Variables ​

Every environment variable read by the kernel (src/), the generated project bootstrap, and the first-party packages in modules/. Variables a plugin reads are declared in that plugin's module.json config[] and documented by the plugin.

Boolean flags are parsed with FILTER_VALIDATE_BOOL, so 1, true, on and yes all enable a flag, and an empty value means "use the default".

Where to set them

Most variables are read through env(), which sees values loaded from the .env cascade. The few marked real env only are read with getenv() before or outside that loader, so they must be in the actual process environment: shell, systemd unit, container, or PHP-FPM pool. A .env line will not reach them.

Kernel ​

Application ​

VariableDefaultRead byEffect
APP_KEYemptyCsrfTokenLayer, UrlGeneratorDefault HMAC secret for CSRF tokens and signed URLs. Empty: CSRF verification fails closed, and signing a URL throws.
APP_URLemptyUrlGenerator (via url() / the CoreContainer binding)Base URL for absolute URLs (route(..., absolute: true), signed links).
APP_DEBUGfalseErrorStage, DebugPageRendererShows the HTML debug page (trace and source excerpt) and real messages for critical errors. Never enable in production. See Error pipeline.
ERROR_STATUS_LEGACYfalseErrorStage, ErrorClassifierRestores the error mapping of 1.17 and earlier: the kernel DomainException, OptimisticLockException and LockTimeoutException answer 500 again, and the two lock exceptions are critical again. A migration aid for clients or alert rules that depend on the old codes; it will be removed in 2.0. See Exceptions.
APP_ENVnoneDebugPageRenderer; the .env loaderShown on the debug page. Also selects .env.{APP_ENV} in the cascade.

Boot ​

VariableDefaultRead byEffect
BOOT_CACHEfalseBootStampSkips manifest recompilation when nothing the compile read has changed. Turn it on for PHP-FPM in production, and clear var/cache/manifests/ on deploy. See Boot pipeline.

Routing ​

All are read once, when the HTTP pipeline is built.

VariableDefaultEffect
ROUTE_HEAD_FALLBACKtrueA HEAD with no route of its own is served by the GET route, body stripped.
ROUTE_METHOD_NOT_ALLOWEDfalseAnswer 405 with an Allow header on a method mismatch instead of 404. Off by default, because a 405 confirms that a path exists.
ROUTE_TRAILING_SLASHstrictstrict: /users/ and /users differ. ignore: match either. redirect: 301 to the canonical form. Any other value means strict.
ROUTE_STRICT_FILTERStrueA route naming an unregistered filter alias fails at pipeline build rather than when the route is requested.
ROUTE_VERIFY_HANDLERSfalseAt boot, check that every handler class and public method exists. Meant for development and CI; it autoloads every controller.

See Declaring routes.

Workers ​

VariableDefaultEffect
JOB_SIGNING_SECRETempty (verification off)HMAC secret the worker uses to verify every dequeued payload. Kernel::withWorkerSecret() takes precedence. Turn it on producer-first: an unsigned payload is rejected and dead-lettered. See Workers & jobs.

Generated project bootstrap ​

These are read by the entry points and bootstrap files a new project gets (templates/, projects/Bootstrap/), not by src/Kernel.

VariableDefaultEffect
APP_ENVproductionRead by the generated bootstrap. Outside local and testing, an empty APP_KEY refuses to boot. app/public/index.php also never shows debug output when this is production, even with APP_DEBUG on.
APP_KEY_PREVIOUSemptyThe previous key, kept during key rotation: the scaffolded EncryptionPort adapter receives both keys, so data encrypted with the old key still decrypts.
APP_TIMEZONEUTCPassed to date_default_timezone_set() at boot. Affects scheduled tasks that declare no timezone.
HASH_BCRYPT_COST12bcrypt cost for the scaffolded HashingPort adapter.
DB_POOL_ENABLEDfalseCLI only: bind a connection pool (Database plugin) for long-running processes.
DB_ENABLE_QUERY_LOGfalseWith the pool enabled, log each query.
TRUSTED_PROXIESempty (trust none)Read by app/public/index.php and app/swoole/index.php: comma-separated proxy IPs/CIDRs (preferred), PRIVATE_SUBNETS (wider than RFC 1918: includes CGNAT 100.64.0.0/10), or (FPM only) REMOTE_ADDR. X-Forwarded-For/-Proto/-Port from these proxies are honoured, so Request::ip() and isSecure() reflect the real client. See Request.
WORKER_QUEUEdefaultQueue app/worker/run.php consumes.
WORKER_MAX_ITERATIONS0 (forever)Jobs a worker processes before exiting, for supervisor-driven restarts.
ENV_CACHEfalseReal env only. Compiles the resolved .env cascade to var/cache/env.*.php. See Configuration.
APP_DOMAINnoneReal env only (read before the cascade loads). On the CLI, the host used to pick the domain tier of the .env cascade (same as --domain).
HKM_PROJECTadminReal env only. The project to boot when no host resolved one (CLI, workers, an unmatched host).
HKM_USERDATA_DIR{root}/projectsReal env only (domain resolution runs before .env loads). Where the machine-wide project registry (projects.json) is looked up.
SESSION_COOKIEhkm_sessionIn the scaffolded bootstrap, the cookie the CSRF layer's bindCookie pins tokens to. It must be an unencrypted cookie that does not rotate. See CSRF.
HKM_GLOBAL_AUTOLOADnoneReal env only. Explicit path to the kernel's vendor/autoload.php for a project using a globally installed kernel.
PSP_GLOBAL_AUTOLOADnoneReal env only. Pre-rename spelling of HKM_GLOBAL_AUTOLOAD, still honored.
HKM_KERNEL_HOMEnoneReal env only. Kernel install directory; its vendor/autoload.php is a candidate for the global autoload.
COMPOSER_HOMEnoneReal env only. Its vendor/autoload.php is a candidate for the global autoload. HOME, APPDATA and USERPROFILE supply the platform defaults after it.

The global-autoload lookup order is described in Installation.

OpenSwoole entry point ​

Read by the generated app/swoole/index.php:

VariableDefaultEffect
SWOOLE_HOST127.0.0.1Bind address.
SWOOLE_PORT9502Bind port.
HKM_WORKERSCPU count (else 4)worker_num.
HKM_ENVproductionEnvironment name passed to the server.
SWOOLE_MAX_REQUEST0 (never)Restart a worker after this many requests (max_request).
SWOOLE_DAEMONIZEfalseRun the server as a daemon.
SWOOLE_COROUTINEfalseEnable coroutine hooks.

Packages ​

VariablePackageEffect
NO_COLORphp-io-cliReal env only. When set to any value, disables ANSI color (no-color.org). Checked first.
FORCE_COLORphp-io-cliReal env only. When set, forces color on, for example in CI logs.
GROUND_WORKSPACE_DIRgroundParent directory for test workspaces (default: the system temp dir).
GROUND_KEEP_WORKSPACEgroundKeep the workspace after a run, for inspection.
GROUND_KEEP_DATABASEgroundReal env only. Keep the test database after a failed migration, for inspection.

LetMigrate reads no environment variables itself. Its connection settings are passed in by whatever constructs it.

Your own variables ​

Read your own variables with env(), and declare each one a module reads in that module's module.json config[], or the boot fails:

php
$apiKey  = env('EXTERNAL_API_KEY');
$timeout = (int) env('EXTERNAL_API_TIMEOUT', 30);

For structured settings, prefer a config/*.php file read through config(). See Configuration.

Source ​

Released under the MIT License.