So Long Relayd, and Thanks for All the Fish

bradley_taunt3 pts0 comments

So Long Relayd, and Thanks for All the Fish

🏠Home

👋About

✍️Posts

🏗️Projects

🌐Colophon

💸Contribute

🤖Infra

💻Uses

🧠Wiki

So Long Relayd, and Thanks for All the Fish

2026-08-17

Running relayd alongside httpd on your OpenBSD web servers is no longer necessary for injecting HTTP security headers. Thanks to the incredible work by rsadowski@ we now have the ability to set our security headers directly inside httpd. Pretty awesome, right?

Note: I still love relayd and I'm aware that it offers more than simply applying HTTP security headers. If you still prefer using it, that's okay! Please don't yell at me!

Requirements

Before & After

Full Guide

Requirements

As of this time of writing (August 2026) you’ll need to be running your system on OpenBSD -current in order to use these new header sets in httpd. If you’re okay with being on the “cutting-edge”, you can update by running the following:

doas sysupgrade -s

This will trigger a pull of the latest snapshot instead of the next release. Your machine will reboot into the installer automatically, upgrade, and then reboot again.

Before & After

Previously your web server would need to have both of the following in order to include HTTP security headers:

/etc/httpd.conf:

server "yourcooldomain.com" {<br>alias "www.yourcooldomain.com"<br>listen on * tls port 443<br>root "/htdocs/yourcooldomain.com"<br>hsts

location "/.well-known/acme-challenge/*" {<br>root "/acme"<br>request strip 2

tls {<br>certificate "/etc/ssl/yourcooldomain.com.crt"<br>key "/etc/ssl/private/yourcooldomain.com.key"<br>server "yourcooldomain.com" {<br>alias "www.yourcooldomain.com"<br>listen on * port 80

location "/.well-known/acme-challenge/*" {<br>root "/acme"<br>request strip 2

block return 301 "https://$SERVER_NAME$REQUEST_URI"

/etc/relayd.conf:

ip4="YOUR IPv4"<br>ip6="YOUR IPv6"<br>table { 127.0.0.1 }<br>log connection

http protocol https {<br>match request header append "X-Forwarded-For" value "$REMOTE_ADDR"<br>match request header append "X-Forwarded-By" \<br>value "$SERVER_ADDR:$SERVER_PORT"<br>match request header set "Connection" value "close"

# Add security headers<br>match response header append "Strict-Transport-Security" value "max-age=31536000; includeSubDomains; preload"<br>match response header append "Cache-Control" value "public, max-age=86400"<br>match response header append "Content-Security-Policy" value "default-src 'self'; script-src 'self'; object-src 'none';"<br>match response header append "X-Content-Type-Options" value "nosniff"<br>match response header append "X-Frame-Options" value "SAMEORIGIN"<br>match response header append "Referrer-Policy" value "no-referrer"<br>match response header append "Permissions-Policy" value "interest-cohort=()"

match request header set "Accept-Encoding" value "gzip, deflate"

relay wwwtls {<br>listen on $ip4 port 443 tls<br>protocol https<br>forward to port 8080 check icmp<br>relay www6tls {<br>listen on $ip6 port 443 tls<br>protocol https<br>forward to port 8080 check icmp

But now we can place everything directly inside our httpd.conf, like so:

server "yourcooldomain.com" {<br>listen on * tls port 443<br>root "/htdocs/yourcooldomain.com"<br>hsts

# Security headers<br>header set "Strict-Transport-Security" "max-age=31536000; includeSubDomains; preload"<br>header set "Content-Security-Policy" "default-src 'self'; script-src 'self'; object-src 'none';"<br>header set "X-Content-Type-Options" "nosniff" always<br>header set "X-Frame-Options" "SAMEORIGIN" always<br>header set "Referrer-Policy" "no-referrer" always<br>header set "X-Permitted-Cross-Domain-Policies" "none" always<br>header set "X-XSS-Protection" "0" always<br>header set "Permissions-Policy" "interest-cohort=()"

# Avoid info leak: strip the revealing header (optional)<br>header remove "X-Powered-By"

location "/.well-known/acme-challenge/*" {<br>root "/acme"<br>request strip 2

tls {<br>certificate "/etc/ssl/yourcooldomain.com.crt"<br>key "/etc/ssl/private/yourcooldomain.com.key"

The above security header settings are just my personal preferences, this can be changed as you see fit. But that’s it!

Full Guide

If you’d like a more detailed guide that takes you through the entire process of setting up your own httpd web server running on OpenBSD, check it out here: httpd.rocks

Found this blog useful?<br>Consider donating or buy some custom stickers!

&uarr; Top of page

Website generated with wruby

Hosted on NearlyFreeSpeech.NET

View this website's source code

Check out NextDNS, TierHive & Fathom

No ads, trackers or cookies. Ever.

RSS Feed | Terms of Use

header security yourcooldomain match value append

Related Articles