Synopsis #
relayd(8) is OpenBSD’s native application-layer proxy and filtering daemon. It supports:
- Reverse proxying (HTTP/HTTPS)
- TLS termination with optional re-encryption
- HTTP/HTTPS load balancing with active health checks
- Layer 7 filtering, header rewriting, and redirection
relayd is included in the OpenBSD base system. Configure it in /etc/relayd.conf and use it with PF rules and backend services such as httpd(8).
Use relayd to terminate TLS, filter HTTP requests, or distribute connections across backend servers.
The Web overview compares the content-serving web servers and distinguishes their roles from relayd.
Common Use Cases #
- Terminate TLS and forward HTTP to a local backend
- Filter and forward incoming HTTPS to multiple application servers
- Forward HTTP to an httpd backend that handles FastCGI
- Implement virtual hosting with separate domains and TLS keys
Basic TLS Terminating Reverse Proxy #
The most common relayd use case is to accept TLS connections and forward them unencrypted to a backend.
Example: TLS frontend to local httpd(8) #
http protocol "https" {
tls keypair "example.org"
}
relay "tlsproxy" {
listen on egress port 443 tls
protocol "https"
forward to 127.0.0.1 port 8080
}
Install the certificate chain as /etc/ssl/example.org.crt and the private key as /etc/ssl/private/example.org.key, owned by root with mode 600 for the key. The protocol keypair name selects those files.
On the backend, httpd(8) should listen on localhost port 8080:
server "example.org" {
listen on 127.0.0.1 port 8080
root "/htdocs/example"
}
Start both services:
doas rcctl enable relayd httpd
doas rcctl start relayd httpd
Allow traffic on port 443 in pf.conf:
pass in on egress proto tcp to port 443
Backend Pool with Load Balancing #
The HA HTTPS load-balancer guide combines a backend pool with certificates, client-address handling and frontend failover. Use NAT or DSR when relayd should manage PF forwarding rather than accept the client connection itself.
relayd can distribute traffic across multiple backend hosts using a table:
table <webservers> { 192.0.2.10, 192.0.2.11, 192.0.2.12 }
relay "cluster" {
listen on egress port 80
forward to <webservers> port 80 check tcp
}
The explicit check tcp enables TCP connection health checks.
To use HTTP health checks, replace the forward to line inside the relay with:
forward to <webservers> port 80 check http "/status" code 200
View real-time status:
doas relayctl show hosts
Redirecting HTTP to HTTPS #
Use a separate httpd listener to generate redirects. This belongs in /etc/httpd.conf, with port 80 available for httpd:
server "example.org" {
listen on egress port 80
block return 301 "https://example.org$REQUEST_URI"
}
Requests reach relayd on port 443 after the redirect. Merge any ACME challenge exception into the HTTP server before enabling blanket redirects.
Using relayd with FastCGI #
Forward HTTP from relayd to httpd. Configure the fastcgi socket inside httpd to reach the PHP-FPM socket, following the httpd chapter
. A Unix-domain socket cannot be used as a relayd host table entry, and HTTP forwarding does not itself translate HTTP into FastCGI.
Logging and Monitoring #
Enable logging in /etc/relayd.conf:
log state changes
Tail logs via syslog:
doas tail -f /var/log/daemon
Query runtime state:
doas relayctl show sessions
doas relayctl show hosts
doas relayctl show relays
Reload configuration without restart:
doas relayd -n && doas rcctl reload relayd
Security Considerations #
- relayd uses privilege separation; do not infer process privileges from the service name
- Keep TLS private keys private to root; the privileged process handles key loading
- Ensure only intended IPs can access TLS ports
- Combine with
pf(4)for full traffic filtering
Example pf.conf Rule #
block in all
pass in on egress proto tcp from any to (self) port 443
pass in on egress proto tcp from any to (self) port 80
Limit access to internal-only relays by using loopback or RFC1918 address bindings.
Service Management #
Enable at boot and manage via rcctl:
doas rcctl enable relayd
doas rcctl start relayd
doas rcctl check relayd
Check for syntax errors:
doas relayd -n -f /etc/relayd.conf
Reload configuration:
doas relayd -n && doas rcctl reload relayd