Skip to content
Configuration Options

Configuration Options

This page is a quick reference for the keys used in config-example.toml. For step-by-step setups, see Basic Setups and Advanced Usage.

This page is intentionally dictionary-like. Detailed behavior and deployment examples are covered in the guide pages linked below.

Quick Navigation

Minimal Example

listen_port = 80
listen_port_tls = 443

[apps.app1]
server_name = "app1.example.com"
tls = { tls_cert_path = "./server.crt", tls_cert_key_path = "./server.key" }

[[apps.app1.reverse_proxy]]
upstream = [
  { location = "app1.local:8080" },
]

Global Settings

OptionRequiredDefaultDescription
listen_portNoNoneTCP port for plaintext HTTP. At least one of listen_port or listen_port_tls must be specified.
listen_port_tlsNoNoneTCP port for HTTPS/TLS. Required if you serve TLS, use ACME, or enable HTTP/3.
public_https_portNoSame as listen_port_tls when TLS is enabledClient-visible HTTPS/HTTP-3 port used in 301 redirects and Alt-Svc headers when the public HTTPS port differs from listen_port_tls, for example behind container port mapping or firewall redirection. Renamed from https_redirection_port in v0.13.0.
tcp_listen_backlogNo1024TCP listen backlog for HTTP/1.1 and HTTP/2 listeners.
max_concurrent_streamsNo64HTTP/2 concurrent stream limit per connection.
max_clientsNo512Shared cap for accepted HTTP/1.1 and HTTP/2 TCP connections. A slot is reserved right after TCP accept and held through PROXY protocol parsing, the TLS handshake, and the whole connection lifetime. 0 rejects every HTTP/1.1 and HTTP/2 connection. HTTP/3 is not counted here; it has its own per-endpoint limit under [experimental.h3].
request_max_body_sizeNo268435456 (256 MiB)Maximum inbound request body size shared by HTTP/1.1, HTTP/2, and HTTP/3. Accepts an integer in bytes or a string with a binary suffix such as "256k", "10m", or "1g". Requests whose Content-Length exceeds the limit are rejected with 413 before any upstream contact; oversize chunked/streamed bodies are detected mid-flight. Set 0 or "unlimited" to disable the limit.
trusted_forwarded_proxiesNoNone (no proxy trusted)List of proxies whose incoming X-Forwarded-* / Forwarded headers are trusted. Accepts CIDR blocks and the built-in aliases "cloudflare", "fastly", and "cloudfront". If omitted or empty, forwarding headers from preceding peers are ignored and rebuilt from the immediate peer address. See Trusted Forwarded Proxies.
sticky_cookie_secretRequired when load_balance = "sticky" is usedNone32-byte secret encoded as unpadded base64url, used to seal sticky-session cookies as opaque AEAD blobs. Rotating the secret resets sticky-session affinity. A generation command is shown below the table.
redact_query_in_access_logNofalseIf true, query-string values in the access log are masked as <redacted> while parameter keys and the path are kept, so URLs carrying tokens or PII are not logged verbatim.
listen_address_v4No0.0.0.0IPv4 address(es) to bind listeners to. Accepts a single string or an array of strings for binding to multiple interfaces, for example ['192.168.1.1', '10.0.0.1']. When multiple addresses are specified, the wildcard 0.0.0.0 must not be included. Duplicate addresses are silently ignored.
listen_address_v6NoNoneIPv6 address(es) to bind listeners to. Accepts a single string or an array of strings, for example '[::]' or ['::1', 'fe80::1']. If omitted and listen_ipv6 = true, binds to [::]. If omitted and listen_ipv6 is false or unset, IPv6 is disabled. When multiple addresses are specified, the wildcard :: must not be included. Duplicate addresses are silently ignored.
listen_ipv6NofalseIf true, bind to [::] when listen_address_v6 is not specified.
default_appNoNoneFallback app name for unmatched plaintext HTTP requests. This applies only to HTTP; HTTPS requests with an unknown server name are rejected unconditionally. On this fallback path, the outgoing Host header is force-overwritten with the default app’s server_name (winning over keep_original_host / set_upstream_host), and the untrusted original host is exposed only in X-Forwarded-Host / Forwarded: host=. Backends must treat those values as untrusted observational data.

A sticky_cookie_secret value can be generated as follows:

openssl rand -base64 32 | tr '+/' '-_' | tr -d '=\n'

Application Definition

All backend applications are defined under [apps].

[apps.<app_name>]

OptionRequiredDefaultDescription
server_nameYesNoneHostname served by this app, for example app.example.com. Must be a syntactically valid hostname (validated at startup since v0.12.0): dot-separated alphanumeric/- labels, up to 253 ASCII characters. Wildcards, underscores, and IPv6 literals are rejected; IPv4 literals are accepted.
reverse_proxyYesNoneList of routing rules for this app.
tlsNoNoneTLS settings for this app. If omitted, the app serves plaintext HTTP only.

TLS Options

These options live under apps.<app_name>.tls.

OptionRequiredDefaultDescription
tls_cert_pathYes for static TLSNonePEM certificate path for this app when using static certificates.
tls_cert_key_pathYes for static TLSNonePEM private key path for this app. The key must be in PKCS8 format.
https_redirectionNotrue when both listen_port and listen_port_tls are setPer-app HTTP-to-HTTPS redirect switch. If you serve HTTPS only, do not set this option.
client_ca_cert_pathNoNoneCA certificate path for mTLS client authentication. Cleartext requests are never forwarded to an app with this option: they receive a 301 redirect when https_redirection is enabled (the default), or 421 when it is explicitly disabled. See Client Authentication.
acmeNofalseIf true, certificates are issued and renewed automatically through ACME instead of tls_cert_path and tls_cert_key_path. See ACME (Let’s Encrypt) Integration.

Reverse Proxy Rules

Each app can contain one or more [[apps.<app_name>.reverse_proxy]] entries.

OptionRequiredDefaultDescription
pathNoNonePath prefix to match, such as "/api" or "/static". Longest-prefix match wins.
replace_pathNoPreserve original pathRewritten prefix forwarded upstream.
upstreamYesNoneList of backend destinations.
load_balanceNononeBackend selection strategy. Supported values are none, round_robin, random, sticky, and primary_backup. Using sticky requires the global sticky_cookie_secret option.
upstream_optionsNoNoneList of request-forwarding behaviors. See Upstream Options.
health_checkNoNoneActive health check configuration. Set true for TCP check with defaults, or use a table for full configuration. See Active Health Check.

Upstream Entries

Each item in upstream = [...] accepts:

OptionRequiredDefaultDescription
locationYesNoneBackend host and port, for example "backend.internal:8080" or "www.example.com".
tlsNofalseIf true, the upstream connection uses HTTPS. If omitted or false, HTTP is used.

Upstream Option Values

See Upstream Options for detailed explanations of each option. The table below summarizes the supported values for upstream_options.

ValueEffect
keep_original_hostPreserve the incoming Host header. This is the default behavior.
set_upstream_hostReplace the Host header with the upstream host.
upgrade_insecure_requestsAdd Upgrade-Insecure-Requests: 1 if it is not already present.
force_http11_upstreamForce HTTP/1.1 for upstream connections.
force_http2_upstreamForce HTTP/2 for upstream connections.
forwarded_headerGenerate the RFC 7239 Forwarded header in addition to the default X-Forwarded-* headers.

Health Check Options

These options live under apps.<app_name>.reverse_proxy.health_check. Alternatively, set health_check = true for a TCP check with all defaults. See Active Health Check for detailed usage.

OptionRequiredDefaultDescription
typeNo"tcp"Check type: "tcp" or "http".
intervalNo10Seconds between health check probes.
timeoutNo5Timeout in seconds per check attempt. Must be less than interval.
unhealthy_thresholdNo3Consecutive failures before marking an upstream unhealthy.
healthy_thresholdNo2Consecutive successes before marking an upstream healthy again.
pathYes for "http"NoneHTTP check endpoint path. Must start with /.
expected_statusNo200Expected HTTP status code for HTTP checks.

Experimental Settings

The [experimental] table controls optional and advanced features.

[experimental]

OptionRequiredDefaultDescription
ignore_sni_consistencyNofalseIf true, relax the consistency check between the TLS SNI and the request Host header. Keeping it false is recommended. This relaxation never applies to apps with client authentication (client_ca_cert_path); such requests over a TLS session established for a different server name are always rejected.
connection_handling_timeoutNo0Total connection handling timeout in seconds. 0 means no timeout.

[experimental.h3]

Add this table to enable HTTP/3 support. See HTTP/3.

The HTTP/3 connection limit is independent of the global max_clients (which covers HTTP/1.1 and HTTP/2 only). The request body limit is the top-level request_max_body_size; the former experimental.h3.request_max_body_size key was removed in v0.14.0 and now causes a configuration load error.

OptionRequiredDefaultDescription
alt_svc_max_ageNo3600Alt-Svc max-age in seconds.
max_concurrent_connectionsNo512Concurrent HTTP/3 (QUIC) connection limit per configured H3 endpoint/listener, covering handshakes through connection close. 0 rejects every HTTP/3 attempt.
max_concurrent_bidistreamNo64Bidirectional QUIC stream limit.
max_concurrent_unistreamNo64Unidirectional QUIC stream limit.
max_idle_timeoutNo10QUIC idle timeout in seconds. 0 means infinite timeout.

[experimental.cache]

Add this table to enable the hybrid response cache. See Caching.

OptionRequiredDefaultDescription
cache_dirNo./cacheCache directory path, relative to the current working directory.
max_cache_entryNo1000Maximum number of cache entries.
max_cache_each_sizeNo65535Maximum size in bytes for a single cacheable response.
max_cache_each_size_on_memoryNo65535 (same as max_cache_each_size)Maximum size in bytes for keeping a cached response in memory. Larger cached responses are stored as files. With the defaults, every cacheable object is served from memory; the file tier engages when max_cache_each_size is raised beyond this value. Set 0 to always use file cache. Worst-case memory use is max_cache_entry × this value.
max_cache_total_sizeNo1073741824 (1 GiB)Ceiling on the total bytes retained by the cache across the on-memory and file tiers. Accepts an integer in bytes or a string with a binary suffix such as "256m" or "1g". When storing a response would exceed it, least-recently-used entries are evicted. Set "unlimited" to disable the ceiling; 0 also means unlimited (not zero capacity), so the string form is recommended to avoid confusion with max_cache_each_size_on_memory = 0.

Cached responses are keyed on the request URI forwarded upstream. A backend that varies content by the original client-facing host, scheme, or URI — for example, multiple virtual hosts flattened onto one upstream via set_upstream_host or default_app — must emit an appropriate Vary header on cacheable responses or mark them non-cacheable.

[experimental.acme]

Add this table when any app uses tls = { acme = true }. See ACME (Let’s Encrypt) Integration.

OptionRequiredDefaultDescription
emailYesNoneContact email for ACME account registration.
dir_urlNoLet’s Encrypt production directoryACME directory URL.
registry_pathNo./acme_registryStorage directory for retrieved certificates and account data.

[experimental.tcp_recv_proxy_protocol]

Add this table to accept inbound HAProxy PROXY protocol headers from a trusted L4 proxy. See PROXY Protocol.

OptionRequiredDefaultDescription
trusted_proxiesYesNoneNon-empty list of trusted proxy CIDR ranges, for example ["127.0.0.1/32", "::1/128"].
timeoutNo50 msTimeout in milliseconds for receiving the PROXY header. Setting 0 falls back to an internal 5s timeout.

Related Guides