Skip to content

Configuration Overview

rust-web-server uses a four-layer configuration system. Each layer can override the one below it. All resolved values are stored as process environment variables under the RWS_CONFIG_* namespace and read at request time — there is no config struct passed through the call stack.

Priority order (lowest to highest)

PrioritySourceNotes
1Built-in defaultsHardcoded in src/entry_point/mod.rs
2System environment variablesSet before the process starts
3rws.config.tomlOptional file in the working directory
4CLI argumentsFlags passed on the command line

A value set at a higher priority layer always wins. For example, --port=9000 on the command line overrides port = 8080 in rws.config.toml, which in turn overrides RWS_CONFIG_PORT=8888 in the environment.

How startup loading works

bootstrap() in src/entry_point/mod.rs runs three steps in order:

read_system_environment_variables(); // step 1: read existing env vars
override_environment_variables_from_config(None); // step 2: apply rws.config.toml
override_environment_variables_from_command_line_args(); // step 3: apply CLI flags

After all three steps, any RWS_CONFIG_* variable that was never set by any source gets its compiled-in default value. From that point on, the server reads configuration exclusively through std::env::var("RWS_CONFIG_*").

The config file path can be overridden at the OS level:

Terminal window
RWS_CONFIG_FILE=/etc/rws/production.toml rws

Hot reload

Some settings can be changed while the server is running without a restart. Trigger a reload with either:

Terminal window
# Unix signal
kill -HUP $(pidof rws)
# HTTP endpoint (no body required)
curl -X POST http://localhost:7878/admin/config/reload

What reloads

SettingEnvironment variable
CORS — all fieldsRWS_CONFIG_CORS_*
Rate-limit thresholdsRWS_CONFIG_RATE_LIMIT_MAX_REQUESTS, RWS_CONFIG_RATE_LIMIT_WINDOW_SECS
Log formatRWS_CONFIG_LOG_FORMAT
Request allocation sizeRWS_CONFIG_REQUEST_ALLOCATION_SIZE_IN_BYTES

On TLS builds, SIGHUP also rebuilds the TlsAcceptor from the updated certificate files for all virtual hosts — no restart needed to rotate certs.

What requires a restart

SettingReason
IP / PortThe bound socket cannot be moved
Thread countThe thread pool is fixed at startup
TLS cert / key paths (plain HTTP build)The acceptor is built once

Reading config in handler code

config_reload::current() returns a typed ConfigSnapshot containing all hot-reloadable values. It takes a brief read lock and clones a handful of strings — safe to call on every request.

use rust_web_server::config_reload;
let cfg = config_reload::current();
if cfg.cors_allow_all {
// allow any origin
}
println!("log format: {}", cfg.log_format);

The ConfigSnapshot fields map directly to environment variables:

FieldEnvironment variable
cors_allow_allRWS_CONFIG_CORS_ALLOW_ALL
cors_allow_originsRWS_CONFIG_CORS_ALLOW_ORIGINS
cors_allow_credentialsRWS_CONFIG_CORS_ALLOW_CREDENTIALS
cors_allow_methodsRWS_CONFIG_CORS_ALLOW_METHODS
cors_allow_headersRWS_CONFIG_CORS_ALLOW_HEADERS
cors_expose_headersRWS_CONFIG_CORS_EXPOSE_HEADERS
cors_max_ageRWS_CONFIG_CORS_MAX_AGE
rate_limit_max_requestsRWS_CONFIG_RATE_LIMIT_MAX_REQUESTS
rate_limit_window_secsRWS_CONFIG_RATE_LIMIT_WINDOW_SECS
log_formatRWS_CONFIG_LOG_FORMAT
request_allocation_sizeRWS_CONFIG_REQUEST_ALLOCATION_SIZE_IN_BYTES

For settings that are not in ConfigSnapshot (IP, port, thread count, TLS paths) read them directly:

let port = std::env::var("RWS_CONFIG_PORT").unwrap_or_else(|_| "7878".to_string());