Appearance
Server
Table of Contents
- Overview
- App Mode
- Proxied Mode and Trusted Proxies
- Server Runtime Mode
- Running in Single Process
- Running in Cluster Mode
- Protocol and TLS Detection
- Configuration Reference
- Notes and Current Behaviors
Overview
Phenix runtime behavior is controlled by two independent configuration dimensions:
- App Mode (
directorproxied): controls how client connection metadata is resolved. - Server runtime mode (
singleorcluster): controls process model and worker execution.
The public application URL is independent from the socket exposed by the server. APP_URL is the canonical URL used to generate links and cookie domains. APP_HOST and APP_PORT select the local listening address and do not alter the canonical URL.
These are configured in config/app.php:
PHP
'app_mode' => env('APP_MODE', static fn (): string => 'direct'),
'trusted_proxies' => env('APP_TRUSTED_PROXIES', static fn (): array => []),
'server_mode' => env('APP_SERVER_MODE', static fn (): string => 'single'),
'url' => env('APP_URL', static fn (): string => 'http://127.0.0.1:1337'),
'host' => env('APP_HOST', static fn (): string => '127.0.0.1'),
'port' => env('APP_PORT', static fn (): int => 1337),For CORS configuration, see CORS (HandleCors) in the Middlewares guide.
App Mode
app.app_mode supports:
direct(AppMode::DIRECT): server is exposed directly to clients.proxied(AppMode::PROXIED): server is behind a reverse proxy/load balancer and trusts forwarding headers from configured proxies.
Use direct when the Phenix process receives traffic directly. Use proxied when requests come through Nginx, HAProxy, ALB, or similar infrastructure.
Proxied Mode and Trusted Proxies
When app_mode is proxied, app.trusted_proxies must be a non-empty array of trusted IPs or CIDRs.
If trusted_proxies is empty, server boot fails with a RuntimeError:
txt
Trusted proxies must be an array of IP addresses or CIDRs.Example configuration:
PHP
'app_mode' => 'proxied',
'trusted_proxies' => ['127.0.0.1/32', '10.0.0.0/8'],Security guidance: trust only known proxy IP ranges. Do not use broad or unknown ranges.
Server Runtime Mode
app.server_mode supports:
single(ServerMode::SINGLE): one server process.cluster(ServerMode::CLUSTER): multiple workers viaamphp/cluster.
In cluster mode, the app uses cluster termination flow (Cluster::awaitTermination()).
In non-cluster mode, the app uses signal trapping (SIGHUP, SIGINT, SIGQUIT, SIGTERM) for graceful stop.
Running in Single Process
Default behavior:
bash
php public/index.phpRunning in Cluster Mode
To run with worker processes:
ini
APP_SERVER_MODE=clusterThen, execute cluster:
bash
vendor/bin/cluster public/index.phpOptional worker count:
bash
vendor/bin/cluster -w 4 public/index.phpYou can inspect additional options with:
bash
vendor/bin/cluster --helpProtocol and TLS Detection
The protocol of the local listener is detected using app.cert_path:
Protocol::HTTPSis used whenapp.cert_pathcontains a certificate path.- Otherwise, the local listener uses HTTP, even when the public
APP_URLis HTTPS because a trusted reverse proxy terminates TLS.
TLS example:
PHP
'url' => 'https://example.com',
'host' => '0.0.0.0',
'port' => 1337,
'cert_path' => base_path('certs/server.pem'),Configuration Reference
| Key | Type | Values / Meaning |
|---|---|---|
app.app_mode | string | direct | proxied |
app.trusted_proxies | array<string> | Trusted proxy IPs/CIDRs (required when proxied) |
app.server_mode | string | single | cluster |
app.url | string | Canonical public URL, including a non-standard public port when needed |
app.host | string | Local interface where the HTTP server listens; it is not used to generate URLs |
app.port | int | Local port where the HTTP server listens; it is not appended to app.url |
app.cert_path | string | null | TLS certificate path used for HTTPS |
Notes and Current Behaviors
- Invalid
app_modevalues fall back todirect. - Invalid
server_modevalues fall back tosingle. - Trusted proxies validation is applied in both single and cluster servers when
app_mode=proxied. - Cluster mode and app mode are independent. You can run
cluster + directorcluster + proxied. APP_URL,APP_HOST, andAPP_PORTare independent. For example, an application can publishhttps://api.example.comwhile listening internally on0.0.0.0:1337.