Configuration / HTTP
Servers & routing
A server declares an IP/port listener, an optional virtual-host name, and its routes.
Listener
[[http.servers]]
listen = "127.0.0.1:8080"
server_name = "example.test"
listen is required and must be a literal socket address. Use 127.0.0.1 for local access, 0.0.0.0 for all IPv4 interfaces, or an IPv6 form such as [::1]:8080. The name is optional.
Virtual hosts
[[http.servers]]
listen = "0.0.0.0:8080"
server_name = "www.example.test"
[[http.servers]]
listen = "0.0.0.0:8080"
server_name = "api.example.test"
Identical addresses share one listener. Thwip matches the request Host to server_name, ignoring ASCII case and the port. The first server in a listener group is the fallback, so place the desired default first.
SSL / TLS ingress
[[http.servers]]
listen = "0.0.0.0:443"
server_name = "example.test"
ssl = { certificate_path = "/etc/thwip/fullchain.pem", private_key_path = "/etc/thwip/privkey.pem", handshake_timeout_ms = 10000, protocols = ["tlsv1_2", "tlsv1_3"] }
Adding ssl makes this listener accept TLS rather than plaintext HTTP. Certificate and key paths must be readable PEM files. TLS 1.2 and TLS 1.3 are supported; omit protocols and ciphers to use the secure defaults.
SSL is optional. A server without an ssl block remains plaintext. One certificate is selected per listener today, so do not place multiple certificate-requiring virtual hosts on the same address until SNI support lands. HTTPS upstreams are also separate, unsupported work.
Matchers and precedence
[[http.servers.locations]]
matcher = { type = "exact", path = "/health" }
action = { type = "response", status = 200, body = "OK" }
[[http.servers.locations]]
matcher = { type = "prefix", path = "/api" }
action = { type = "proxy", upstream_group = "api" }
exact targets one path. prefix targets paths beginning with its value. Exact wins first; otherwise the longest prefix wins, so /api/admin beats /api.
Home