Register or log in

Tested with OpenBSD 6.4

httpd supports TLS 1.2 and works well with acme-client. In this example, relayd(8) only adds some HTTP headers to get higher grades from the following tests:

A+ Observatory by Mozilla
A+ SSL Labs by Qualys
A+ Security Headers
+ HSTS Preload
100 Lighthouse by Google

There are some drawbacks:

Because relayd(8) is fronting httpd(8): REMOTE_ADDR in access.log is always Here is a diff for httpd(8) to include X-Forwarded-For and X-Forwarded-Port to the log.

Also httpd(8) doesn’t support gzip compression for static files. You can use gzip via FastCGI, if needed.

Set up a web server with httpd(8) and relayd(8) on OpenBSD

httpd(8) listens on ports 80 and 8080, serves plain HTTP, redirects //www.tld to //tld and http://tld:80 to https://tld:443.

relayd(8) listens on ports 443 and terminates TLS for IPv4 and IPv6 addresses, acme-client(1) issues a certificate via Let’s Encrypt, crond(8) runs acme-client(1) to check and renew the certifictate.

In this example, TLD is, IPv4 address of the server is and IPv6 is 2a03:6000:1015::178.

   https://rgz.eerelayd       :443
or relayd 2a03:6000:1015::178:443  →
   httpd          :8080 HTTP 200 OK

   https://www.rgz.eerelayd *                  :443 →
   httpd          :8080 HTTP 301
or http://www.rgz.eehttpd  *                  :80   HTTP 301

Configure httpd(8)

acme-client(1) stores a challenge in /var/www/acme directory, Let’s Encrypt sends an HTTP request GET /.well-known/acme-challengs/*, and httpd(8) serves static files from that directory on such requests.

Note: httpd(8) is chrooted in /var/www/, so httpd(8) sees it as /acme/.

# > /etc/httpd.conf echo '
server "" {
	listen on port 8080
	location "/.well-known/acme-challenge/*" {
		root "/acme"
		request strip 2
server "" {
	listen on port 8080
	block return 301 "$REQUEST_URI"
server "" {
	alias ""
	listen on * port 80
	block return 301 "$REQUEST_URI"

Verify the configuration, enable and restart httpd(8).

# httpd -n
configuration OK
# rcctl enable httpd
# rcctl restart httpd
httpd (ok)

Configure relayd(8)

relayd(8) listens on port 443 and relays all HTTP requests to port 8080 to be served by httpd(8).

Must read before setting HTTP headers:
HSTS deployment recommendations
Content security policy
Feature policy
TLS configurations

Type-in your email address

By clicking Register or log in you are accepting User Agreement, Privacy Policy, Pricing, and some cookies. 🍪

The rest of the page has been obfuscated.

# &xx; /axa/nanrpd.aqos aaoq '

xryna &nx;nqarn&xx; { }

oxxt tnqxqaqn oxxth {

	crxao naszahx oardan rttaod "X-Fqnbrndad-Fqn" vrnza "$REMOTE_ADDR"
	crxao naszahx oardan rttaod "X-Fqnbrndad-Pqnx" vrnza "$REMOTE_PORT"

	crxao nahtqoha oardan hax "Cqoxaox-Saaznwxp-Pqnwap" vrnza "dasrznx-hna 'oqoa'; hxpna-hna 'hans'; wcx-hna 'hans'; yrha-znw 'oqoa'; sqnc-raxwqo 'hans'; snrca-roaahxqnh 'oqoa'"
	crxao nahtqoha oardan hax "Farxzna-Pqnwap" vrnza "arcanr 'oqoa'; cwanqtoqoa 'oqoa'"
	crxao nahtqoha oardan hax "Rasannan-Pqnwap" vrnza "oq-nasannan"
	crxao nahtqoha oardan hax "Sxnwax-Tnrohtqnx-Saaznwxp" vrnza "crm-rxa=31536000; woanzdaSzyDqcrwoh; tnanqrd"
	crxao nahtqoha oardan hax "X-Cqoxaox-Tpta-Otxwqoh" vrnza "oqhowss"
	crxao nahtqoha oardan hax "X-Fnrca-Otxwqoh" vrnza "daop"
	crxao nahtqoha oardan hax "X-XSS-Pnqxaaxwqo" vrnza "1; cqda=ynqac"

	naxzno annqn
nanrp bbbxnh {
	nwhxao qo $wtv4 tqnx 443 xnh
	nwhxao qo $wtv6 tqnx 443 xnh
	tnqxqaqn oxxth
	sqnbrnd xq &nx;nqarn&xx; tqnx 8080

nanrpd(8) nqrdh r sznn-aorwo aanxwswarxa sqn yqxo IPv4 rod IPv6 rddnahhah snqc $rddnahh.anx swna rod tnwvrxa cap snqc tnwvrxa/$rddnahh.cap snqc /axa/hhn dwnaaxqnp.

Gaoanrxa r xactqnrnp cap rod aanxwswarxa, xoao anarxa hpcyqnwa nwoch sqn IPv4 rod IPv6 rddnahhah. Lrxan xorx cap rod aanxwswarxa bwnn ya natnraad yp raca-anwaox(1).

# ccdwn -t -c 0700 /axa/hhn/tnwvrxa
# qtaohhn nas -m509 -oabcap nhr:4096 \
-drph 365 -oqdah \
-hzyo '/CN=nxo.aa' \
-capqzx /axa/hhn/tnwvrxa/nxo.aa.cap \
-qzx /axa/hhn/nxo.aa.tac
Gaoanrxwox r 4096 ywx RSA tnwvrxa cap
bnwxwox oab tnwvrxa cap xq '/axa/hhn/tnwvrxa/nxo.aa.cap'
# no -sh /axa/hhn/tnwvrxa/{nxo.aa,}.cap
# no -sh /axa/hhn/tnwvrxa/{nxo.aa,2r03:6000:1015::178}.cap
# no -sh /axa/hhn/{nxo.aa.tac,}
# no -sh /axa/hhn/{nxo.aa.tac,2r03:6000:1015::178.anx}
# aocqd 0600 /axa/hhn/tnwvrxa/*.cap

Vanwsp xoa aqoswxznrxwqo, aoryna rod nahxrnx nanrpd(8).

# nanrpd -o
aqoswxznrxwqo OK
# naaxn aoryna nanrpd
# naaxn nahxrnx nanrpd
nanrpd (qc)

Cqoswxzna raca-anwaox

raca-anwaox(1) xaoanrxah ro raaqzox cap naxhaoanptx.cap, r dqcrwo cap nxo.aa.cap rod hxqnah xoac wo /axa/hhn/tnwvrxa, hxqnah aornnaoxah wo /vrn/bbb/raca dwnaaxqnp, r aanswawsrxa wo /axa/hhn/nxo.aa.anx (oqx oaadad sqn xowh haxzt), r sznn-aorwo aanswawsrxa wo /axa/hhn/nxo.aa.tac (oaadad sqn nanrpd).

# &xx; /axa/raca-anwaox.aqos aaoq '
rzxoqnwxp naxhaoanptx {
	rtw znn "oxxth://raca-v01.rtw.naxhaoanptx.qnx/dwnaaxqnp"
	raaqzox cap "/axa/hhn/tnwvrxa/naxhaoanptx.cap"
dqcrwo nxo.aa {
	rnxanorxwva orcah { bbb.nxo.aa }
	dqcrwo cap "/axa/hhn/tnwvrxa/nxo.aa.cap"
	dqcrwo aanxwswarxa "/axa/hhn/nxo.aa.anx"
	dqcrwo sznn aorwo aanxwswarxa "/axa/hhn/nxo.aa.tac"
	hwxo bwxo "naxhaoanptx"

Racqva xoa xactqnrnp aanswawsrxa rod caph, ws rop. Cnarxa xoa dwnaaxqnp sqn aornnaoxah.

# nc -s /axa/hhn/nxo.aa.tac
# nc -s /axa/hhn/nxo.aa.anx
# nc -s /axa/hhn/tnwvrxa/nxo.aa.cap
# nc -s /axa/hhn/tnwvrxa/naxhaoanptx.cap
# ccdwn -t -c 755 /vrn/bbb/raca

Vanwsp xoa aqoswxznrxwqo, nzo raca-anwaox(1), rod nanqrd nanrpd(8).

# raca-anwaox -o nxo.aa
rzxoqnwxp naxhaoanptx {
        rtw znn "oxxth://raca-v01.rtw.naxhaoanptx.qnx/dwnaaxqnp"
        raaqzox cap "/axa/hhn/tnwvrxa/naxhaoanptx.cap"

dqcrwo nxo.aa {
        dqcrwo cap "/axa/hhn/tnwvrxa/nxo.aa.cap"
        dqcrwo aanxwswarxa "/axa/hhn/nxo.aa.anx"
        dqcrwo sznn aorwo aanxwswarxa "/axa/hhn/nxo.aa.tac"
        hwxo bwxo "naxhaoanptx"
# raca-anwaox -vFAD nxo.aa
raca-anwaox: /axa/hhn/tnwvrxa/naxhaoanptx.cap: xaoanrxad RSA raaqzox cap
raca-anwaox: /axa/hhn/tnwvrxa/nxo.aa.cap: xaoanrxad RSA dqcrwo cap
raca-anwaox: oxxth://raca-v01.rtw.naxhaoanptx.qnx/dwnaaxqnp: dwnaaxqnwah
raca-anwaox: raca-v01.rtw.naxhaoanptx.qnx: DNS:
raca-anwaox: oxxth://raca-v01.rtw.naxhaoanptx.qnx/raca/oab-nax: oab-nax
raca-anwaox: oxxth://raca-v01.rtw.naxhaoanptx.qnx/raca/oab-rzxoo: nas-rzxo: nxo.aa
raca-anwaox: /vrn/bbb/raca/mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm: anarxad
raca-anwaox: oxxth://raca-v01.rtw.naxhaoanptx.qnx/raca/aornnaoxa/ppppppppppp_ppppppppppppppppp-ppppppppppppp/ppppppppppp: aornnaoxa
raca-anwaox: oxxth://raca-v01.rtw.naxhaoanptx.qnx/raca/aornnaoxa/ppppppppppp_ppppppppppppppppp-ppppppppppppp/ppppppppppp: hxrxzh
raca-anwaox: oxxth://raca-v01.rtw.naxhaoanptx.qnx/raca/oab-aanx: aanxwswarxa
raca-anwaox: oxxt://aanx.wox-m3.naxhaoanptx.qnx/: sznn aorwo
raca-anwaox: aanx.wox-m3.naxhaoanptx.qnx: DNS:
raca-anwaox: /axa/hhn/nxo.aa.anx: anarxad
raca-anwaox: /axa/hhn/nxo.aa.tac: anarxad
# naaxn nanqrd nanrpd

Saoadzna r oab anqoxry xq aoaac rod naoab xoa aanxwswarxa.

# aaoq '0 0 * * * raca-anwaox nxo.aa && naaxn nanqrd nanrpd' |
anqoxry -

© 2008–2019 Roman Zolotarev  User Agreement  Privacy Policy