# Reference: site file

URL: https://scalws.com/docs/reference/site-file/
Source: `docs/reference/schema` in the ScalWS repository

<h3 id="aliases"><code>aliases</code></h3>

| | |
|---|---|
| Syntax | `aliases: [<string>, ...]` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Further domains served by the same site.


<h3 id="cache"><code>cache</code></h3>

| | |
|---|---|
| Syntax | `cache: {...}` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Response cache for the site; absent: no caching.


<h3 id="cache.bypass_cookies"><code>cache.bypass_cookies</code></h3>

| | |
|---|---|
| Syntax | `bypass_cookies: [<string>, ...]` |
| Default | `[]` |
| Context | `cache` |
| Reload | applies on reload |

Cookie-name prefixes that mark a personalised request (added to the profile's).


<h3 id="cache.bypass_paths"><code>cache.bypass_paths</code></h3>

| | |
|---|---|
| Syntax | `bypass_paths: [<string>, ...]` |
| Default | `[]` |
| Context | `cache` |
| Reload | applies on reload |

Path prefixes that are never cached (added to the profile's).


<h3 id="cache.bypass_query"><code>cache.bypass_query</code></h3>

| | |
|---|---|
| Syntax | `bypass_query: [<string>, ...]` |
| Default | `[]` |
| Context | `cache` |
| Reload | applies on reload |

Query parameters that disable caching (added to the profile's).


<h3 id="cache.default_ttl"><code>cache.default_ttl</code></h3>

| | |
|---|---|
| Syntax | `default_ttl: <duration> (e.g. 30s)` |
| Default | `none` |
| Context | `cache` |
| Reload | applies on reload |

Freshness for `200` responses that carry no caching headers at all. Default: none (only explicitly cacheable responses are stored).


<h3 id="cache.enabled"><code>cache.enabled</code></h3>

| | |
|---|---|
| Syntax | `enabled: true \| false` |
| Default | `true` |
| Context | `cache` |
| Reload | applies on reload |

Cache this application's responses.


<h3 id="cache.stale_while_revalidate"><code>cache.stale_while_revalidate</code></h3>

| | |
|---|---|
| Syntax | `stale_while_revalidate: <duration> (e.g. 30s)` |
| Default | `none` |
| Context | `cache` |
| Reload | applies on reload |

Serve stale entries this long while refreshing in the background.


<h3 id="domain"><code>domain</code></h3>

| | |
|---|---|
| Syntax | `domain: <string>` |
| Default | `required` |
| Context | `site file` |
| Reload | applies on reload |

The site's main domain.


<h3 id="htaccess"><code>htaccess</code></h3>

| | |
|---|---|
| Syntax | `htaccess: true \| false` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Read Apache `.htaccess` files below `root` (ADR-0031).


<h3 id="https_redirect"><code>https_redirect</code></h3>

| | |
|---|---|
| Syntax | `https_redirect: true \| false` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Redirect plain HTTP to HTTPS (the `www.` redirect follows it).


<h3 id="name"><code>name</code></h3>

| | |
|---|---|
| Syntax | `name: <string>` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Application name; default derived from `domain`.


<h3 id="node"><code>node</code></h3>

| | |
|---|---|
| Syntax | `node: true \| <string> \| [<string>, ...] \| {...}` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Node.js: the command as a string or list, or the Node.js settings.


<h3 id="node.command"><code>node.command</code></h3>

| | |
|---|---|
| Syntax | `command: [<string>, ...]` |
| Default | `[]` |
| Context | `node` |
| Reload | applies on reload |

Command started by scalws (no shell), e.g. `[node, server.js]`; the application listens on `PORT`.


<h3 id="node.env"><code>node.env</code></h3>

| | |
|---|---|
| Syntax | `env: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `node` |
| Reload | applies on reload |

Environment variables for the process.


<h3 id="node.health_path"><code>node.health_path</code></h3>

| | |
|---|---|
| Syntax | `health_path: <string>` |
| Default | `none` |
| Context | `node` |
| Reload | applies on reload |

Optional readiness path; any non-5xx answer counts as ready.


<h3 id="node.listen"><code>node.listen</code></h3>

| | |
|---|---|
| Syntax | `listen: unix \| tcp` |
| Default | `unix` |
| Context | `node` |
| Reload | applies on reload |

`unix`: a socket under `runtime_dir` passed as `PORT`; `tcp`: a free loopback port.


<h3 id="node.response_timeout"><code>node.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `node` |
| Reload | applies on reload |

Time to wait for the response headers of the application.


<h3 id="node.startup_timeout"><code>node.startup_timeout</code></h3>

| | |
|---|---|
| Syntax | `startup_timeout: <duration> (e.g. 30s)` |
| Default | `30s` |
| Context | `node` |
| Reload | applies on reload |

Time the process gets to become ready.


<h3 id="node.stop_timeout"><code>node.stop_timeout</code></h3>

| | |
|---|---|
| Syntax | `stop_timeout: <duration> (e.g. 30s)` |
| Default | `10s` |
| Context | `node` |
| Reload | applies on reload |

Time the process gets to exit after SIGTERM before it is killed.


<h3 id="node.upstream"><code>node.upstream</code></h3>

| | |
|---|---|
| Syntax | `upstream: <string>` |
| Default | `none` |
| Context | `node` |
| Reload | applies on reload |

Proxy to a Node.js process managed elsewhere instead of starting one.


<h3 id="node.workers"><code>node.workers</code></h3>

| | |
|---|---|
| Syntax | `workers: {...}` |
| Default | `none` |
| Context | `node` |
| Reload | applies on reload |

Number of processes (`min`); requests are balanced across ready ones.


<h3 id="node.workers.autoscale"><code>node.workers.autoscale</code></h3>

| | |
|---|---|
| Syntax | `autoscale: off \| auto \| recommend` |
| Default | `recommend` |
| Context | `node.workers` |
| Reload | applies on reload |

`off`, `recommend` (default) or `auto` (ADR-0014).


<h3 id="node.workers.max"><code>node.workers.max</code></h3>

| | |
|---|---|
| Syntax | `max: <integer>` |
| Default | `required` |
| Context | `node.workers` |
| Reload | applies on reload |

Upper bound when the pool is scaled.


<h3 id="node.workers.min"><code>node.workers.min</code></h3>

| | |
|---|---|
| Syntax | `min: <integer>` |
| Default | `required` |
| Context | `node.workers` |
| Reload | applies on reload |

Processes started at the beginning and kept at least.


<h3 id="node.workers.target_concurrency"><code>node.workers.target_concurrency</code></h3>

| | |
|---|---|
| Syntax | `target_concurrency: <integer>` |
| Default | `none` |
| Context | `node.workers` |
| Reload | applies on reload |

Concurrent requests one worker is expected to handle well (utilisation basis).


<h3 id="php"><code>php</code></h3>

| | |
|---|---|
| Syntax | `php: true \| <string> \| [<string>, ...] \| {...}` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

PHP: `true` (a managed PHP-FPM pool), the address of an existing pool (`unix:/run/php/php8.3-fpm.sock`) or the PHP settings.


<h3 id="php.fastcgi"><code>php.fastcgi</code></h3>

| | |
|---|---|
| Syntax | `fastcgi: <string>` |
| Default | `none` |
| Context | `php` |
| Reload | applies on reload |

External pool: `unix:/path.sock` or `tcp:host:port`. Mutually exclusive with `fpm`.


<h3 id="php.fpm"><code>php.fpm</code></h3>

| | |
|---|---|
| Syntax | `fpm: {...}` |
| Default | `none` |
| Context | `php` |
| Reload | applies on reload |

Managed PHP-FPM pool settings (workers, ini values); not used with `fastcgi`.


<h3 id="php.fpm.binary"><code>php.fpm.binary</code></h3>

| | |
|---|---|
| Syntax | `binary: <string>` |
| Default | `none` |
| Context | `php.fpm` |
| Reload | applies on reload |

PHP-FPM binary; default: `php-fpm` on `PATH`, else the newest versioned one (`php-fpm8.4`, Alpine's `php-fpm84`).


<h3 id="php.fpm.env"><code>php.fpm.env</code></h3>

| | |
|---|---|
| Syntax | `env: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `php.fpm` |
| Reload | applies on reload |

Environment passed to PHP (`env[...]`).


<h3 id="php.fpm.ini"><code>php.fpm.ini</code></h3>

| | |
|---|---|
| Syntax | `ini: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `php.fpm` |
| Reload | applies on reload |

`php_admin_value[...]` settings, e.g. `memory_limit: 256M`.


<h3 id="php.fpm.max_requests"><code>php.fpm.max_requests</code></h3>

| | |
|---|---|
| Syntax | `max_requests: <integer>` |
| Default | `500` |
| Context | `php.fpm` |
| Reload | applies on reload |

`pm.max_requests`; 0 disables recycling.


<h3 id="php.fpm.workers"><code>php.fpm.workers</code></h3>

| | |
|---|---|
| Syntax | `workers: {...}` |
| Default | `none` |
| Context | `php.fpm` |
| Reload | applies on reload |

`min` = `pm.start_servers`/`pm.min_spare_servers`, `max` = `pm.max_children`.


<h3 id="php.fpm.workers.autoscale"><code>php.fpm.workers.autoscale</code></h3>

| | |
|---|---|
| Syntax | `autoscale: off \| auto \| recommend` |
| Default | `recommend` |
| Context | `php.fpm.workers` |
| Reload | applies on reload |

`off`, `recommend` (default) or `auto` (ADR-0014).


<h3 id="php.fpm.workers.max"><code>php.fpm.workers.max</code></h3>

| | |
|---|---|
| Syntax | `max: <integer>` |
| Default | `required` |
| Context | `php.fpm.workers` |
| Reload | applies on reload |

Upper bound when the pool is scaled.


<h3 id="php.fpm.workers.min"><code>php.fpm.workers.min</code></h3>

| | |
|---|---|
| Syntax | `min: <integer>` |
| Default | `required` |
| Context | `php.fpm.workers` |
| Reload | applies on reload |

Processes started at the beginning and kept at least.


<h3 id="php.fpm.workers.target_concurrency"><code>php.fpm.workers.target_concurrency</code></h3>

| | |
|---|---|
| Syntax | `target_concurrency: <integer>` |
| Default | `none` |
| Context | `php.fpm.workers` |
| Reload | applies on reload |

Concurrent requests one worker is expected to handle well (utilisation basis).


<h3 id="php.front_controller"><code>php.front_controller</code></h3>

| | |
|---|---|
| Syntax | `front_controller: <string>` |
| Default | `none` |
| Context | `php` |
| Reload | applies on reload |

Script that handles requests for paths that do not exist, e.g. `/index.php`.


<h3 id="php.index"><code>php.index</code></h3>

| | |
|---|---|
| Syntax | `index: [<string>, ...]` |
| Default | `["index.php","index.html"]` |
| Context | `php` |
| Reload | applies on reload |

Index files for directory requests, tried in order.


<h3 id="php.response_timeout"><code>php.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `php` |
| Reload | applies on reload |

Time to wait for PHP-FPM's response headers.


<h3 id="php.root"><code>php.root</code></h3>

| | |
|---|---|
| Syntax | `root: <string>` |
| Default | `none` |
| Context | `php` |
| Reload | applies on reload |

Document root; defaults to the application `root`.


<h3 id="php.startup_timeout"><code>php.startup_timeout</code></h3>

| | |
|---|---|
| Syntax | `startup_timeout: <duration> (e.g. 30s)` |
| Default | `30s` |
| Context | `php` |
| Reload | applies on reload |

Time the managed PHP-FPM pool gets to become ready.


<h3 id="php.stop_timeout"><code>php.stop_timeout</code></h3>

| | |
|---|---|
| Syntax | `stop_timeout: <duration> (e.g. 30s)` |
| Default | `10s` |
| Context | `php` |
| Reload | applies on reload |

Time the managed pool gets to exit before it is killed.


<h3 id="profile"><code>profile</code></h3>

| | |
|---|---|
| Syntax | `profile: <string>` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Application profile, e.g. `wordpress` (deny rules, cache bypass, defaults).


<h3 id="proxy"><code>proxy</code></h3>

| | |
|---|---|
| Syntax | `proxy: true \| <string> \| [<string>, ...] \| {...}` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Reverse proxy: the upstream URL or the proxy settings.


<h3 id="proxy.backends"><code>proxy.backends</code></h3>

| | |
|---|---|
| Syntax | `backends: [{...}, ...]` |
| Default | `none` |
| Context | `proxy` |
| Reload | applies on reload |

Weighted split per request across pools (alternative to `upstream`).


<h3 id="proxy.backends-.pool"><code>proxy.backends[].pool</code></h3>

| | |
|---|---|
| Syntax | `pool: <string>` |
| Default | `none` |
| Context | `proxy.backends[]` |
| Reload | applies on reload |

Name of a pool in `upstreams`; alternative to `status`.


<h3 id="proxy.backends-.status"><code>proxy.backends[].status</code></h3>

| | |
|---|---|
| Syntax | `status: <integer>` |
| Default | `none` |
| Context | `proxy.backends[]` |
| Reload | applies on reload |

Answers this share of the requests with this status (500-599) instead of sending them to a pool.


<h3 id="proxy.backends-.weight"><code>proxy.backends[].weight</code></h3>

| | |
|---|---|
| Syntax | `weight: <integer>` |
| Default | `1` |
| Context | `proxy.backends[]` |
| Reload | applies on reload |

Share of requests (0..=1000); 0 sends none.


<h3 id="proxy.client"><code>proxy.client</code></h3>

| | |
|---|---|
| Syntax | `client: hyper \| experimental` |
| Default | `none` |
| Context | `proxy` |
| Reload | applies on reload |

HTTP/1 client used towards this upstream; unset: `server.upstream_client`.


<h3 id="proxy.connect_timeout"><code>proxy.connect_timeout</code></h3>

| | |
|---|---|
| Syntax | `connect_timeout: <duration> (e.g. 30s)` |
| Default | `5s` |
| Context | `proxy` |
| Reload | applies on reload |

Time to establish a connection to the upstream.


<h3 id="proxy.preserve_host"><code>proxy.preserve_host</code></h3>

| | |
|---|---|
| Syntax | `preserve_host: true \| false` |
| Default | `true` |
| Context | `proxy` |
| Reload | applies on reload |

Forward the client's Host header (default) instead of the upstream authority.


<h3 id="proxy.response_timeout"><code>proxy.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `proxy` |
| Reload | applies on reload |

Time allowed for the upstream to return response headers.


<h3 id="proxy.tls_ca_file"><code>proxy.tls_ca_file</code></h3>

| | |
|---|---|
| Syntax | `tls_ca_file: <string>` |
| Default | `none` |
| Context | `proxy` |
| Reload | applies on reload |

Extra CA bundle (PEM) trusted for `https://` upstreams, in addition to the system roots.


<h3 id="proxy.upstream"><code>proxy.upstream</code></h3>

| | |
|---|---|
| Syntax | `upstream: <string> \| {...}` |
| Default | `none` |
| Context | `proxy` |
| Reload | applies on reload |

`http://host:port`, `https://host:port` or `unix:/absolute/path.sock` (one address, no retries), or `{pool: name}`: a pool from `upstreams`.


<h3 id="proxy.upstream.pool"><code>proxy.upstream.pool</code></h3>

| | |
|---|---|
| Syntax | `pool: <string>` |
| Default | `required` |
| Context | `proxy.upstream` |
| Reload | applies on reload |

Name of a pool in `upstreams`.


<h3 id="proxy.websocket"><code>proxy.websocket</code></h3>

| | |
|---|---|
| Syntax | `websocket: true \| false` |
| Default | `true` |
| Context | `proxy` |
| Reload | applies on reload |

Allow WebSocket upgrades to be tunnelled to this upstream.


<h3 id="python"><code>python</code></h3>

| | |
|---|---|
| Syntax | `python: true \| <string> \| [<string>, ...] \| {...}` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Python: `module:app` (ASGI through uvicorn) or the Python settings.


<h3 id="python.app"><code>python.app</code></h3>

| | |
|---|---|
| Syntax | `app: <string>` |
| Default | `none` |
| Context | `python` |
| Reload | applies on reload |

`module:callable`, e.g. `app:app` or `mysite.wsgi:application`.


<h3 id="python.command"><code>python.command</code></h3>

| | |
|---|---|
| Syntax | `command: [<string>, ...]` |
| Default | `[]` |
| Context | `python` |
| Reload | applies on reload |

Explicit argv. Bind arguments are appended for uvicorn/hypercorn/gunicorn unless the argv already contains `{socket}` or `{port}`.


<h3 id="python.env"><code>python.env</code></h3>

| | |
|---|---|
| Syntax | `env: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `python` |
| Reload | applies on reload |

Environment variables for the processes.


<h3 id="python.health_path"><code>python.health_path</code></h3>

| | |
|---|---|
| Syntax | `health_path: <string>` |
| Default | `none` |
| Context | `python` |
| Reload | applies on reload |

Path requested to decide that a worker is ready and healthy.


<h3 id="python.listen"><code>python.listen</code></h3>

| | |
|---|---|
| Syntax | `listen: unix \| tcp` |
| Default | `unix` |
| Context | `python` |
| Reload | applies on reload |

`unix`: a socket under `runtime_dir`; `tcp`: a free loopback port.


<h3 id="python.mode"><code>python.mode</code></h3>

| | |
|---|---|
| Syntax | `mode: asgi \| wsgi` |
| Default | `required` |
| Context | `python` |
| Reload | applies on reload |

`asgi` (uvicorn) or `wsgi` (gunicorn).


<h3 id="python.process_pool"><code>python.process_pool</code></h3>

| | |
|---|---|
| Syntax | `process_pool: true \| false` |
| Default | `false` |
| Context | `python` |
| Reload | applies on reload |

scalws runs `workers.min..max` single-worker server processes itself instead of one server with `--workers`, so the pool can be scaled and restarted live (ADR-0014). Trades the server's copy-on-write sharing for scaling.


<h3 id="python.response_timeout"><code>python.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `python` |
| Reload | applies on reload |

Time to wait for the response headers of the application.


<h3 id="python.server"><code>python.server</code></h3>

| | |
|---|---|
| Syntax | `server: uvicorn \| hypercorn \| gunicorn` |
| Default | `none` |
| Context | `python` |
| Reload | applies on reload |

Default: uvicorn for ASGI, gunicorn for WSGI.


<h3 id="python.startup_timeout"><code>python.startup_timeout</code></h3>

| | |
|---|---|
| Syntax | `startup_timeout: <duration> (e.g. 30s)` |
| Default | `30s` |
| Context | `python` |
| Reload | applies on reload |

Time the processes get to become ready.


<h3 id="python.stop_timeout"><code>python.stop_timeout</code></h3>

| | |
|---|---|
| Syntax | `stop_timeout: <duration> (e.g. 30s)` |
| Default | `10s` |
| Context | `python` |
| Reload | applies on reload |

Time the processes get to exit after SIGTERM before they are killed.


<h3 id="python.upstream"><code>python.upstream</code></h3>

| | |
|---|---|
| Syntax | `upstream: <string>` |
| Default | `none` |
| Context | `python` |
| Reload | applies on reload |

Proxy to a Python server managed elsewhere instead of starting one.


<h3 id="python.virtualenv"><code>python.virtualenv</code></h3>

| | |
|---|---|
| Syntax | `virtualenv: <string>` |
| Default | `none` |
| Context | `python` |
| Reload | applies on reload |

Virtual environment whose server binary and packages are used.


<h3 id="python.workers"><code>python.workers</code></h3>

| | |
|---|---|
| Syntax | `workers: {...}` |
| Default | `none` |
| Context | `python` |
| Reload | applies on reload |

Worker processes of the application server (`min`).


<h3 id="python.workers.autoscale"><code>python.workers.autoscale</code></h3>

| | |
|---|---|
| Syntax | `autoscale: off \| auto \| recommend` |
| Default | `recommend` |
| Context | `python.workers` |
| Reload | applies on reload |

`off`, `recommend` (default) or `auto` (ADR-0014).


<h3 id="python.workers.max"><code>python.workers.max</code></h3>

| | |
|---|---|
| Syntax | `max: <integer>` |
| Default | `required` |
| Context | `python.workers` |
| Reload | applies on reload |

Upper bound when the pool is scaled.


<h3 id="python.workers.min"><code>python.workers.min</code></h3>

| | |
|---|---|
| Syntax | `min: <integer>` |
| Default | `required` |
| Context | `python.workers` |
| Reload | applies on reload |

Processes started at the beginning and kept at least.


<h3 id="python.workers.target_concurrency"><code>python.workers.target_concurrency</code></h3>

| | |
|---|---|
| Syntax | `target_concurrency: <integer>` |
| Default | `none` |
| Context | `python.workers` |
| Reload | applies on reload |

Concurrent requests one worker is expected to handle well (utilisation basis).


<h3 id="redirect"><code>redirect</code></h3>

| | |
|---|---|
| Syntax | `redirect: true \| <string> \| [<string>, ...] \| {...}` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Redirect: the target origin or the redirect settings.


<h3 id="redirect.host"><code>redirect.host</code></h3>

| | |
|---|---|
| Syntax | `host: <string>` |
| Default | `none` |
| Context | `redirect` |
| Reload | applies on reload |

Replaces the request's host; unset: taken from the request.


<h3 id="redirect.keep_path"><code>redirect.keep_path</code></h3>

| | |
|---|---|
| Syntax | `keep_path: true \| false` |
| Default | `true` |
| Context | `redirect` |
| Reload | applies on reload |

Append the request's path and query to `to`.


<h3 id="redirect.path"><code>redirect.path</code></h3>

| | |
|---|---|
| Syntax | `path: <string>` |
| Default | `none` |
| Context | `redirect` |
| Reload | applies on reload |

Replaces the request's path; unset: taken from the request.


<h3 id="redirect.port"><code>redirect.port</code></h3>

| | |
|---|---|
| Syntax | `port: <integer>` |
| Default | `none` |
| Context | `redirect` |
| Reload | applies on reload |

Replaces the request's port; unset: the well-known port of a configured `scheme`, else taken from the request.


<h3 id="redirect.prefix"><code>redirect.prefix</code></h3>

| | |
|---|---|
| Syntax | `prefix: <string>` |
| Default | `none` |
| Context | `redirect` |
| Reload | applies on reload |

Replaces the matched prefix of the request's path; unset: taken from the request.


<h3 id="redirect.scheme"><code>redirect.scheme</code></h3>

| | |
|---|---|
| Syntax | `scheme: http \| https` |
| Default | `none` |
| Context | `redirect` |
| Reload | applies on reload |

Replaces the request's scheme; unset: taken from the request.


<h3 id="redirect.status"><code>redirect.status</code></h3>

| | |
|---|---|
| Syntax | `status: <integer>` |
| Default | `301` |
| Context | `redirect` |
| Reload | applies on reload |

301, 302, 303, 307 or 308.


<h3 id="redirect.to"><code>redirect.to</code></h3>

| | |
|---|---|
| Syntax | `to: <string>` |
| Default | `none` |
| Context | `redirect` |
| Reload | applies on reload |

Target origin, e.g. `https://example.com`: scheme and host (and port), no path when `keep_path` is on. Alternative to the fields `scheme`, `host`, `port`, `path` and `prefix`.


<h3 id="resources"><code>resources</code></h3>

| | |
|---|---|
| Syntax | `resources: {...}` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Tenant resource limits; set them in one site file per tenant.


<h3 id="resources.burst"><code>resources.burst</code></h3>

| | |
|---|---|
| Syntax | `burst: <integer>` |
| Default | `none` |
| Context | `resources` |
| Reload | applies on reload |

Token-bucket burst for `requests_per_second` (default: equal to the rate).


<h3 id="resources.cpu"><code>resources.cpu</code></h3>

| | |
|---|---|
| Syntax | `cpu: <cpu quota> (e.g. "400%")` |
| Default | `none` |
| Context | `resources` |
| Reload | applies on reload |

`cpu.max`, e.g. `"400%"` = four CPUs.


<h3 id="resources.io_bandwidth"><code>resources.io_bandwidth</code></h3>

| | |
|---|---|
| Syntax | `io_bandwidth: <size> (e.g. 16KiB)` |
| Default | `none` |
| Context | `resources` |
| Reload | applies on reload |

`io.max`: read and write bytes per second each, on every disk holding the tenant's application roots, e.g. `"20MiB"`.


<h3 id="resources.io_weight"><code>resources.io_weight</code></h3>

| | |
|---|---|
| Syntax | `io_weight: <integer>` |
| Default | `none` |
| Context | `resources` |
| Reload | applies on reload |

`io.weight` (1-10000, default 100), best effort: needs a weight-capable I/O scheduler.


<h3 id="resources.max_concurrent_requests"><code>resources.max_concurrent_requests</code></h3>

| | |
|---|---|
| Syntax | `max_concurrent_requests: <integer>` |
| Default | `none` |
| Context | `resources` |
| Reload | applies on reload |

Requests of this tenant processed concurrently; excess gets 503.


<h3 id="resources.memory"><code>resources.memory</code></h3>

| | |
|---|---|
| Syntax | `memory: <size> (e.g. 16KiB)` |
| Default | `none` |
| Context | `resources` |
| Reload | applies on reload |

`memory.max`.


<h3 id="resources.pids"><code>resources.pids</code></h3>

| | |
|---|---|
| Syntax | `pids: <integer>` |
| Default | `none` |
| Context | `resources` |
| Reload | applies on reload |

`pids.max`.


<h3 id="resources.requests_per_second"><code>resources.requests_per_second</code></h3>

| | |
|---|---|
| Syntax | `requests_per_second: <integer>` |
| Default | `none` |
| Context | `resources` |
| Reload | applies on reload |

Sustained request rate; excess gets 429.


<h3 id="resources.swap"><code>resources.swap</code></h3>

| | |
|---|---|
| Syntax | `swap: <size> (e.g. 16KiB)` |
| Default | `none` |
| Context | `resources` |
| Reload | applies on reload |

`memory.swap.max` when `memory` is set; default 0 (no swap).


<h3 id="root"><code>root</code></h3>

| | |
|---|---|
| Syntax | `root: <string>` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Document root: static files, PHP scripts or the application's directory.


<h3 id="root_symlinks"><code>root_symlinks</code></h3>

| | |
|---|---|
| Syntax | `root_symlinks: follow \| refuse` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Symbolic links in the path of `root`: `follow` (default) or `refuse` (the root must be canonical and is opened without following links; for hosting panels).


<h3 id="routes"><code>routes</code></h3>

| | |
|---|---|
| Syntax | `routes: [{...}, ...]` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Path-prefix routes with their own runtime.


<h3 id="routes-.allow"><code>routes[].allow</code></h3>

| | |
|---|---|
| Syntax | `allow: [<string>, ...]` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

Client addresses and CIDR blocks allowed; if set, only these clients (403 else).


<h3 id="routes-.basic_auth"><code>routes[].basic_auth</code></h3>

| | |
|---|---|
| Syntax | `basic_auth: {...}` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

HTTP basic authentication against an htpasswd file.


<h3 id="routes-.basic_auth.realm"><code>routes[].basic_auth.realm</code></h3>

| | |
|---|---|
| Syntax | `realm: <string>` |
| Default | `Restricted` |
| Context | `routes[].basic_auth` |
| Reload | applies on reload |

Realm shown by the browser (default `Restricted`).


<h3 id="routes-.basic_auth.users_file"><code>routes[].basic_auth.users_file</code></h3>

| | |
|---|---|
| Syntax | `users_file: <string>` |
| Default | `required` |
| Context | `routes[].basic_auth` |
| Reload | applies on reload |

Absolute path of an htpasswd file (bcrypt, SHA-256/512 crypt or Apache MD5 entries).


<h3 id="routes-.cors"><code>routes[].cors</code></h3>

| | |
|---|---|
| Syntax | `cors: {...}` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

Cross-origin resource sharing; preflight requests are answered by ScalWS.


<h3 id="routes-.cors.allow_credentials"><code>routes[].cors.allow_credentials</code></h3>

| | |
|---|---|
| Syntax | `allow_credentials: true \| false` |
| Default | `false` |
| Context | `routes[].cors` |
| Reload | applies on reload |

Allow credentials (cookies, authorization); not with `allow_origins: ["*"]`.


<h3 id="routes-.cors.allow_headers"><code>routes[].cors.allow_headers</code></h3>

| | |
|---|---|
| Syntax | `allow_headers: [<string>, ...]` |
| Default | `["DNT","Keep-Alive","User-Agent","X-Requested-With","If-Modified-Since","Cache-Control","Content-Type","Range","Authorization"]` |
| Context | `routes[].cors` |
| Reload | applies on reload |

Request headers allowed in preflight answers (ingress-nginx defaults).


<h3 id="routes-.cors.allow_methods"><code>routes[].cors.allow_methods</code></h3>

| | |
|---|---|
| Syntax | `allow_methods: [<string>, ...]` |
| Default | `["GET","PUT","POST","DELETE","PATCH","OPTIONS"]` |
| Context | `routes[].cors` |
| Reload | applies on reload |

Methods allowed in preflight answers (default: GET, PUT, POST, DELETE, PATCH, OPTIONS).


<h3 id="routes-.cors.allow_origins"><code>routes[].cors.allow_origins</code></h3>

| | |
|---|---|
| Syntax | `allow_origins: [<string>, ...]` |
| Default | `required` |
| Context | `routes[].cors` |
| Reload | applies on reload |

Allowed origins, e.g. `https://app.example.com`, `https://*.example.com`, or `["*"]`.


<h3 id="routes-.cors.expose_headers"><code>routes[].cors.expose_headers</code></h3>

| | |
|---|---|
| Syntax | `expose_headers: [<string>, ...]` |
| Default | `none` |
| Context | `routes[].cors` |
| Reload | applies on reload |

Response headers exposed to the page.


<h3 id="routes-.cors.max_age"><code>routes[].cors.max_age</code></h3>

| | |
|---|---|
| Syntax | `max_age: <duration> (e.g. 30s)` |
| Default | `1728000s` |
| Context | `routes[].cors` |
| Reload | applies on reload |

How long a preflight answer may be cached, at most 365 days (default 20 days).


<h3 id="routes-.deny"><code>routes[].deny</code></h3>

| | |
|---|---|
| Syntax | `deny: [<string>, ...]` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

Client addresses and CIDR blocks refused with 403; checked after `allow`.


<h3 id="routes-.headers"><code>routes[].headers</code></h3>

| | |
|---|---|
| Syntax | `headers: [{...}, ...]` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

Request headers that must match (all of them).


<h3 id="routes-.headers-.name"><code>routes[].headers[].name</code></h3>

| | |
|---|---|
| Syntax | `name: <string>` |
| Default | `required` |
| Context | `routes[].headers[]` |
| Reload | applies on reload |

Header name (case-insensitive) or query parameter name.


<h3 id="routes-.headers-.regex"><code>routes[].headers[].regex</code></h3>

| | |
|---|---|
| Syntax | `regex: <string>` |
| Default | `none` |
| Context | `routes[].headers[]` |
| Reload | applies on reload |

Regular expression the value must match (searched anywhere unless anchored).


<h3 id="routes-.headers-.value"><code>routes[].headers[].value</code></h3>

| | |
|---|---|
| Syntax | `value: <string>` |
| Default | `none` |
| Context | `routes[].headers[]` |
| Reload | applies on reload |

Exact, case-sensitive value.


<h3 id="routes-.https_redirect"><code>routes[].https_redirect</code></h3>

| | |
|---|---|
| Syntax | `https_redirect: true \| false` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

Answer plain-HTTP requests that select this route with a 301 to HTTPS; unset: the application's `https_redirect`.


<h3 id="routes-.max_body"><code>routes[].max_body</code></h3>

| | |
|---|---|
| Syntax | `max_body: <size> (e.g. 16KiB)` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

Largest request body; overrides `limits.max_request_body_bytes`; 413 above.


<h3 id="routes-.methods"><code>routes[].methods</code></h3>

| | |
|---|---|
| Syntax | `methods: [<string>, ...]` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

Request methods this route matches, e.g. `[GET, POST]`; empty: any.


<h3 id="routes-.path"><code>routes[].path</code></h3>

| | |
|---|---|
| Syntax | `path: <string>` |
| Default | `required` |
| Context | `routes[]` |
| Reload | applies on reload |

Path of the route; how it is compared depends on `path_type`.


<h3 id="routes-.path_type"><code>routes[].path_type</code></h3>

| | |
|---|---|
| Syntax | `path_type: prefix \| exact \| regex` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

`prefix` (default, whole segments, longest first), `exact` or `regex` (anchored at the start, in configuration order).


<h3 id="routes-.query"><code>routes[].query</code></h3>

| | |
|---|---|
| Syntax | `query: [{...}, ...]` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

Query parameters that must match (all of them, decoded, first occurrence).


<h3 id="routes-.query-.name"><code>routes[].query[].name</code></h3>

| | |
|---|---|
| Syntax | `name: <string>` |
| Default | `required` |
| Context | `routes[].query[]` |
| Reload | applies on reload |

Header name (case-insensitive) or query parameter name.


<h3 id="routes-.query-.regex"><code>routes[].query[].regex</code></h3>

| | |
|---|---|
| Syntax | `regex: <string>` |
| Default | `none` |
| Context | `routes[].query[]` |
| Reload | applies on reload |

Regular expression the value must match (searched anywhere unless anchored).


<h3 id="routes-.query-.value"><code>routes[].query[].value</code></h3>

| | |
|---|---|
| Syntax | `value: <string>` |
| Default | `none` |
| Context | `routes[].query[]` |
| Reload | applies on reload |

Exact, case-sensitive value.


<h3 id="routes-.request_headers"><code>routes[].request_headers</code></h3>

| | |
|---|---|
| Syntax | `request_headers: {...}` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

Changes to the request headers (after the built-in proxy headers).


<h3 id="routes-.request_headers.add"><code>routes[].request_headers.add</code></h3>

| | |
|---|---|
| Syntax | `add: {<key>: <string>, ...}` |
| Default | `none` |
| Context | `routes[].request_headers` |
| Reload | applies on reload |

Headers added next to any present.


<h3 id="routes-.request_headers.remove"><code>routes[].request_headers.remove</code></h3>

| | |
|---|---|
| Syntax | `remove: [<string>, ...]` |
| Default | `none` |
| Context | `routes[].request_headers` |
| Reload | applies on reload |

Headers removed.


<h3 id="routes-.request_headers.set"><code>routes[].request_headers.set</code></h3>

| | |
|---|---|
| Syntax | `set: {<key>: <string>, ...}` |
| Default | `none` |
| Context | `routes[].request_headers` |
| Reload | applies on reload |

Headers set to this value, replacing any present.


<h3 id="routes-.request_timeout"><code>routes[].request_timeout</code></h3>

| | |
|---|---|
| Syntax | `request_timeout: <duration> (e.g. 30s)` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

Time from the route match until the response head; 504 when exceeded.


<h3 id="routes-.response_headers"><code>routes[].response_headers</code></h3>

| | |
|---|---|
| Syntax | `response_headers: {...}` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

Changes to every response of the route, including errors generated by ScalWS.


<h3 id="routes-.response_headers.add"><code>routes[].response_headers.add</code></h3>

| | |
|---|---|
| Syntax | `add: {<key>: <string>, ...}` |
| Default | `none` |
| Context | `routes[].response_headers` |
| Reload | applies on reload |

Headers added next to any present.


<h3 id="routes-.response_headers.remove"><code>routes[].response_headers.remove</code></h3>

| | |
|---|---|
| Syntax | `remove: [<string>, ...]` |
| Default | `none` |
| Context | `routes[].response_headers` |
| Reload | applies on reload |

Headers removed.


<h3 id="routes-.response_headers.set"><code>routes[].response_headers.set</code></h3>

| | |
|---|---|
| Syntax | `set: {<key>: <string>, ...}` |
| Default | `none` |
| Context | `routes[].response_headers` |
| Reload | applies on reload |

Headers set to this value, replacing any present.


<h3 id="routes-.rewrite"><code>routes[].rewrite</code></h3>

| | |
|---|---|
| Syntax | `rewrite: {...}` |
| Default | `none` |
| Context | `routes[]` |
| Reload | applies on reload |

Path and Host rewrite before the runtime.


<h3 id="routes-.rewrite.host"><code>routes[].rewrite.host</code></h3>

| | |
|---|---|
| Syntax | `host: <string>` |
| Default | `none` |
| Context | `routes[].rewrite` |
| Reload | applies on reload |

Host sent upstream (implies `preserve_host: false`), `host` or `host:port`.


<h3 id="routes-.rewrite.path"><code>routes[].rewrite.path</code></h3>

| | |
|---|---|
| Syntax | `path: <string>` |
| Default | `none` |
| Context | `routes[].rewrite` |
| Reload | applies on reload |

Full path; `$1`..`$9` from a regex route, `$0` the match, `$$` a literal `$`; `?...` in it sets the query (else the query is kept).


<h3 id="routes-.rewrite.prefix"><code>routes[].rewrite.prefix</code></h3>

| | |
|---|---|
| Syntax | `prefix: <string>` |
| Default | `none` |
| Context | `routes[].rewrite` |
| Reload | applies on reload |

Replaces the matched prefix (prefix routes only).


<h3 id="routes-.runtime"><code>routes[].runtime</code></h3>

| | |
|---|---|
| Syntax | `runtime: {...}` |
| Default | `required` |
| Context | `routes[]` |
| Reload | applies on reload |

Runtime that handles requests under the path.


<h3 id="routes-.runtime.static.index"><code>routes[].runtime&lt;static&gt;.index</code></h3>

| | |
|---|---|
| Syntax | `index: [<string>, ...]` |
| Default | `["index.html"]` |
| Context | `routes[].runtime (type: static)` |
| Reload | applies on reload |

File names served for a directory request, tried in order.


<h3 id="routes-.runtime.static.precompressed"><code>routes[].runtime&lt;static&gt;.precompressed</code></h3>

| | |
|---|---|
| Syntax | `precompressed: true \| false` |
| Default | `false` |
| Context | `routes[].runtime (type: static)` |
| Reload | applies on reload |

Serve `<file>.br` / `<file>.gz` siblings to clients that accept them.


<h3 id="routes-.runtime.static.root"><code>routes[].runtime&lt;static&gt;.root</code></h3>

| | |
|---|---|
| Syntax | `root: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: static)` |
| Reload | applies on reload |

Document root. Defaults to the application's `root`.


<h3 id="routes-.runtime.proxy.backends"><code>routes[].runtime&lt;proxy&gt;.backends</code></h3>

| | |
|---|---|
| Syntax | `backends: [{...}, ...]` |
| Default | `none` |
| Context | `routes[].runtime (type: proxy)` |
| Reload | applies on reload |

Weighted split per request across pools (alternative to `upstream`).


<h3 id="routes-.runtime.proxy.backends-.pool"><code>routes[].runtime&lt;proxy&gt;.backends[].pool</code></h3>

| | |
|---|---|
| Syntax | `pool: <string>` |
| Default | `none` |
| Context | `routes[].runtime<proxy>.backends[]` |
| Reload | applies on reload |

Name of a pool in `upstreams`; alternative to `status`.


<h3 id="routes-.runtime.proxy.backends-.status"><code>routes[].runtime&lt;proxy&gt;.backends[].status</code></h3>

| | |
|---|---|
| Syntax | `status: <integer>` |
| Default | `none` |
| Context | `routes[].runtime<proxy>.backends[]` |
| Reload | applies on reload |

Answers this share of the requests with this status (500-599) instead of sending them to a pool.


<h3 id="routes-.runtime.proxy.backends-.weight"><code>routes[].runtime&lt;proxy&gt;.backends[].weight</code></h3>

| | |
|---|---|
| Syntax | `weight: <integer>` |
| Default | `1` |
| Context | `routes[].runtime<proxy>.backends[]` |
| Reload | applies on reload |

Share of requests (0..=1000); 0 sends none.


<h3 id="routes-.runtime.proxy.client"><code>routes[].runtime&lt;proxy&gt;.client</code></h3>

| | |
|---|---|
| Syntax | `client: hyper \| experimental` |
| Default | `none` |
| Context | `routes[].runtime (type: proxy)` |
| Reload | applies on reload |

HTTP/1 client used towards this upstream; unset: `server.upstream_client`.


<h3 id="routes-.runtime.proxy.connect_timeout"><code>routes[].runtime&lt;proxy&gt;.connect_timeout</code></h3>

| | |
|---|---|
| Syntax | `connect_timeout: <duration> (e.g. 30s)` |
| Default | `5s` |
| Context | `routes[].runtime (type: proxy)` |
| Reload | applies on reload |

Time to establish a connection to the upstream.


<h3 id="routes-.runtime.proxy.preserve_host"><code>routes[].runtime&lt;proxy&gt;.preserve_host</code></h3>

| | |
|---|---|
| Syntax | `preserve_host: true \| false` |
| Default | `true` |
| Context | `routes[].runtime (type: proxy)` |
| Reload | applies on reload |

Forward the client's Host header (default) instead of the upstream authority.


<h3 id="routes-.runtime.proxy.response_timeout"><code>routes[].runtime&lt;proxy&gt;.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `routes[].runtime (type: proxy)` |
| Reload | applies on reload |

Time allowed for the upstream to return response headers.


<h3 id="routes-.runtime.proxy.tls_ca_file"><code>routes[].runtime&lt;proxy&gt;.tls_ca_file</code></h3>

| | |
|---|---|
| Syntax | `tls_ca_file: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: proxy)` |
| Reload | applies on reload |

Extra CA bundle (PEM) trusted for `https://` upstreams, in addition to the system roots.


<h3 id="routes-.runtime.proxy.upstream"><code>routes[].runtime&lt;proxy&gt;.upstream</code></h3>

| | |
|---|---|
| Syntax | `upstream: <string> \| {...}` |
| Default | `none` |
| Context | `routes[].runtime (type: proxy)` |
| Reload | applies on reload |

`http://host:port`, `https://host:port` or `unix:/absolute/path.sock` (one address, no retries), or `{pool: name}`: a pool from `upstreams`.


<h3 id="routes-.runtime.proxy.upstream.pool"><code>routes[].runtime&lt;proxy&gt;.upstream.pool</code></h3>

| | |
|---|---|
| Syntax | `pool: <string>` |
| Default | `required` |
| Context | `routes[].runtime<proxy>.upstream` |
| Reload | applies on reload |

Name of a pool in `upstreams`.


<h3 id="routes-.runtime.proxy.websocket"><code>routes[].runtime&lt;proxy&gt;.websocket</code></h3>

| | |
|---|---|
| Syntax | `websocket: true \| false` |
| Default | `true` |
| Context | `routes[].runtime (type: proxy)` |
| Reload | applies on reload |

Allow WebSocket upgrades to be tunnelled to this upstream.


<h3 id="routes-.runtime.respond.body"><code>routes[].runtime&lt;respond&gt;.body</code></h3>

| | |
|---|---|
| Syntax | `body: <string>` |
| Default | `` |
| Context | `routes[].runtime (type: respond)` |
| Reload | applies on reload |

Response body (at most 64 KiB).


<h3 id="routes-.runtime.respond.content_type"><code>routes[].runtime&lt;respond&gt;.content_type</code></h3>

| | |
|---|---|
| Syntax | `content_type: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: respond)` |
| Reload | applies on reload |

`Content-Type` of the response; default `text/plain; charset=utf-8`.


<h3 id="routes-.runtime.respond.status"><code>routes[].runtime&lt;respond&gt;.status</code></h3>

| | |
|---|---|
| Syntax | `status: <integer>` |
| Default | `200` |
| Context | `routes[].runtime (type: respond)` |
| Reload | applies on reload |

HTTP status of the fixed response (200-599).


<h3 id="routes-.runtime.redirect.host"><code>routes[].runtime&lt;redirect&gt;.host</code></h3>

| | |
|---|---|
| Syntax | `host: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: redirect)` |
| Reload | applies on reload |

Replaces the request's host; unset: taken from the request.


<h3 id="routes-.runtime.redirect.keep_path"><code>routes[].runtime&lt;redirect&gt;.keep_path</code></h3>

| | |
|---|---|
| Syntax | `keep_path: true \| false` |
| Default | `true` |
| Context | `routes[].runtime (type: redirect)` |
| Reload | applies on reload |

Append the request's path and query to `to`.


<h3 id="routes-.runtime.redirect.path"><code>routes[].runtime&lt;redirect&gt;.path</code></h3>

| | |
|---|---|
| Syntax | `path: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: redirect)` |
| Reload | applies on reload |

Replaces the request's path; unset: taken from the request.


<h3 id="routes-.runtime.redirect.port"><code>routes[].runtime&lt;redirect&gt;.port</code></h3>

| | |
|---|---|
| Syntax | `port: <integer>` |
| Default | `none` |
| Context | `routes[].runtime (type: redirect)` |
| Reload | applies on reload |

Replaces the request's port; unset: the well-known port of a configured `scheme`, else taken from the request.


<h3 id="routes-.runtime.redirect.prefix"><code>routes[].runtime&lt;redirect&gt;.prefix</code></h3>

| | |
|---|---|
| Syntax | `prefix: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: redirect)` |
| Reload | applies on reload |

Replaces the matched prefix of the request's path; unset: taken from the request.


<h3 id="routes-.runtime.redirect.scheme"><code>routes[].runtime&lt;redirect&gt;.scheme</code></h3>

| | |
|---|---|
| Syntax | `scheme: http \| https` |
| Default | `none` |
| Context | `routes[].runtime (type: redirect)` |
| Reload | applies on reload |

Replaces the request's scheme; unset: taken from the request.


<h3 id="routes-.runtime.redirect.status"><code>routes[].runtime&lt;redirect&gt;.status</code></h3>

| | |
|---|---|
| Syntax | `status: <integer>` |
| Default | `301` |
| Context | `routes[].runtime (type: redirect)` |
| Reload | applies on reload |

301, 302, 303, 307 or 308.


<h3 id="routes-.runtime.redirect.to"><code>routes[].runtime&lt;redirect&gt;.to</code></h3>

| | |
|---|---|
| Syntax | `to: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: redirect)` |
| Reload | applies on reload |

Target origin, e.g. `https://example.com`: scheme and host (and port), no path when `keep_path` is on. Alternative to the fields `scheme`, `host`, `port`, `path` and `prefix`.


<h3 id="routes-.runtime.php.fastcgi"><code>routes[].runtime&lt;php&gt;.fastcgi</code></h3>

| | |
|---|---|
| Syntax | `fastcgi: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: php)` |
| Reload | applies on reload |

External pool: `unix:/path.sock` or `tcp:host:port`. Mutually exclusive with `fpm`.


<h3 id="routes-.runtime.php.fpm"><code>routes[].runtime&lt;php&gt;.fpm</code></h3>

| | |
|---|---|
| Syntax | `fpm: {...}` |
| Default | `none` |
| Context | `routes[].runtime (type: php)` |
| Reload | applies on reload |

Managed PHP-FPM pool settings (workers, ini values); not used with `fastcgi`.


<h3 id="routes-.runtime.php.fpm.binary"><code>routes[].runtime&lt;php&gt;.fpm.binary</code></h3>

| | |
|---|---|
| Syntax | `binary: <string>` |
| Default | `none` |
| Context | `routes[].runtime<php>.fpm` |
| Reload | applies on reload |

PHP-FPM binary; default: `php-fpm` on `PATH`, else the newest versioned one (`php-fpm8.4`, Alpine's `php-fpm84`).


<h3 id="routes-.runtime.php.fpm.env"><code>routes[].runtime&lt;php&gt;.fpm.env</code></h3>

| | |
|---|---|
| Syntax | `env: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `routes[].runtime<php>.fpm` |
| Reload | applies on reload |

Environment passed to PHP (`env[...]`).


<h3 id="routes-.runtime.php.fpm.ini"><code>routes[].runtime&lt;php&gt;.fpm.ini</code></h3>

| | |
|---|---|
| Syntax | `ini: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `routes[].runtime<php>.fpm` |
| Reload | applies on reload |

`php_admin_value[...]` settings, e.g. `memory_limit: 256M`.


<h3 id="routes-.runtime.php.fpm.max_requests"><code>routes[].runtime&lt;php&gt;.fpm.max_requests</code></h3>

| | |
|---|---|
| Syntax | `max_requests: <integer>` |
| Default | `500` |
| Context | `routes[].runtime<php>.fpm` |
| Reload | applies on reload |

`pm.max_requests`; 0 disables recycling.


<h3 id="routes-.runtime.php.fpm.workers"><code>routes[].runtime&lt;php&gt;.fpm.workers</code></h3>

| | |
|---|---|
| Syntax | `workers: {...}` |
| Default | `none` |
| Context | `routes[].runtime<php>.fpm` |
| Reload | applies on reload |

`min` = `pm.start_servers`/`pm.min_spare_servers`, `max` = `pm.max_children`.


<h3 id="routes-.runtime.php.fpm.workers.autoscale"><code>routes[].runtime&lt;php&gt;.fpm.workers.autoscale</code></h3>

| | |
|---|---|
| Syntax | `autoscale: off \| auto \| recommend` |
| Default | `recommend` |
| Context | `routes[].runtime<php>.fpm.workers` |
| Reload | applies on reload |

`off`, `recommend` (default) or `auto` (ADR-0014).


<h3 id="routes-.runtime.php.fpm.workers.max"><code>routes[].runtime&lt;php&gt;.fpm.workers.max</code></h3>

| | |
|---|---|
| Syntax | `max: <integer>` |
| Default | `required` |
| Context | `routes[].runtime<php>.fpm.workers` |
| Reload | applies on reload |

Upper bound when the pool is scaled.


<h3 id="routes-.runtime.php.fpm.workers.min"><code>routes[].runtime&lt;php&gt;.fpm.workers.min</code></h3>

| | |
|---|---|
| Syntax | `min: <integer>` |
| Default | `required` |
| Context | `routes[].runtime<php>.fpm.workers` |
| Reload | applies on reload |

Processes started at the beginning and kept at least.


<h3 id="routes-.runtime.php.fpm.workers.target_concurrency"><code>routes[].runtime&lt;php&gt;.fpm.workers.target_concurrency</code></h3>

| | |
|---|---|
| Syntax | `target_concurrency: <integer>` |
| Default | `none` |
| Context | `routes[].runtime<php>.fpm.workers` |
| Reload | applies on reload |

Concurrent requests one worker is expected to handle well (utilisation basis).


<h3 id="routes-.runtime.php.front_controller"><code>routes[].runtime&lt;php&gt;.front_controller</code></h3>

| | |
|---|---|
| Syntax | `front_controller: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: php)` |
| Reload | applies on reload |

Script that handles requests for paths that do not exist, e.g. `/index.php`.


<h3 id="routes-.runtime.php.index"><code>routes[].runtime&lt;php&gt;.index</code></h3>

| | |
|---|---|
| Syntax | `index: [<string>, ...]` |
| Default | `["index.php","index.html"]` |
| Context | `routes[].runtime (type: php)` |
| Reload | applies on reload |

Index files for directory requests, tried in order.


<h3 id="routes-.runtime.php.response_timeout"><code>routes[].runtime&lt;php&gt;.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `routes[].runtime (type: php)` |
| Reload | applies on reload |

Time to wait for PHP-FPM's response headers.


<h3 id="routes-.runtime.php.root"><code>routes[].runtime&lt;php&gt;.root</code></h3>

| | |
|---|---|
| Syntax | `root: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: php)` |
| Reload | applies on reload |

Document root; defaults to the application `root`.


<h3 id="routes-.runtime.php.startup_timeout"><code>routes[].runtime&lt;php&gt;.startup_timeout</code></h3>

| | |
|---|---|
| Syntax | `startup_timeout: <duration> (e.g. 30s)` |
| Default | `30s` |
| Context | `routes[].runtime (type: php)` |
| Reload | applies on reload |

Time the managed PHP-FPM pool gets to become ready.


<h3 id="routes-.runtime.php.stop_timeout"><code>routes[].runtime&lt;php&gt;.stop_timeout</code></h3>

| | |
|---|---|
| Syntax | `stop_timeout: <duration> (e.g. 30s)` |
| Default | `10s` |
| Context | `routes[].runtime (type: php)` |
| Reload | applies on reload |

Time the managed pool gets to exit before it is killed.


<h3 id="routes-.runtime.node.command"><code>routes[].runtime&lt;node&gt;.command</code></h3>

| | |
|---|---|
| Syntax | `command: [<string>, ...]` |
| Default | `[]` |
| Context | `routes[].runtime (type: node)` |
| Reload | applies on reload |

Command started by scalws (no shell), e.g. `[node, server.js]`; the application listens on `PORT`.


<h3 id="routes-.runtime.node.env"><code>routes[].runtime&lt;node&gt;.env</code></h3>

| | |
|---|---|
| Syntax | `env: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `routes[].runtime (type: node)` |
| Reload | applies on reload |

Environment variables for the process.


<h3 id="routes-.runtime.node.health_path"><code>routes[].runtime&lt;node&gt;.health_path</code></h3>

| | |
|---|---|
| Syntax | `health_path: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: node)` |
| Reload | applies on reload |

Optional readiness path; any non-5xx answer counts as ready.


<h3 id="routes-.runtime.node.listen"><code>routes[].runtime&lt;node&gt;.listen</code></h3>

| | |
|---|---|
| Syntax | `listen: unix \| tcp` |
| Default | `unix` |
| Context | `routes[].runtime (type: node)` |
| Reload | applies on reload |

`unix`: a socket under `runtime_dir` passed as `PORT`; `tcp`: a free loopback port.


<h3 id="routes-.runtime.node.response_timeout"><code>routes[].runtime&lt;node&gt;.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `routes[].runtime (type: node)` |
| Reload | applies on reload |

Time to wait for the response headers of the application.


<h3 id="routes-.runtime.node.startup_timeout"><code>routes[].runtime&lt;node&gt;.startup_timeout</code></h3>

| | |
|---|---|
| Syntax | `startup_timeout: <duration> (e.g. 30s)` |
| Default | `30s` |
| Context | `routes[].runtime (type: node)` |
| Reload | applies on reload |

Time the process gets to become ready.


<h3 id="routes-.runtime.node.stop_timeout"><code>routes[].runtime&lt;node&gt;.stop_timeout</code></h3>

| | |
|---|---|
| Syntax | `stop_timeout: <duration> (e.g. 30s)` |
| Default | `10s` |
| Context | `routes[].runtime (type: node)` |
| Reload | applies on reload |

Time the process gets to exit after SIGTERM before it is killed.


<h3 id="routes-.runtime.node.upstream"><code>routes[].runtime&lt;node&gt;.upstream</code></h3>

| | |
|---|---|
| Syntax | `upstream: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: node)` |
| Reload | applies on reload |

Proxy to a Node.js process managed elsewhere instead of starting one.


<h3 id="routes-.runtime.node.workers"><code>routes[].runtime&lt;node&gt;.workers</code></h3>

| | |
|---|---|
| Syntax | `workers: {...}` |
| Default | `none` |
| Context | `routes[].runtime (type: node)` |
| Reload | applies on reload |

Number of processes (`min`); requests are balanced across ready ones.


<h3 id="routes-.runtime.node.workers.autoscale"><code>routes[].runtime&lt;node&gt;.workers.autoscale</code></h3>

| | |
|---|---|
| Syntax | `autoscale: off \| auto \| recommend` |
| Default | `recommend` |
| Context | `routes[].runtime<node>.workers` |
| Reload | applies on reload |

`off`, `recommend` (default) or `auto` (ADR-0014).


<h3 id="routes-.runtime.node.workers.max"><code>routes[].runtime&lt;node&gt;.workers.max</code></h3>

| | |
|---|---|
| Syntax | `max: <integer>` |
| Default | `required` |
| Context | `routes[].runtime<node>.workers` |
| Reload | applies on reload |

Upper bound when the pool is scaled.


<h3 id="routes-.runtime.node.workers.min"><code>routes[].runtime&lt;node&gt;.workers.min</code></h3>

| | |
|---|---|
| Syntax | `min: <integer>` |
| Default | `required` |
| Context | `routes[].runtime<node>.workers` |
| Reload | applies on reload |

Processes started at the beginning and kept at least.


<h3 id="routes-.runtime.node.workers.target_concurrency"><code>routes[].runtime&lt;node&gt;.workers.target_concurrency</code></h3>

| | |
|---|---|
| Syntax | `target_concurrency: <integer>` |
| Default | `none` |
| Context | `routes[].runtime<node>.workers` |
| Reload | applies on reload |

Concurrent requests one worker is expected to handle well (utilisation basis).


<h3 id="routes-.runtime.python.app"><code>routes[].runtime&lt;python&gt;.app</code></h3>

| | |
|---|---|
| Syntax | `app: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

`module:callable`, e.g. `app:app` or `mysite.wsgi:application`.


<h3 id="routes-.runtime.python.command"><code>routes[].runtime&lt;python&gt;.command</code></h3>

| | |
|---|---|
| Syntax | `command: [<string>, ...]` |
| Default | `[]` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

Explicit argv. Bind arguments are appended for uvicorn/hypercorn/gunicorn unless the argv already contains `{socket}` or `{port}`.


<h3 id="routes-.runtime.python.env"><code>routes[].runtime&lt;python&gt;.env</code></h3>

| | |
|---|---|
| Syntax | `env: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

Environment variables for the processes.


<h3 id="routes-.runtime.python.health_path"><code>routes[].runtime&lt;python&gt;.health_path</code></h3>

| | |
|---|---|
| Syntax | `health_path: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

Path requested to decide that a worker is ready and healthy.


<h3 id="routes-.runtime.python.listen"><code>routes[].runtime&lt;python&gt;.listen</code></h3>

| | |
|---|---|
| Syntax | `listen: unix \| tcp` |
| Default | `unix` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

`unix`: a socket under `runtime_dir`; `tcp`: a free loopback port.


<h3 id="routes-.runtime.python.mode"><code>routes[].runtime&lt;python&gt;.mode</code></h3>

| | |
|---|---|
| Syntax | `mode: asgi \| wsgi` |
| Default | `required` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

`asgi` (uvicorn) or `wsgi` (gunicorn).


<h3 id="routes-.runtime.python.process_pool"><code>routes[].runtime&lt;python&gt;.process_pool</code></h3>

| | |
|---|---|
| Syntax | `process_pool: true \| false` |
| Default | `false` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

scalws runs `workers.min..max` single-worker server processes itself instead of one server with `--workers`, so the pool can be scaled and restarted live (ADR-0014). Trades the server's copy-on-write sharing for scaling.


<h3 id="routes-.runtime.python.response_timeout"><code>routes[].runtime&lt;python&gt;.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

Time to wait for the response headers of the application.


<h3 id="routes-.runtime.python.server"><code>routes[].runtime&lt;python&gt;.server</code></h3>

| | |
|---|---|
| Syntax | `server: uvicorn \| hypercorn \| gunicorn` |
| Default | `none` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

Default: uvicorn for ASGI, gunicorn for WSGI.


<h3 id="routes-.runtime.python.startup_timeout"><code>routes[].runtime&lt;python&gt;.startup_timeout</code></h3>

| | |
|---|---|
| Syntax | `startup_timeout: <duration> (e.g. 30s)` |
| Default | `30s` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

Time the processes get to become ready.


<h3 id="routes-.runtime.python.stop_timeout"><code>routes[].runtime&lt;python&gt;.stop_timeout</code></h3>

| | |
|---|---|
| Syntax | `stop_timeout: <duration> (e.g. 30s)` |
| Default | `10s` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

Time the processes get to exit after SIGTERM before they are killed.


<h3 id="routes-.runtime.python.upstream"><code>routes[].runtime&lt;python&gt;.upstream</code></h3>

| | |
|---|---|
| Syntax | `upstream: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

Proxy to a Python server managed elsewhere instead of starting one.


<h3 id="routes-.runtime.python.virtualenv"><code>routes[].runtime&lt;python&gt;.virtualenv</code></h3>

| | |
|---|---|
| Syntax | `virtualenv: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

Virtual environment whose server binary and packages are used.


<h3 id="routes-.runtime.python.workers"><code>routes[].runtime&lt;python&gt;.workers</code></h3>

| | |
|---|---|
| Syntax | `workers: {...}` |
| Default | `none` |
| Context | `routes[].runtime (type: python)` |
| Reload | applies on reload |

Worker processes of the application server (`min`).


<h3 id="routes-.runtime.python.workers.autoscale"><code>routes[].runtime&lt;python&gt;.workers.autoscale</code></h3>

| | |
|---|---|
| Syntax | `autoscale: off \| auto \| recommend` |
| Default | `recommend` |
| Context | `routes[].runtime<python>.workers` |
| Reload | applies on reload |

`off`, `recommend` (default) or `auto` (ADR-0014).


<h3 id="routes-.runtime.python.workers.max"><code>routes[].runtime&lt;python&gt;.workers.max</code></h3>

| | |
|---|---|
| Syntax | `max: <integer>` |
| Default | `required` |
| Context | `routes[].runtime<python>.workers` |
| Reload | applies on reload |

Upper bound when the pool is scaled.


<h3 id="routes-.runtime.python.workers.min"><code>routes[].runtime&lt;python&gt;.workers.min</code></h3>

| | |
|---|---|
| Syntax | `min: <integer>` |
| Default | `required` |
| Context | `routes[].runtime<python>.workers` |
| Reload | applies on reload |

Processes started at the beginning and kept at least.


<h3 id="routes-.runtime.python.workers.target_concurrency"><code>routes[].runtime&lt;python&gt;.workers.target_concurrency</code></h3>

| | |
|---|---|
| Syntax | `target_concurrency: <integer>` |
| Default | `none` |
| Context | `routes[].runtime<python>.workers` |
| Reload | applies on reload |

Concurrent requests one worker is expected to handle well (utilisation basis).


<h3 id="routes-.runtime.container.command"><code>routes[].runtime&lt;container&gt;.command</code></h3>

| | |
|---|---|
| Syntax | `command: [<string>, ...]` |
| Default | `[]` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Arguments after the image; `{port}` is replaced by the port scalws chose.


<h3 id="routes-.runtime.container.drop_capabilities"><code>routes[].runtime&lt;container&gt;.drop_capabilities</code></h3>

| | |
|---|---|
| Syntax | `drop_capabilities: true \| false` |
| Default | `false` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Drop all Linux capabilities.


<h3 id="routes-.runtime.container.engine"><code>routes[].runtime&lt;container&gt;.engine</code></h3>

| | |
|---|---|
| Syntax | `engine: podman \| docker` |
| Default | `podman` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Container engine: `podman` or `docker`.


<h3 id="routes-.runtime.container.engine_path"><code>routes[].runtime&lt;container&gt;.engine_path</code></h3>

| | |
|---|---|
| Syntax | `engine_path: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Engine binary; default `podman` / `docker` from `PATH`.


<h3 id="routes-.runtime.container.env"><code>routes[].runtime&lt;container&gt;.env</code></h3>

| | |
|---|---|
| Syntax | `env: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Environment variables for the containers.


<h3 id="routes-.runtime.container.health_path"><code>routes[].runtime&lt;container&gt;.health_path</code></h3>

| | |
|---|---|
| Syntax | `health_path: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Path requested to decide that a container is ready and healthy.


<h3 id="routes-.runtime.container.image"><code>routes[].runtime&lt;container&gt;.image</code></h3>

| | |
|---|---|
| Syntax | `image: <string>` |
| Default | `required` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Image reference, e.g. `docker.io/library/nginx:1.27`.


<h3 id="routes-.runtime.container.mounts"><code>routes[].runtime&lt;container&gt;.mounts</code></h3>

| | |
|---|---|
| Syntax | `mounts: [{...}, ...]` |
| Default | `[]` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Host directories mounted into the containers.


<h3 id="routes-.runtime.container.mounts-.read_only"><code>routes[].runtime&lt;container&gt;.mounts[].read_only</code></h3>

| | |
|---|---|
| Syntax | `read_only: true \| false` |
| Default | `true` |
| Context | `routes[].runtime<container>.mounts[]` |
| Reload | applies on reload |

Mount read-only.


<h3 id="routes-.runtime.container.mounts-.source"><code>routes[].runtime&lt;container&gt;.mounts[].source</code></h3>

| | |
|---|---|
| Syntax | `source: <string>` |
| Default | `required` |
| Context | `routes[].runtime<container>.mounts[]` |
| Reload | applies on reload |

Host path (absolute).


<h3 id="routes-.runtime.container.mounts-.target"><code>routes[].runtime&lt;container&gt;.mounts[].target</code></h3>

| | |
|---|---|
| Syntax | `target: <string>` |
| Default | `required` |
| Context | `routes[].runtime<container>.mounts[]` |
| Reload | applies on reload |

Path inside the container (absolute).


<h3 id="routes-.runtime.container.network"><code>routes[].runtime&lt;container&gt;.network</code></h3>

| | |
|---|---|
| Syntax | `network: bridge \| host` |
| Default | `bridge` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

`bridge`: publish `port` on a loopback port; `host`: share the host network.


<h3 id="routes-.runtime.container.port"><code>routes[].runtime&lt;container&gt;.port</code></h3>

| | |
|---|---|
| Syntax | `port: <integer>` |
| Default | `none` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Port the application listens on inside the container (`bridge` networking).


<h3 id="routes-.runtime.container.pull"><code>routes[].runtime&lt;container&gt;.pull</code></h3>

| | |
|---|---|
| Syntax | `pull: missing \| always \| never` |
| Default | `missing` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

When the image is pulled: `missing`, `always` or `never`.


<h3 id="routes-.runtime.container.read_only"><code>routes[].runtime&lt;container&gt;.read_only</code></h3>

| | |
|---|---|
| Syntax | `read_only: true \| false` |
| Default | `false` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Read-only root filesystem (a tmpfs is mounted at `/tmp`).


<h3 id="routes-.runtime.container.response_timeout"><code>routes[].runtime&lt;container&gt;.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Time to wait for the response headers of the application.


<h3 id="routes-.runtime.container.startup_timeout"><code>routes[].runtime&lt;container&gt;.startup_timeout</code></h3>

| | |
|---|---|
| Syntax | `startup_timeout: <duration> (e.g. 30s)` |
| Default | `120s` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Time a container gets to become ready (includes pulling the image).


<h3 id="routes-.runtime.container.stop_timeout"><code>routes[].runtime&lt;container&gt;.stop_timeout</code></h3>

| | |
|---|---|
| Syntax | `stop_timeout: <duration> (e.g. 30s)` |
| Default | `10s` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Time a container gets to stop before it is killed.


<h3 id="routes-.runtime.container.user"><code>routes[].runtime&lt;container&gt;.user</code></h3>

| | |
|---|---|
| Syntax | `user: <string>` |
| Default | `none` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

User the container runs as (`--user`).


<h3 id="routes-.runtime.container.workers"><code>routes[].runtime&lt;container&gt;.workers</code></h3>

| | |
|---|---|
| Syntax | `workers: {...}` |
| Default | `none` |
| Context | `routes[].runtime (type: container)` |
| Reload | applies on reload |

Number of containers (`min` at start; scaled between `min` and `max`).


<h3 id="routes-.runtime.container.workers.autoscale"><code>routes[].runtime&lt;container&gt;.workers.autoscale</code></h3>

| | |
|---|---|
| Syntax | `autoscale: off \| auto \| recommend` |
| Default | `recommend` |
| Context | `routes[].runtime<container>.workers` |
| Reload | applies on reload |

`off`, `recommend` (default) or `auto` (ADR-0014).


<h3 id="routes-.runtime.container.workers.max"><code>routes[].runtime&lt;container&gt;.workers.max</code></h3>

| | |
|---|---|
| Syntax | `max: <integer>` |
| Default | `required` |
| Context | `routes[].runtime<container>.workers` |
| Reload | applies on reload |

Upper bound when the pool is scaled.


<h3 id="routes-.runtime.container.workers.min"><code>routes[].runtime&lt;container&gt;.workers.min</code></h3>

| | |
|---|---|
| Syntax | `min: <integer>` |
| Default | `required` |
| Context | `routes[].runtime<container>.workers` |
| Reload | applies on reload |

Processes started at the beginning and kept at least.


<h3 id="routes-.runtime.container.workers.target_concurrency"><code>routes[].runtime&lt;container&gt;.workers.target_concurrency</code></h3>

| | |
|---|---|
| Syntax | `target_concurrency: <integer>` |
| Default | `none` |
| Context | `routes[].runtime<container>.workers` |
| Reload | applies on reload |

Concurrent requests one worker is expected to handle well (utilisation basis).


<h3 id="runtime"><code>runtime</code></h3>

| | |
|---|---|
| Syntax | `runtime: {...}` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

The full runtime syntax of `scalws.yaml`, instead of a shorthand above.


<h3 id="runtime.static.index"><code>runtime&lt;static&gt;.index</code></h3>

| | |
|---|---|
| Syntax | `index: [<string>, ...]` |
| Default | `["index.html"]` |
| Context | `runtime (type: static)` |
| Reload | applies on reload |

File names served for a directory request, tried in order.


<h3 id="runtime.static.precompressed"><code>runtime&lt;static&gt;.precompressed</code></h3>

| | |
|---|---|
| Syntax | `precompressed: true \| false` |
| Default | `false` |
| Context | `runtime (type: static)` |
| Reload | applies on reload |

Serve `<file>.br` / `<file>.gz` siblings to clients that accept them.


<h3 id="runtime.static.root"><code>runtime&lt;static&gt;.root</code></h3>

| | |
|---|---|
| Syntax | `root: <string>` |
| Default | `none` |
| Context | `runtime (type: static)` |
| Reload | applies on reload |

Document root. Defaults to the application's `root`.


<h3 id="runtime.proxy.backends"><code>runtime&lt;proxy&gt;.backends</code></h3>

| | |
|---|---|
| Syntax | `backends: [{...}, ...]` |
| Default | `none` |
| Context | `runtime (type: proxy)` |
| Reload | applies on reload |

Weighted split per request across pools (alternative to `upstream`).


<h3 id="runtime.proxy.backends-.pool"><code>runtime&lt;proxy&gt;.backends[].pool</code></h3>

| | |
|---|---|
| Syntax | `pool: <string>` |
| Default | `none` |
| Context | `runtime<proxy>.backends[]` |
| Reload | applies on reload |

Name of a pool in `upstreams`; alternative to `status`.


<h3 id="runtime.proxy.backends-.status"><code>runtime&lt;proxy&gt;.backends[].status</code></h3>

| | |
|---|---|
| Syntax | `status: <integer>` |
| Default | `none` |
| Context | `runtime<proxy>.backends[]` |
| Reload | applies on reload |

Answers this share of the requests with this status (500-599) instead of sending them to a pool.


<h3 id="runtime.proxy.backends-.weight"><code>runtime&lt;proxy&gt;.backends[].weight</code></h3>

| | |
|---|---|
| Syntax | `weight: <integer>` |
| Default | `1` |
| Context | `runtime<proxy>.backends[]` |
| Reload | applies on reload |

Share of requests (0..=1000); 0 sends none.


<h3 id="runtime.proxy.client"><code>runtime&lt;proxy&gt;.client</code></h3>

| | |
|---|---|
| Syntax | `client: hyper \| experimental` |
| Default | `none` |
| Context | `runtime (type: proxy)` |
| Reload | applies on reload |

HTTP/1 client used towards this upstream; unset: `server.upstream_client`.


<h3 id="runtime.proxy.connect_timeout"><code>runtime&lt;proxy&gt;.connect_timeout</code></h3>

| | |
|---|---|
| Syntax | `connect_timeout: <duration> (e.g. 30s)` |
| Default | `5s` |
| Context | `runtime (type: proxy)` |
| Reload | applies on reload |

Time to establish a connection to the upstream.


<h3 id="runtime.proxy.preserve_host"><code>runtime&lt;proxy&gt;.preserve_host</code></h3>

| | |
|---|---|
| Syntax | `preserve_host: true \| false` |
| Default | `true` |
| Context | `runtime (type: proxy)` |
| Reload | applies on reload |

Forward the client's Host header (default) instead of the upstream authority.


<h3 id="runtime.proxy.response_timeout"><code>runtime&lt;proxy&gt;.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `runtime (type: proxy)` |
| Reload | applies on reload |

Time allowed for the upstream to return response headers.


<h3 id="runtime.proxy.tls_ca_file"><code>runtime&lt;proxy&gt;.tls_ca_file</code></h3>

| | |
|---|---|
| Syntax | `tls_ca_file: <string>` |
| Default | `none` |
| Context | `runtime (type: proxy)` |
| Reload | applies on reload |

Extra CA bundle (PEM) trusted for `https://` upstreams, in addition to the system roots.


<h3 id="runtime.proxy.upstream"><code>runtime&lt;proxy&gt;.upstream</code></h3>

| | |
|---|---|
| Syntax | `upstream: <string> \| {...}` |
| Default | `none` |
| Context | `runtime (type: proxy)` |
| Reload | applies on reload |

`http://host:port`, `https://host:port` or `unix:/absolute/path.sock` (one address, no retries), or `{pool: name}`: a pool from `upstreams`.


<h3 id="runtime.proxy.upstream.pool"><code>runtime&lt;proxy&gt;.upstream.pool</code></h3>

| | |
|---|---|
| Syntax | `pool: <string>` |
| Default | `required` |
| Context | `runtime<proxy>.upstream` |
| Reload | applies on reload |

Name of a pool in `upstreams`.


<h3 id="runtime.proxy.websocket"><code>runtime&lt;proxy&gt;.websocket</code></h3>

| | |
|---|---|
| Syntax | `websocket: true \| false` |
| Default | `true` |
| Context | `runtime (type: proxy)` |
| Reload | applies on reload |

Allow WebSocket upgrades to be tunnelled to this upstream.


<h3 id="runtime.respond.body"><code>runtime&lt;respond&gt;.body</code></h3>

| | |
|---|---|
| Syntax | `body: <string>` |
| Default | `` |
| Context | `runtime (type: respond)` |
| Reload | applies on reload |

Response body (at most 64 KiB).


<h3 id="runtime.respond.content_type"><code>runtime&lt;respond&gt;.content_type</code></h3>

| | |
|---|---|
| Syntax | `content_type: <string>` |
| Default | `none` |
| Context | `runtime (type: respond)` |
| Reload | applies on reload |

`Content-Type` of the response; default `text/plain; charset=utf-8`.


<h3 id="runtime.respond.status"><code>runtime&lt;respond&gt;.status</code></h3>

| | |
|---|---|
| Syntax | `status: <integer>` |
| Default | `200` |
| Context | `runtime (type: respond)` |
| Reload | applies on reload |

HTTP status of the fixed response (200-599).


<h3 id="runtime.redirect.host"><code>runtime&lt;redirect&gt;.host</code></h3>

| | |
|---|---|
| Syntax | `host: <string>` |
| Default | `none` |
| Context | `runtime (type: redirect)` |
| Reload | applies on reload |

Replaces the request's host; unset: taken from the request.


<h3 id="runtime.redirect.keep_path"><code>runtime&lt;redirect&gt;.keep_path</code></h3>

| | |
|---|---|
| Syntax | `keep_path: true \| false` |
| Default | `true` |
| Context | `runtime (type: redirect)` |
| Reload | applies on reload |

Append the request's path and query to `to`.


<h3 id="runtime.redirect.path"><code>runtime&lt;redirect&gt;.path</code></h3>

| | |
|---|---|
| Syntax | `path: <string>` |
| Default | `none` |
| Context | `runtime (type: redirect)` |
| Reload | applies on reload |

Replaces the request's path; unset: taken from the request.


<h3 id="runtime.redirect.port"><code>runtime&lt;redirect&gt;.port</code></h3>

| | |
|---|---|
| Syntax | `port: <integer>` |
| Default | `none` |
| Context | `runtime (type: redirect)` |
| Reload | applies on reload |

Replaces the request's port; unset: the well-known port of a configured `scheme`, else taken from the request.


<h3 id="runtime.redirect.prefix"><code>runtime&lt;redirect&gt;.prefix</code></h3>

| | |
|---|---|
| Syntax | `prefix: <string>` |
| Default | `none` |
| Context | `runtime (type: redirect)` |
| Reload | applies on reload |

Replaces the matched prefix of the request's path; unset: taken from the request.


<h3 id="runtime.redirect.scheme"><code>runtime&lt;redirect&gt;.scheme</code></h3>

| | |
|---|---|
| Syntax | `scheme: http \| https` |
| Default | `none` |
| Context | `runtime (type: redirect)` |
| Reload | applies on reload |

Replaces the request's scheme; unset: taken from the request.


<h3 id="runtime.redirect.status"><code>runtime&lt;redirect&gt;.status</code></h3>

| | |
|---|---|
| Syntax | `status: <integer>` |
| Default | `301` |
| Context | `runtime (type: redirect)` |
| Reload | applies on reload |

301, 302, 303, 307 or 308.


<h3 id="runtime.redirect.to"><code>runtime&lt;redirect&gt;.to</code></h3>

| | |
|---|---|
| Syntax | `to: <string>` |
| Default | `none` |
| Context | `runtime (type: redirect)` |
| Reload | applies on reload |

Target origin, e.g. `https://example.com`: scheme and host (and port), no path when `keep_path` is on. Alternative to the fields `scheme`, `host`, `port`, `path` and `prefix`.


<h3 id="runtime.php.fastcgi"><code>runtime&lt;php&gt;.fastcgi</code></h3>

| | |
|---|---|
| Syntax | `fastcgi: <string>` |
| Default | `none` |
| Context | `runtime (type: php)` |
| Reload | applies on reload |

External pool: `unix:/path.sock` or `tcp:host:port`. Mutually exclusive with `fpm`.


<h3 id="runtime.php.fpm"><code>runtime&lt;php&gt;.fpm</code></h3>

| | |
|---|---|
| Syntax | `fpm: {...}` |
| Default | `none` |
| Context | `runtime (type: php)` |
| Reload | applies on reload |

Managed PHP-FPM pool settings (workers, ini values); not used with `fastcgi`.


<h3 id="runtime.php.fpm.binary"><code>runtime&lt;php&gt;.fpm.binary</code></h3>

| | |
|---|---|
| Syntax | `binary: <string>` |
| Default | `none` |
| Context | `runtime<php>.fpm` |
| Reload | applies on reload |

PHP-FPM binary; default: `php-fpm` on `PATH`, else the newest versioned one (`php-fpm8.4`, Alpine's `php-fpm84`).


<h3 id="runtime.php.fpm.env"><code>runtime&lt;php&gt;.fpm.env</code></h3>

| | |
|---|---|
| Syntax | `env: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `runtime<php>.fpm` |
| Reload | applies on reload |

Environment passed to PHP (`env[...]`).


<h3 id="runtime.php.fpm.ini"><code>runtime&lt;php&gt;.fpm.ini</code></h3>

| | |
|---|---|
| Syntax | `ini: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `runtime<php>.fpm` |
| Reload | applies on reload |

`php_admin_value[...]` settings, e.g. `memory_limit: 256M`.


<h3 id="runtime.php.fpm.max_requests"><code>runtime&lt;php&gt;.fpm.max_requests</code></h3>

| | |
|---|---|
| Syntax | `max_requests: <integer>` |
| Default | `500` |
| Context | `runtime<php>.fpm` |
| Reload | applies on reload |

`pm.max_requests`; 0 disables recycling.


<h3 id="runtime.php.fpm.workers"><code>runtime&lt;php&gt;.fpm.workers</code></h3>

| | |
|---|---|
| Syntax | `workers: {...}` |
| Default | `none` |
| Context | `runtime<php>.fpm` |
| Reload | applies on reload |

`min` = `pm.start_servers`/`pm.min_spare_servers`, `max` = `pm.max_children`.


<h3 id="runtime.php.fpm.workers.autoscale"><code>runtime&lt;php&gt;.fpm.workers.autoscale</code></h3>

| | |
|---|---|
| Syntax | `autoscale: off \| auto \| recommend` |
| Default | `recommend` |
| Context | `runtime<php>.fpm.workers` |
| Reload | applies on reload |

`off`, `recommend` (default) or `auto` (ADR-0014).


<h3 id="runtime.php.fpm.workers.max"><code>runtime&lt;php&gt;.fpm.workers.max</code></h3>

| | |
|---|---|
| Syntax | `max: <integer>` |
| Default | `required` |
| Context | `runtime<php>.fpm.workers` |
| Reload | applies on reload |

Upper bound when the pool is scaled.


<h3 id="runtime.php.fpm.workers.min"><code>runtime&lt;php&gt;.fpm.workers.min</code></h3>

| | |
|---|---|
| Syntax | `min: <integer>` |
| Default | `required` |
| Context | `runtime<php>.fpm.workers` |
| Reload | applies on reload |

Processes started at the beginning and kept at least.


<h3 id="runtime.php.fpm.workers.target_concurrency"><code>runtime&lt;php&gt;.fpm.workers.target_concurrency</code></h3>

| | |
|---|---|
| Syntax | `target_concurrency: <integer>` |
| Default | `none` |
| Context | `runtime<php>.fpm.workers` |
| Reload | applies on reload |

Concurrent requests one worker is expected to handle well (utilisation basis).


<h3 id="runtime.php.front_controller"><code>runtime&lt;php&gt;.front_controller</code></h3>

| | |
|---|---|
| Syntax | `front_controller: <string>` |
| Default | `none` |
| Context | `runtime (type: php)` |
| Reload | applies on reload |

Script that handles requests for paths that do not exist, e.g. `/index.php`.


<h3 id="runtime.php.index"><code>runtime&lt;php&gt;.index</code></h3>

| | |
|---|---|
| Syntax | `index: [<string>, ...]` |
| Default | `["index.php","index.html"]` |
| Context | `runtime (type: php)` |
| Reload | applies on reload |

Index files for directory requests, tried in order.


<h3 id="runtime.php.response_timeout"><code>runtime&lt;php&gt;.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `runtime (type: php)` |
| Reload | applies on reload |

Time to wait for PHP-FPM's response headers.


<h3 id="runtime.php.root"><code>runtime&lt;php&gt;.root</code></h3>

| | |
|---|---|
| Syntax | `root: <string>` |
| Default | `none` |
| Context | `runtime (type: php)` |
| Reload | applies on reload |

Document root; defaults to the application `root`.


<h3 id="runtime.php.startup_timeout"><code>runtime&lt;php&gt;.startup_timeout</code></h3>

| | |
|---|---|
| Syntax | `startup_timeout: <duration> (e.g. 30s)` |
| Default | `30s` |
| Context | `runtime (type: php)` |
| Reload | applies on reload |

Time the managed PHP-FPM pool gets to become ready.


<h3 id="runtime.php.stop_timeout"><code>runtime&lt;php&gt;.stop_timeout</code></h3>

| | |
|---|---|
| Syntax | `stop_timeout: <duration> (e.g. 30s)` |
| Default | `10s` |
| Context | `runtime (type: php)` |
| Reload | applies on reload |

Time the managed pool gets to exit before it is killed.


<h3 id="runtime.node.command"><code>runtime&lt;node&gt;.command</code></h3>

| | |
|---|---|
| Syntax | `command: [<string>, ...]` |
| Default | `[]` |
| Context | `runtime (type: node)` |
| Reload | applies on reload |

Command started by scalws (no shell), e.g. `[node, server.js]`; the application listens on `PORT`.


<h3 id="runtime.node.env"><code>runtime&lt;node&gt;.env</code></h3>

| | |
|---|---|
| Syntax | `env: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `runtime (type: node)` |
| Reload | applies on reload |

Environment variables for the process.


<h3 id="runtime.node.health_path"><code>runtime&lt;node&gt;.health_path</code></h3>

| | |
|---|---|
| Syntax | `health_path: <string>` |
| Default | `none` |
| Context | `runtime (type: node)` |
| Reload | applies on reload |

Optional readiness path; any non-5xx answer counts as ready.


<h3 id="runtime.node.listen"><code>runtime&lt;node&gt;.listen</code></h3>

| | |
|---|---|
| Syntax | `listen: unix \| tcp` |
| Default | `unix` |
| Context | `runtime (type: node)` |
| Reload | applies on reload |

`unix`: a socket under `runtime_dir` passed as `PORT`; `tcp`: a free loopback port.


<h3 id="runtime.node.response_timeout"><code>runtime&lt;node&gt;.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `runtime (type: node)` |
| Reload | applies on reload |

Time to wait for the response headers of the application.


<h3 id="runtime.node.startup_timeout"><code>runtime&lt;node&gt;.startup_timeout</code></h3>

| | |
|---|---|
| Syntax | `startup_timeout: <duration> (e.g. 30s)` |
| Default | `30s` |
| Context | `runtime (type: node)` |
| Reload | applies on reload |

Time the process gets to become ready.


<h3 id="runtime.node.stop_timeout"><code>runtime&lt;node&gt;.stop_timeout</code></h3>

| | |
|---|---|
| Syntax | `stop_timeout: <duration> (e.g. 30s)` |
| Default | `10s` |
| Context | `runtime (type: node)` |
| Reload | applies on reload |

Time the process gets to exit after SIGTERM before it is killed.


<h3 id="runtime.node.upstream"><code>runtime&lt;node&gt;.upstream</code></h3>

| | |
|---|---|
| Syntax | `upstream: <string>` |
| Default | `none` |
| Context | `runtime (type: node)` |
| Reload | applies on reload |

Proxy to a Node.js process managed elsewhere instead of starting one.


<h3 id="runtime.node.workers"><code>runtime&lt;node&gt;.workers</code></h3>

| | |
|---|---|
| Syntax | `workers: {...}` |
| Default | `none` |
| Context | `runtime (type: node)` |
| Reload | applies on reload |

Number of processes (`min`); requests are balanced across ready ones.


<h3 id="runtime.node.workers.autoscale"><code>runtime&lt;node&gt;.workers.autoscale</code></h3>

| | |
|---|---|
| Syntax | `autoscale: off \| auto \| recommend` |
| Default | `recommend` |
| Context | `runtime<node>.workers` |
| Reload | applies on reload |

`off`, `recommend` (default) or `auto` (ADR-0014).


<h3 id="runtime.node.workers.max"><code>runtime&lt;node&gt;.workers.max</code></h3>

| | |
|---|---|
| Syntax | `max: <integer>` |
| Default | `required` |
| Context | `runtime<node>.workers` |
| Reload | applies on reload |

Upper bound when the pool is scaled.


<h3 id="runtime.node.workers.min"><code>runtime&lt;node&gt;.workers.min</code></h3>

| | |
|---|---|
| Syntax | `min: <integer>` |
| Default | `required` |
| Context | `runtime<node>.workers` |
| Reload | applies on reload |

Processes started at the beginning and kept at least.


<h3 id="runtime.node.workers.target_concurrency"><code>runtime&lt;node&gt;.workers.target_concurrency</code></h3>

| | |
|---|---|
| Syntax | `target_concurrency: <integer>` |
| Default | `none` |
| Context | `runtime<node>.workers` |
| Reload | applies on reload |

Concurrent requests one worker is expected to handle well (utilisation basis).


<h3 id="runtime.python.app"><code>runtime&lt;python&gt;.app</code></h3>

| | |
|---|---|
| Syntax | `app: <string>` |
| Default | `none` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

`module:callable`, e.g. `app:app` or `mysite.wsgi:application`.


<h3 id="runtime.python.command"><code>runtime&lt;python&gt;.command</code></h3>

| | |
|---|---|
| Syntax | `command: [<string>, ...]` |
| Default | `[]` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

Explicit argv. Bind arguments are appended for uvicorn/hypercorn/gunicorn unless the argv already contains `{socket}` or `{port}`.


<h3 id="runtime.python.env"><code>runtime&lt;python&gt;.env</code></h3>

| | |
|---|---|
| Syntax | `env: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

Environment variables for the processes.


<h3 id="runtime.python.health_path"><code>runtime&lt;python&gt;.health_path</code></h3>

| | |
|---|---|
| Syntax | `health_path: <string>` |
| Default | `none` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

Path requested to decide that a worker is ready and healthy.


<h3 id="runtime.python.listen"><code>runtime&lt;python&gt;.listen</code></h3>

| | |
|---|---|
| Syntax | `listen: unix \| tcp` |
| Default | `unix` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

`unix`: a socket under `runtime_dir`; `tcp`: a free loopback port.


<h3 id="runtime.python.mode"><code>runtime&lt;python&gt;.mode</code></h3>

| | |
|---|---|
| Syntax | `mode: asgi \| wsgi` |
| Default | `required` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

`asgi` (uvicorn) or `wsgi` (gunicorn).


<h3 id="runtime.python.process_pool"><code>runtime&lt;python&gt;.process_pool</code></h3>

| | |
|---|---|
| Syntax | `process_pool: true \| false` |
| Default | `false` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

scalws runs `workers.min..max` single-worker server processes itself instead of one server with `--workers`, so the pool can be scaled and restarted live (ADR-0014). Trades the server's copy-on-write sharing for scaling.


<h3 id="runtime.python.response_timeout"><code>runtime&lt;python&gt;.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

Time to wait for the response headers of the application.


<h3 id="runtime.python.server"><code>runtime&lt;python&gt;.server</code></h3>

| | |
|---|---|
| Syntax | `server: uvicorn \| hypercorn \| gunicorn` |
| Default | `none` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

Default: uvicorn for ASGI, gunicorn for WSGI.


<h3 id="runtime.python.startup_timeout"><code>runtime&lt;python&gt;.startup_timeout</code></h3>

| | |
|---|---|
| Syntax | `startup_timeout: <duration> (e.g. 30s)` |
| Default | `30s` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

Time the processes get to become ready.


<h3 id="runtime.python.stop_timeout"><code>runtime&lt;python&gt;.stop_timeout</code></h3>

| | |
|---|---|
| Syntax | `stop_timeout: <duration> (e.g. 30s)` |
| Default | `10s` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

Time the processes get to exit after SIGTERM before they are killed.


<h3 id="runtime.python.upstream"><code>runtime&lt;python&gt;.upstream</code></h3>

| | |
|---|---|
| Syntax | `upstream: <string>` |
| Default | `none` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

Proxy to a Python server managed elsewhere instead of starting one.


<h3 id="runtime.python.virtualenv"><code>runtime&lt;python&gt;.virtualenv</code></h3>

| | |
|---|---|
| Syntax | `virtualenv: <string>` |
| Default | `none` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

Virtual environment whose server binary and packages are used.


<h3 id="runtime.python.workers"><code>runtime&lt;python&gt;.workers</code></h3>

| | |
|---|---|
| Syntax | `workers: {...}` |
| Default | `none` |
| Context | `runtime (type: python)` |
| Reload | applies on reload |

Worker processes of the application server (`min`).


<h3 id="runtime.python.workers.autoscale"><code>runtime&lt;python&gt;.workers.autoscale</code></h3>

| | |
|---|---|
| Syntax | `autoscale: off \| auto \| recommend` |
| Default | `recommend` |
| Context | `runtime<python>.workers` |
| Reload | applies on reload |

`off`, `recommend` (default) or `auto` (ADR-0014).


<h3 id="runtime.python.workers.max"><code>runtime&lt;python&gt;.workers.max</code></h3>

| | |
|---|---|
| Syntax | `max: <integer>` |
| Default | `required` |
| Context | `runtime<python>.workers` |
| Reload | applies on reload |

Upper bound when the pool is scaled.


<h3 id="runtime.python.workers.min"><code>runtime&lt;python&gt;.workers.min</code></h3>

| | |
|---|---|
| Syntax | `min: <integer>` |
| Default | `required` |
| Context | `runtime<python>.workers` |
| Reload | applies on reload |

Processes started at the beginning and kept at least.


<h3 id="runtime.python.workers.target_concurrency"><code>runtime&lt;python&gt;.workers.target_concurrency</code></h3>

| | |
|---|---|
| Syntax | `target_concurrency: <integer>` |
| Default | `none` |
| Context | `runtime<python>.workers` |
| Reload | applies on reload |

Concurrent requests one worker is expected to handle well (utilisation basis).


<h3 id="runtime.container.command"><code>runtime&lt;container&gt;.command</code></h3>

| | |
|---|---|
| Syntax | `command: [<string>, ...]` |
| Default | `[]` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Arguments after the image; `{port}` is replaced by the port scalws chose.


<h3 id="runtime.container.drop_capabilities"><code>runtime&lt;container&gt;.drop_capabilities</code></h3>

| | |
|---|---|
| Syntax | `drop_capabilities: true \| false` |
| Default | `false` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Drop all Linux capabilities.


<h3 id="runtime.container.engine"><code>runtime&lt;container&gt;.engine</code></h3>

| | |
|---|---|
| Syntax | `engine: podman \| docker` |
| Default | `podman` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Container engine: `podman` or `docker`.


<h3 id="runtime.container.engine_path"><code>runtime&lt;container&gt;.engine_path</code></h3>

| | |
|---|---|
| Syntax | `engine_path: <string>` |
| Default | `none` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Engine binary; default `podman` / `docker` from `PATH`.


<h3 id="runtime.container.env"><code>runtime&lt;container&gt;.env</code></h3>

| | |
|---|---|
| Syntax | `env: {<key>: <string>, ...}` |
| Default | `empty` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Environment variables for the containers.


<h3 id="runtime.container.health_path"><code>runtime&lt;container&gt;.health_path</code></h3>

| | |
|---|---|
| Syntax | `health_path: <string>` |
| Default | `none` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Path requested to decide that a container is ready and healthy.


<h3 id="runtime.container.image"><code>runtime&lt;container&gt;.image</code></h3>

| | |
|---|---|
| Syntax | `image: <string>` |
| Default | `required` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Image reference, e.g. `docker.io/library/nginx:1.27`.


<h3 id="runtime.container.mounts"><code>runtime&lt;container&gt;.mounts</code></h3>

| | |
|---|---|
| Syntax | `mounts: [{...}, ...]` |
| Default | `[]` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Host directories mounted into the containers.


<h3 id="runtime.container.mounts-.read_only"><code>runtime&lt;container&gt;.mounts[].read_only</code></h3>

| | |
|---|---|
| Syntax | `read_only: true \| false` |
| Default | `true` |
| Context | `runtime<container>.mounts[]` |
| Reload | applies on reload |

Mount read-only.


<h3 id="runtime.container.mounts-.source"><code>runtime&lt;container&gt;.mounts[].source</code></h3>

| | |
|---|---|
| Syntax | `source: <string>` |
| Default | `required` |
| Context | `runtime<container>.mounts[]` |
| Reload | applies on reload |

Host path (absolute).


<h3 id="runtime.container.mounts-.target"><code>runtime&lt;container&gt;.mounts[].target</code></h3>

| | |
|---|---|
| Syntax | `target: <string>` |
| Default | `required` |
| Context | `runtime<container>.mounts[]` |
| Reload | applies on reload |

Path inside the container (absolute).


<h3 id="runtime.container.network"><code>runtime&lt;container&gt;.network</code></h3>

| | |
|---|---|
| Syntax | `network: bridge \| host` |
| Default | `bridge` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

`bridge`: publish `port` on a loopback port; `host`: share the host network.


<h3 id="runtime.container.port"><code>runtime&lt;container&gt;.port</code></h3>

| | |
|---|---|
| Syntax | `port: <integer>` |
| Default | `none` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Port the application listens on inside the container (`bridge` networking).


<h3 id="runtime.container.pull"><code>runtime&lt;container&gt;.pull</code></h3>

| | |
|---|---|
| Syntax | `pull: missing \| always \| never` |
| Default | `missing` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

When the image is pulled: `missing`, `always` or `never`.


<h3 id="runtime.container.read_only"><code>runtime&lt;container&gt;.read_only</code></h3>

| | |
|---|---|
| Syntax | `read_only: true \| false` |
| Default | `false` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Read-only root filesystem (a tmpfs is mounted at `/tmp`).


<h3 id="runtime.container.response_timeout"><code>runtime&lt;container&gt;.response_timeout</code></h3>

| | |
|---|---|
| Syntax | `response_timeout: <duration> (e.g. 30s)` |
| Default | `60s` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Time to wait for the response headers of the application.


<h3 id="runtime.container.startup_timeout"><code>runtime&lt;container&gt;.startup_timeout</code></h3>

| | |
|---|---|
| Syntax | `startup_timeout: <duration> (e.g. 30s)` |
| Default | `120s` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Time a container gets to become ready (includes pulling the image).


<h3 id="runtime.container.stop_timeout"><code>runtime&lt;container&gt;.stop_timeout</code></h3>

| | |
|---|---|
| Syntax | `stop_timeout: <duration> (e.g. 30s)` |
| Default | `10s` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Time a container gets to stop before it is killed.


<h3 id="runtime.container.user"><code>runtime&lt;container&gt;.user</code></h3>

| | |
|---|---|
| Syntax | `user: <string>` |
| Default | `none` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

User the container runs as (`--user`).


<h3 id="runtime.container.workers"><code>runtime&lt;container&gt;.workers</code></h3>

| | |
|---|---|
| Syntax | `workers: {...}` |
| Default | `none` |
| Context | `runtime (type: container)` |
| Reload | applies on reload |

Number of containers (`min` at start; scaled between `min` and `max`).


<h3 id="runtime.container.workers.autoscale"><code>runtime&lt;container&gt;.workers.autoscale</code></h3>

| | |
|---|---|
| Syntax | `autoscale: off \| auto \| recommend` |
| Default | `recommend` |
| Context | `runtime<container>.workers` |
| Reload | applies on reload |

`off`, `recommend` (default) or `auto` (ADR-0014).


<h3 id="runtime.container.workers.max"><code>runtime&lt;container&gt;.workers.max</code></h3>

| | |
|---|---|
| Syntax | `max: <integer>` |
| Default | `required` |
| Context | `runtime<container>.workers` |
| Reload | applies on reload |

Upper bound when the pool is scaled.


<h3 id="runtime.container.workers.min"><code>runtime&lt;container&gt;.workers.min</code></h3>

| | |
|---|---|
| Syntax | `min: <integer>` |
| Default | `required` |
| Context | `runtime<container>.workers` |
| Reload | applies on reload |

Processes started at the beginning and kept at least.


<h3 id="runtime.container.workers.target_concurrency"><code>runtime&lt;container&gt;.workers.target_concurrency</code></h3>

| | |
|---|---|
| Syntax | `target_concurrency: <integer>` |
| Default | `none` |
| Context | `runtime<container>.workers` |
| Reload | applies on reload |

Concurrent requests one worker is expected to handle well (utilisation basis).


<h3 id="security"><code>security</code></h3>

| | |
|---|---|
| Syntax | `security: {...}` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Deny paths and rate limits for the site.


<h3 id="security.deny_paths"><code>security.deny_paths</code></h3>

| | |
|---|---|
| Syntax | `deny_paths: [<string>, ...]` |
| Default | `[]` |
| Context | `security` |
| Reload | applies on reload |

Denied paths (added to the profile's); `*` matches any characters.


<h3 id="security.ignore_profile_rules"><code>security.ignore_profile_rules</code></h3>

| | |
|---|---|
| Syntax | `ignore_profile_rules: true \| false` |
| Default | `false` |
| Context | `security` |
| Reload | applies on reload |

Do not apply the profile's deny rules.


<h3 id="security.rate_limits"><code>security.rate_limits</code></h3>

| | |
|---|---|
| Syntax | `rate_limits: [{...}, ...]` |
| Default | `[]` |
| Context | `security` |
| Reload | applies on reload |

Request rates per client address for matching paths (first match applies).


<h3 id="security.rate_limits-.burst"><code>security.rate_limits[].burst</code></h3>

| | |
|---|---|
| Syntax | `burst: <integer>` |
| Default | `none` |
| Context | `security.rate_limits[]` |
| Reload | applies on reload |

Token-bucket burst (default: equal to the rate).


<h3 id="security.rate_limits-.path"><code>security.rate_limits[].path</code></h3>

| | |
|---|---|
| Syntax | `path: <string>` |
| Default | `required` |
| Context | `security.rate_limits[]` |
| Reload | applies on reload |

Path prefix the limit applies to.


<h3 id="security.rate_limits-.requests_per_second"><code>security.rate_limits[].requests_per_second</code></h3>

| | |
|---|---|
| Syntax | `requests_per_second: <integer>` |
| Default | `required` |
| Context | `security.rate_limits[]` |
| Reload | applies on reload |

Sustained requests per second per client address on this path.


<h3 id="static"><code>static</code></h3>

| | |
|---|---|
| Syntax | `static: true \| <string> \| [<string>, ...] \| {...}` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Static files (the default): `true` or `{index: [...], precompressed: true}`.


<h3 id="static.index"><code>static.index</code></h3>

| | |
|---|---|
| Syntax | `index: [<string>, ...]` |
| Default | `["index.html"]` |
| Context | `static` |
| Reload | applies on reload |

File names served for a directory request, tried in order.


<h3 id="static.precompressed"><code>static.precompressed</code></h3>

| | |
|---|---|
| Syntax | `precompressed: true \| false` |
| Default | `false` |
| Context | `static` |
| Reload | applies on reload |

Serve `<file>.br` / `<file>.gz` siblings to clients that accept them.


<h3 id="static.root"><code>static.root</code></h3>

| | |
|---|---|
| Syntax | `root: <string>` |
| Default | `none` |
| Context | `static` |
| Reload | applies on reload |

Document root. Defaults to the application's `root`.


<h3 id="tenant"><code>tenant</code></h3>

| | |
|---|---|
| Syntax | `tenant: <string>` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Tenant (account) of the site; default derived from `domain`. Sites of one tenant share its resource limits.


<h3 id="tls"><code>tls</code></h3>

| | |
|---|---|
| Syntax | `tls: auto \| manual` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

`auto`: certificate via ACME; `manual`: from the TLS listeners' certificates. Default: `auto` when `server.acme.enabled`, else `manual`.


<h3 id="user"><code>user</code></h3>

| | |
|---|---|
| Syntax | `user: <string>` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

Tenant settings (only once per tenant).


<h3 id="www"><code>www</code></h3>

| | |
|---|---|
| Syntax | `www: none \| alias \| redirect` |
| Default | `none` |
| Context | `site file` |
| Reload | applies on reload |

`www.<domain>`: not served (`none`), served as an alias, or redirected to `domain`.
