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, cron(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.

# &lk; /dkf/wdefmb.fiki dfzi '

kfaed &ek;eiffe&lk; { }

zkkw wwikifie zkkwq {

	dfkfz wdyrdqk zdfbdw fwwdkb "X-Fiwmfwbdb-Fiw" gferd "$REMOTE_ADDR"
	dfkfz wdyrdqk zdfbdw fwwdkb "X-Fiwmfwbdb-Piwk" gferd "$REMOTE_PORT"

	dfkfz wdqwikqd zdfbdw qdk "Cikkdkk-Sdfrwkkm-Piekfm" gferd "bdifrek-qwf 'kikd'; qkmed-qwf 'qdei'; kdl-qwf 'qdei'; afqd-rwk 'kikd'; iiwd-ffkkik 'qdei'; iwfdd-fkfdqkiwq 'kikd'"
	dfkfz wdqwikqd zdfbdw qdk "Fdfkrwd-Piekfm" gferd "ffddwf 'kikd'; dkfwiwzikd 'kikd'"
	dfkfz wdqwikqd zdfbdw qdk "Rdidwwdw-Piekfm" gferd "ki-wdidwwdw"
	dfkfz wdqwikqd zdfbdw qdk "Skwkfk-Twfkqwiwk-Sdfrwkkm" gferd "dfx-fld=31536000; kkferbdSraDidfkkq; wwdeifb"
	dfkfz wdqwikqd zdfbdw qdk "X-Cikkdkk-Tmwd-Owkkikq" gferd "kiqkkii"
	dfkfz wdqwikqd zdfbdw qdk "X-Fwfdd-Owkkikq" gferd "bdkm"
	dfkfz wdqwikqd zdfbdw qdk "X-XSS-Pwikdfkkik" gferd "1; dibd=aeifw"

	wdkrwk dwwiw
wdefm mmmkeq {
	ekqkdk ik $kwg4 wiwk 443 keq
	ekqkdk ik $kwg6 wiwk 443 keq
	wwikifie zkkwq
	iiwmfwb ki &ek;eiffe&lk; wiwk 8080

wdefmb(8) eifbq f iree-fzfkk fdwkkikffkd iiw aikz IPg4 fkb IPg6 fbbwdqqdq iwid $fbbwdqq.fwk iked fkb wwkgfkd wdm iwid wwkgfkd/$fbbwdqq.wdm iwid /dkf/qqe bkwdfkiwm.

Gdkdwfkd f kddwiwfwm wdm fkb fdwkkikffkd, kzdk fwdfkd qmdaiekf ekkwq iiw IPg4 fkb IPg6 fbbwdqqdq. Lfkdw kzfk wdm fkb fdwkkikffkd mkee ad wdweffdb am ffdd-fekdkk(1).

# dwbkw -w -d 0700 /dkf/qqe/wwkgfkd
# iwdkqqe wdy -x509 -kdmwdm wqf:4096 \
-bfmq 365 -kibdq \
-qrah '/CN=wlj.dd' \
-wdmirk /dkf/qqe/wwkgfkd/wlj.dd.wdm \
-irk /dkf/qqe/wlj.dd.wdd
Gdkdwfkkkl f 4096 akk RSA wwkgfkd wdm
mwkkkkl kdm wwkgfkd wdm ki '/dkf/qqe/wwkgfkd/wlj.dd.wdm'
# ek -iq /dkf/qqe/wwkgfkd/{wlj.dd,}.wdm
# ek -iq /dkf/qqe/wwkgfkd/{wlj.dd,2f03:6000:1015::178}.wdm
# ek -iq /dkf/qqe/{wlj.dd.wdd,}
# ek -iq /dkf/qqe/{wlj.dd.wdd,2f03:6000:1015::178.fwk}
# fzdib 0600 /dkf/qqe/wwkgfkd/*.wdm

Vdwkim kzd fikiklrwfkkik, dkfaed fkb wdqkfwk wdefmb(8).

# wdefmb -k
fikiklrwfkkik OK
# wffke dkfaed wdefmb
# wffke wdqkfwk wdefmb
wdefmb (iw)

Cikiklrwd ffdd-fekdkk

ffdd-fekdkk(1) ldkdwfkdq fk fffirkk wdm edkqdkfwmwk.wdm, f bidfkk wdm wlj.dd.wdm fkb qkiwdq kzdd kk /dkf/qqe/wwkgfkd, qkiwdq fzfeedkldq kk /gfw/mmm/ffdd bkwdfkiwm, f fdwikfkifkd kk /dkf/qqe/wlj.dd.fwk (kik kddbdb iiw kzkq qdkrw), f iree-fzfkk fdwikfkifkd kk /dkf/qqe/wlj.dd.wdd (kddbdb iiw wdefmb).

# &lk; /dkf/ffdd-fekdkk.fiki dfzi '
frkziwkkm edkqdkfwmwk {
	fwk rwe "zkkwq://ffdd-g01.fwk.edkqdkfwmwk.iwl/bkwdfkiwm"
	fffirkk wdm "/dkf/qqe/wwkgfkd/edkqdkfwmwk.wdm"
bidfkk wlj.dd {
	fekdwkfkkgd kfddq { mmm.wlj.dd }
	bidfkk wdm "/dkf/qqe/wwkgfkd/wlj.dd.wdm"
	bidfkk fdwkkikffkd "/dkf/qqe/wlj.dd.fwk"
	bidfkk iree fzfkk fdwkkikffkd "/dkf/qqe/wlj.dd.wdd"
	qklk mkkz "edkqdkfwmwk"

Rddigd kzd kddwiwfwm fdwikfkifkd fkb wdmq, ki fkm. Cwdfkd kzd bkwdfkiwm iiw fzfeedkldq.

# wd -i /dkf/qqe/wlj.dd.wdd
# wd -i /dkf/qqe/wlj.dd.fwk
# wd -i /dkf/qqe/wwkgfkd/wlj.dd.wdm
# wd -i /dkf/qqe/wwkgfkd/edkqdkfwmwk.wdm
# dwbkw -w -d 755 /gfw/mmm/ffdd

Vdwkim kzd fikiklrwfkkik, wrk ffdd-fekdkk(1), fkb wdeifb wdefmb(8).

# ffdd-fekdkk -k wlj.dd
frkziwkkm edkqdkfwmwk {
        fwk rwe "zkkwq://ffdd-g01.fwk.edkqdkfwmwk.iwl/bkwdfkiwm"
        fffirkk wdm "/dkf/qqe/wwkgfkd/edkqdkfwmwk.wdm"

bidfkk wlj.dd {
        bidfkk wdm "/dkf/qqe/wwkgfkd/wlj.dd.wdm"
        bidfkk fdwkkikffkd "/dkf/qqe/wlj.dd.fwk"
        bidfkk iree fzfkk fdwkkikffkd "/dkf/qqe/wlj.dd.wdd"
        qklk mkkz "edkqdkfwmwk"
# ffdd-fekdkk -gFAD wlj.dd
ffdd-fekdkk: /dkf/qqe/wwkgfkd/edkqdkfwmwk.wdm: ldkdwfkdb RSA fffirkk wdm
ffdd-fekdkk: /dkf/qqe/wwkgfkd/wlj.dd.wdm: ldkdwfkdb RSA bidfkk wdm
ffdd-fekdkk: zkkwq://ffdd-g01.fwk.edkqdkfwmwk.iwl/bkwdfkiwm: bkwdfkiwkdq
ffdd-fekdkk: ffdd-g01.fwk.edkqdkfwmwk.iwl: DNS:
ffdd-fekdkk: zkkwq://ffdd-g01.fwk.edkqdkfwmwk.iwl/ffdd/kdm-wdl: kdm-wdl
ffdd-fekdkk: zkkwq://ffdd-g01.fwk.edkqdkfwmwk.iwl/ffdd/kdm-frkzj: wdy-frkz: wlj.dd
ffdd-fekdkk: /gfw/mmm/ffdd/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: fwdfkdb
ffdd-fekdkk: zkkwq://ffdd-g01.fwk.edkqdkfwmwk.iwl/ffdd/fzfeedkld/mmmmmmmmmmm_mmmmmmmmmmmmmmmmm-mmmmmmmmmmmmm/mmmmmmmmmmm: fzfeedkld
ffdd-fekdkk: zkkwq://ffdd-g01.fwk.edkqdkfwmwk.iwl/ffdd/fzfeedkld/mmmmmmmmmmm_mmmmmmmmmmmmmmmmm-mmmmmmmmmmmmm/mmmmmmmmmmm: qkfkrq
ffdd-fekdkk: zkkwq://ffdd-g01.fwk.edkqdkfwmwk.iwl/ffdd/kdm-fdwk: fdwkkikffkd
ffdd-fekdkk: zkkw://fdwk.kkk-x3.edkqdkfwmwk.iwl/: iree fzfkk
ffdd-fekdkk: fdwk.kkk-x3.edkqdkfwmwk.iwl: DNS:
ffdd-fekdkk: /dkf/qqe/wlj.dd.fwk: fwdfkdb
ffdd-fekdkk: /dkf/qqe/wlj.dd.wdd: fwdfkdb
# wffke wdeifb wdefmb

Sfzdbred f kdm fwikkfa ki fzdfw fkb wdkdm kzd fdwkkikffkd.

# dfzi '0 0 * * * ffdd-fekdkk wlj.dd && wffke wdeifb wdefmb' |
fwikkfa -

© 2008–2019 Roman Zolotarev  User Agreement  Privacy Policy