Introduction
I wanted to create an article site to share my knowledge and also
contribute to OpenBSD somehow, so I had the idea to host it in an
OpenBSD VPS. Searching how can I do it, I found about
httpd
, relayd
and acme-client
,
all available at OpenBSD man
pages.
How it works?
We will setup httpd(8)
for serving the content,
relayd(8)
for tls termination and security headers,
acme-client(1)
for managing and getting certifications, and
pf
for setting rules in our server.
| request acme-client (Let's Encrypt cert renewals)
| ^
| |
v v
---> relayd (tls termination + security headers) ---> httpd (serves static files)
acme-client
If you want, copy the example acme-client.conf(5)
in
/etc/examples/acme-client.conf
to
/etc/acme-client.conf
to have it as template.
# cp /etc/examples/acme-client.conf /etc/
Now, configure acme-client.conf(5)
in /etc
directory, example:
# Authorities contactable by acme
authority letsencrypt {
api url "https://acme-v02.api.letsencrypt.org/directory"
account key "/etc/acme/letsencrypt-privkey.pem"
}
# Certificates for domain via letsencrypt
domain fugu.cafe {
# Subdomains
alternative names { www.fugu.cafe }
domain key "/etc/ssl/private/fugu.cafe.key"
domain full chain certificate "/etc/ssl/fugu.cafe.crt"
sign with letsencrypt
}
Now you can generate the certificate. If you already set up relayd, you must reload it after generating the certificate.
# acme-client -v fugu.cafe
If you want renewal, you can setup a cron(8)
job with
this command plus relayd(8)
reloading.
# Every 03:00
0 3 * * * acme-client fugu.cafe && rcctl restart relayd
httpd
If you want, copy the example httpd.conf(5)
in
/etc/examples/httpd.conf
to /etc/httpd.conf
to
have it as template.
# cp /etc/examples/httpd.conf /etc/
Now, configure httpd.conf(5)
in /etc
directory. It's recommended to put your static site under
/var/www/htdocs/
. Here is an example:
# Redirects to https
server "fugu.cafe" {
listen on 127.0.0.1 port 80
location * {
block return 301 "https://$HTTP_HOST$REQUEST_URI"
}
}
server "fugu.cafe" {
alias "www.fugu.cafe"
listen on 127.0.0.1 port 8080
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
# Recommended to set it in htdocs, i did it outside.
# e.g. /htdocs/fugu.cafe
root "/fugu.cafe"
location "/" {
block return 302 "/main/"
}
# Block hidden files
location "/.*" {
block
}
}
It's recommended to change your static website directory owner to
www
, because httpd(8)
is run as
www
user as default.
# chown -R www:www /var/www/fugu.cafe
Check for any errors in httpd configuration.
# httpd -n
If your configuration is OK, you can start or restart
httpd(8)
.
# rcctl enable httpd
# rcctl start httpd
relayd
If you want, copy the example relayd.conf(5)
in
/etc/examples/relayd.conf
to /etc/relayd.conf
to have it as template.
# cp /etc/examples/relayd.conf /etc/
Now, configure relayd.conf(5)
in /etc
directory, example:
ipv4="<address4>"
ipv6="<address6>"
table <local> { 127.0.0.1 }
http protocol https {
tls keypair "fugu.cafe"
tls ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"
# Security headers
match response header set "Referrer-Policy" value "same-origin"
match response header set "X-Frame-Options" value "deny"
match response header set "X-XSS-Protection" value "1; mode=block"
match response header set "X-Content-Type-Options" value "nosniff"
match response header set "Strict-Transport-Security" value "max-age=31536000; includeSubDomains; preload"
match response header set "Content-Security-Policy" value "default-src 'self'; style-src 'self'; img-src 'self'; base-uri 'self'; frame-ancestors"
match response header set "Permissions-Policy" value "accelerometer=()"
match response header set "Cache-Control" value "max-age=86400"
match request header append "X-Forwarded-For" value "$REMOTE_ADDR"
match request header append "X-Forwarded-Port" value "$REMOTE_PORT"
return error
pass
}
relay wwwtls {
listen on $ipv4 port 443 tls
protocol https
forward to <local> port 8080
}
relay www6tls {
listen on $ipv6 port 443 tls
protocol https
forward to <local> port 8080
}
# I didn't want to go direct to httpd in case of http for usability
relay www {
listen on $ipv4 port 80
forward to <local> port 80
}
relay www6 {
listen on $ipv6 port 80
forward to <local> port 80
}
Feel free to set security headers to your need. Also, check for any errors.
# relayd -n
If your configuration is OK, you can start or restart
relayd(8)
.
# rcctl enable relayd
# rcctl start relayd
Conclusion
If everything is OK, your static site is now fully served by OpenBSD,
using httpd(8)
for content, relayd(8)
for tls
termination and headers, and acme-client(1)
for certificate
management. It’s a simple, secure and minimal setup, entirely maintained
within the system itself.