Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/MercuryWorkshop/epoxy-tls/llms.txt

Use this file to discover all available pages before exploring further.

The [server] section of the epoxy-server configuration file controls how the server binds to the network, which transport protocol it speaks, TLS termination, log verbosity, and the Tokio runtime that drives the process. Every option has a sensible default so you only need to specify the values that differ from the defaults.

Config file basics

epoxy-server reads a configuration file in TOML (default), JSON, or YAML. Pass the path to the file as the first CLI argument:
epoxy-server /etc/epoxy/config.toml
To use a different format, add --format:
epoxy-server --format json /etc/epoxy/config.json
epoxy-server --format yaml /etc/epoxy/config.yaml
To print the built-in defaults and exit (useful as a starting point), run:
epoxy-server --default-config
The top-level config is divided into three sections, each mapped to its own table:
[server]   # listener, TLS, runtime
[wisp]     # Wisp protocol and extensions
[stream]   # per-stream filtering and access control

[server] fields

bind
[socket_type, address]
default:"[\"tcp\", \"127.0.0.1:4000\"]"
A two-element array that specifies the socket type and the address to listen on.Socket type variants:
ValueDescription
"tcp"Plain TCP socket (default)
"tlstcp"TCP socket with TLS — requires tls_keypair
"unix"Unix domain socket — address is a filesystem path
"tlsunix"Unix domain socket with TLS — requires tls_keypair
"file"File “socket” — accepts a single connection immediately via stdin/stdout; useful for testing
# TCP on all interfaces, port 4000
bind = ["tcp", "0.0.0.0:4000"]

# TLS-terminated TCP
bind = ["tlstcp", "0.0.0.0:443"]

# Unix socket
bind = ["unix", "/run/epoxy/wisp.sock"]
transport
string
default:"\"websocket\""
The framing protocol used on top of the socket.
ValueDescription
"websocket"Standard WebSocket upgrade — compatible with all epoxy-client builds (default)
"lengthdelimitedle"Little-endian u32 length-delimited codec (see tokio-util) — lower overhead, not WebSocket
Most deployments should use "websocket". The length-delimited transport is intended for non-browser environments where WebSocket framing overhead matters.
tls_keypair
[string, string] | null
default:"null"
Paths to the TLS certificate and private key in PEM format, as a two-element array [cert.pem, key.pem]. Required when bind uses "tlstcp" or "tlsunix".
tls_keypair = ["/etc/epoxy/cert.pem", "/etc/epoxy/key.pem"]
Leave unset (or null) for plain (non-TLS) sockets. If you terminate TLS at a reverse proxy (nginx, Caddy, etc.) you do not need this field.
resolve_ipv6
boolean
default:"false"
When true, the server will resolve hostnames to IPv6 addresses and open upstream connections over IPv6. When false (the default), only IPv4 addresses are used for upstream connections.
tcp_nodelay
boolean
default:"true"
Enables TCP_NODELAY on client TCP connections, disabling Nagle’s algorithm. This reduces latency for small, interactive packets at the cost of slightly higher packet count. Recommended to leave true for typical proxy workloads.
file_raw_mode
boolean
default:"false"
When using the "file" socket type, setting this to true puts the terminal into raw mode before reading. Has no effect for TCP or Unix socket listeners.
stats_endpoint
string | [socket_type, address] | null
default:"null"
Enables an HTTP endpoint that exposes server statistics. Accepts two forms:
  • Same server — a URL path string served on the same listener as the Wisp server:
    stats_endpoint = "/stats"
    
  • Separate server — a [socket_type, address] tuple that binds a dedicated HTTP listener:
    stats_endpoint = ["tcp", "127.0.0.1:9090"]
    
Leave unset (or null) to disable the stats endpoint entirely.
use_real_ip_headers
boolean
default:"false"
When true, the server inspects the X-Real-IP and X-Forwarded-For HTTP headers to determine the real client IP address. Enable this when epoxy-server is deployed behind a reverse proxy that sets these headers.
Only enable use_real_ip_headers when epoxy-server is not directly internet-facing. If the server accepts connections from untrusted clients, those clients could spoof their source IP by injecting these headers themselves.
non_ws_response
string
default:"\":3\""
The plain-text body sent in response to any HTTP request that is not a WebSocket upgrade. Useful for adding a basic health-check string or a short message for visitors who reach the server with a browser.
max_message_size
integer
default:"65536"
Maximum WebSocket message size in bytes that the server will accept from a client. Messages larger than this limit cause the connection to be closed. The default is 65536 (64 KiB).Increase this value only if you have clients that send unusually large individual WebSocket frames.
log_level
string
default:"\"info\""
Minimum severity of log messages written to stderr.
ValueDescription
"error"Fatal and non-fatal errors only
"warn"Errors and warnings
"info"Normal operational messages (default)
"debug"Detailed diagnostic output
"trace"Very verbose per-packet tracing
"off"Disable all logging
runtime
string
default:"\"multithread\""
The Tokio async runtime flavor used by the server.
ValueDescription
"singlethread"Single-threaded runtime — lowest overhead, no parallelism
"multithread"Work-stealing multi-threaded runtime (default) — best general-purpose choice
"multithreadalt"Alternate multi-threaded runtime — only available when the server is compiled with RUSTFLAGS="--cfg tokio_unstable"
"threadpercore"Spawns one single-threaded runtime per logical CPU core — highest throughput on CPU-bound workloads
"multithread" is the right choice for the vast majority of deployments. Switch to "threadpercore" only after profiling shows CPU saturation with "multithread". The "multithreadalt" variant requires an unstable Tokio build flag and is not available in standard release binaries.

Complete example

[server]
bind = ["tcp", "0.0.0.0:4000"]
transport = "websocket"
resolve_ipv6 = false
tcp_nodelay = true
file_raw_mode = false
tls_keypair = ["/etc/epoxy/cert.pem", "/etc/epoxy/key.pem"]
stats_endpoint = "/stats"
use_real_ip_headers = true
non_ws_response = ":3"
max_message_size = 65536
log_level = "info"
runtime = "multithread"
When running epoxy-server behind a reverse proxy such as nginx or Caddy, set use_real_ip_headers = true so that access logs and IP-based filtering use the real client address rather than the proxy’s address. Make sure your reverse proxy is configured to forward X-Real-IP or X-Forwarded-For and that epoxy-server is not directly reachable from the internet, or clients will be able to forge these headers.

Build docs developers (and LLMs) love