# scalwsd

URL: https://scalws.com/docs/reference/programs/scalwsd/
Source: `docs/reference/programs/scalwsd.md` in the ScalWS repository

`scalwsd` is the ScalWS web server daemon: it serves client traffic from one configuration file, either on its own as `scalwsd.service` or as an instance started by scalws-controller.

```text
scalwsd [OPTIONS]
```

`scalwsd --help` lists the options; `scalwsd --version` prints the version.

## Options

| Option | Default | Meaning |
|---|---|---|
| `-c, --config <PATH>` | `$SCALWS_CONFIG`, else `/etc/scalws/scalws.yaml` | YAML configuration file. |
| `--check` | | Validates and prepares the configuration, then exits. Prints `configuration OK`, or exits with 2. |
| `--worker-threads <N>` | number of CPUs | Tokio worker threads. Also the per-core event-loop count unless [`server.event_loops`](https://scalws.com/docs/reference/server/#server.event_loops) is set. |
| `--wait-for-activation` | | Prepares everything, but accepts client connections only after `SIGUSR2`. Until then `/readyz` on the metrics listener reports `ready`, and `active` after. |
| `--instance-id <ID>` | | Instance identity under the controller: the runtime directory, admin socket and disk cache move to per-instance subdirectories, and the remote admin listener is not started. `[a-z0-9-]`, at most 32 characters. |
| `--metrics-address <ADDR>` | | Metrics listener address (`/metrics`, `/healthz`, `/readyz`) for this instance. Turns the metrics listener on. |
| `--reuseport` | | Same as [`server.listener_mode`](https://scalws.com/docs/reference/server/#server.listener_mode)`: reuseport`. Not allowed with HTTP/3 listeners. |
| `--listen-socket <PATH>` | | Receives the listening sockets from this Unix socket (`listener_mode: inherited`, used by scalws-controller). |
| `--limit-share-file <PATH>` | | A file holding the number of instances that share the configured per-client, route and tenant limits. Each limit is divided by that number, rounded up. Re-read on every reload. |
| `--tenant-limits-file <PATH>` | | Run-time tenant limits to start with. Kept by scalws-controller. |
| `--sandbox-floor <MODE>` | `$SCALWS_SANDBOX_FLOOR`, else none | Lowest [sandbox](https://scalws.com/docs/guide/sandbox/) mode (`off`, `audit`, `on`): the stricter of this and [`server.sandbox`](https://scalws.com/docs/reference/server/#server.sandbox) applies. scalws-controller passes it from its own record. |
| `--config-sha256 <HEX>` | | SHA-256 the configuration file must have, given by scalws-controller from its own record. The bytes parsed at start and on every reload are checked against it; a mismatch fails the start (exit 2) or rejects the reload. |
| `--previous-config-sha256 <HEX>` | | SHA-256 `--previous-config` must have; a file that differs is not compared with (a document root that cannot be opened then fails the start). |
| `--sandbox-selftest` | | Applies the configured sandbox (as `on`) to this process, checks that it refuses what it must and allows what it must, prints the result and exits: 0 passed, 1 failed, 2 not applicable here. |
| `--features` | | Prints the optional Cargo features the binary was built with, one per line (`http3`, `mimalloc`, `ebpf`, `perf-instrumentation`), and exits. The packages print `http3` and `mimalloc`. |
| `--service-sandbox` | | Service sandbox for systems without systemd (OpenRC): the systemd unit's write fence and system call settings, inherited by every program started. |
| `--service-rw <PATH>` | | Extra writable directory of `--service-sandbox` (repeatable), the twin of `ReadWritePaths=`. |
| `--restrict-suid-sgid` | | Refuses set-user/group-ID modes on files and directories this process and every program it starts create, like systemd's `RestrictSUIDSGID=`, but leaves `openat2` to the static files. The packaged unit passes it instead of that setting; `--service-sandbox` includes it. `SCALWS_RESTRICT_SUID_SGID=false` (in a drop-in) turns it off. |
| `--previous-config <PATH>` | | The configuration of the generation this one replaces (given by scalws-controller on a reload). An application whose document root cannot be opened answers `503` only when its root and runtimes are unchanged from it; a new or changed one fails the start, so the controller rolls the generation back. Without it every such application answers `503`. |

The instance options (`--wait-for-activation`, `--instance-id`, `--listen-socket`,
`--limit-share-file`, `--tenant-limits-file`, `--previous-config`, `--sandbox-floor`,
`--config-sha256`) are set by scalws-controller. An instance (`--instance-id`) with a
sandbox floor of `audit` or `on` refuses a configuration that would start processes. You normally
use only `--config`, `--check` and perhaps `--worker-threads`.

Socket addresses and the instance id follow the [value formats](https://scalws.com/docs/reference/value-formats/).

## Exit status

| Status | When |
|---|---|
| 0 | `--check` passed, or the server stopped normally. |
| 1 | Start-up failed (for example a port that cannot be bound). |
| 2 | The configuration cannot be loaded, the command-line options do not fit it (for example `--reuseport` with an HTTP/3 listener, or an invalid `--instance-id`), or `--check` failed. |

## Signals

On Unix:

| Signal | Effect |
|---|---|
| `SIGHUP` | Reloads the configuration file, like `scalwsctl reload`. A rejected reload is logged and the active configuration stays. Once a shutdown has begun, it is logged and ignored. |
| `SIGTERM`, `SIGINT` | Keeps serving for [`server.limits.shutdown_delay`](https://scalws.com/docs/reference/server-limits/#server.limits.shutdown_delay) (a second signal ends the delay), drains connections for up to [`server.limits.shutdown_timeout`](https://scalws.com/docs/reference/server-limits/#server.limits.shutdown_timeout), closes the remaining ones, and exits with 0. Both are read from the active configuration when the signal arrives. A signal received while the server starts takes effect once it has started. |
| `SIGUSR2` | Activation (with `--wait-for-activation`). |

On other platforms, Ctrl-C drains and exits, and reloading by signal is not available.

```sh
scalwsd --config /etc/scalws/scalws.yaml --check
systemctl reload scalwsd       # sends SIGHUP
```

Changes that a reload cannot apply, such as listener addresses, are refused with
"requires a restart"; see [Files and services](https://scalws.com/docs/guide/files-and-services/#how-reload-works).

## See also

* [Command-line programs](https://scalws.com/docs/guide/cli/)
* [scalwsctl](https://scalws.com/docs/reference/programs/scalwsctl/), [scalws-controller](https://scalws.com/docs/reference/programs/scalws-controller/), [scalws-console](https://scalws.com/docs/reference/programs/scalws-console/)
* [Configuration](https://scalws.com/docs/guide/configuration/)
