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 [wisp] section of the epoxy-server configuration file controls everything related to the Wisp protocol layer: which version of the protocol is negotiated, which Wisp v2 extensions are advertised to clients, how authentication is enforced, and what message of the day is sent on connect. These settings are independent of the network listener (configured in [server]) and the per-stream filtering rules (configured in [stream]).

[wisp] fields

wisp_v2
boolean
default:"true"
Enable Wisp version 2 handshaking and extension negotiation. When true (the default), the server performs the Wisp v2 handshake and advertises the extensions listed in extensions. When false, the server falls back to Wisp v1, which has no extension support.Disable this only when you need to support clients that do not implement Wisp v2.
extensions
string[]
default:"[\"udp\", \"motd\"]"
List of Wisp v2 protocol extensions advertised during the handshake. Only applies when wisp_v2 = true.
ValueDescription
"udp"Enables Wisp v2 UDP stream support
"motd"Sends the motd_extension string to clients on connect
"wispnet"Unofficial Wispnet-like extension for inter-server routing
extensions = ["udp", "motd"]
The authentication extension ("password" or "certificate") is not listed here — it is configured separately via the auth_extension field.
auth_extension
string | null
default:"null"
Wisp v2 authentication extension to advertise. When set, clients must complete the chosen authentication challenge during the Wisp v2 handshake. Requires wisp_v2 = true.
ValueDescription
"password"Username/password authentication — see password_extension_users
"certificate"Ed25519 public-key authentication — see certificate_extension_keys
nullNo authentication (default)
Only one authentication method can be active at a time.
buffer_size
integer
default:"128"
Flow-control buffer size advertised to clients in the Wisp handshake, expressed as a number of packets. Clients use this value to determine how many packets they may send before waiting for the server to acknowledge receipt.Increase this value to improve throughput on high-latency connections. Very large values may increase memory usage under load.
prefix
string
default:"\"\""
URL path prefix for the Wisp endpoint. The server strips this prefix before handling the WebSocket upgrade. Do not include a trailing slash.
# Wisp endpoint will be reachable at /wisp
prefix = "/wisp"
Leave empty (the default) to serve Wisp at the root path /.
allow_wsproxy
boolean
default:"true"
Allow legacy wsproxy connections in addition to the Wisp protocol. wsproxy is an older, simpler tunneling protocol that predates Wisp. Disable this if you only want to accept Wisp clients and want to reduce attack surface.
read_limit
float
default:"Infinity"
Maximum read throughput in bytes per second applied across all streams within a single Wisp connection. When the aggregate incoming data rate exceeds this limit the connection is throttled. The default is Infinity (no limit).
This field is only available when epoxy-server is compiled with the speed-limit feature flag. It has no effect in standard release builds that omit this feature.
# Limit each connection to 10 MB/s read throughput
read_limit = 10_000_000.0
write_limit
float
default:"Infinity"
Maximum write throughput in bytes per second applied across all streams within a single Wisp connection. When the aggregate outgoing data rate exceeds this limit the connection is throttled. The default is Infinity (no limit).
This field is only available when epoxy-server is compiled with the speed-limit feature flag. It has no effect in standard release builds that omit this feature.
# Limit each connection to 10 MB/s write throughput
write_limit = 10_000_000.0
password_extension_users
object
default:"{}"
Map of username → password pairs used when auth_extension = "password". Clients must supply a matching username and password during the Wisp v2 handshake to be permitted.
[wisp.password_extension_users]
alice = "correct-horse-battery-staple"
bob   = "hunter2"
This field is omitted from the serialized default config when it is empty.
password_extension_required
boolean
default:"true"
When true (the default) and auth_extension = "password", authentication is mandatory — clients that do not present valid credentials are rejected. Set to false to make authentication optional (clients that skip the challenge are still allowed).
certificate_extension_keys
string[]
default:"[]"
Paths to Ed25519 public key files in PEM format, used when auth_extension = "certificate". Clients must possess the corresponding private key and prove ownership during the Wisp v2 handshake.
certificate_extension_keys = [
  "/etc/epoxy/keys/alice.pub.pem",
  "/etc/epoxy/keys/bob.pub.pem"
]
This field is omitted from the serialized default config when it is empty.
certificate_extension_required
boolean
default:"true"
When true (the default) and auth_extension = "certificate", certificate authentication is mandatory. Set to false to permit connections from clients that do not provide a certificate.
motd_extension
string
default:"\"epoxy_server (<version>)\""
The message of the day sent to clients via the Wisp v2 MOTD extension. Only delivered when "motd" is included in extensions. The default value includes the server version string, git SHA, and compiler info.
motd_extension = "Welcome to my Wisp server!"

Authentication examples

Password authentication

[wisp]
wisp_v2 = true
extensions = ["udp", "motd"]
auth_extension = "password"
password_extension_required = true
motd_extension = "Authentication required."

[wisp.password_extension_users]
alice = "correct-horse-battery-staple"
bob   = "hunter2"

Certificate authentication

Generate an Ed25519 keypair for each user (for example with openssl), distribute the private key to the client, and add the public key path to the server config:
openssl genpkey -algorithm ed25519 -out alice.key.pem
openssl pkey -in alice.key.pem -pubout -out alice.pub.pem
[wisp]
wisp_v2 = true
extensions = ["udp", "motd"]
auth_extension = "certificate"
certificate_extension_required = true
certificate_extension_keys = [
  "/etc/epoxy/keys/alice.pub.pem"
]
motd_extension = "Certificate authentication required."
With auth_extension = "password", usernames and passwords are transmitted in plaintext at the Wisp protocol level. If epoxy-server is exposed directly over plain TCP without TLS, credentials are visible to any network observer. Always ensure the connection between epoxy-client and epoxy-server is encrypted — either by using a TLS socket type ("tlstcp" / "tlsunix") in [server], or by placing epoxy-server behind a TLS-terminating reverse proxy such as nginx or Caddy. Note that epoxy-client itself also performs an inner TLS handshake for destination traffic, but that does not protect the Wisp authentication exchange.

Build docs developers (and LLMs) love