LUNARTHALE

Create a Simple Static Site on OpenBSD 6.6

5-February-2020


This is not a how-to per se, but more like a record of my journey on setting a simple static site up on OpenBSD 6.6. You should already have installed OpenBSD on your server already. In my case, I use an OpenBSD instance provided by Vultr(the VPS provider). Let's go!!

Httpd and httpd.conf

By default httpd already shipped with OpenBSD already for many versions ago. There are 2 man pages related to setting it up which are httpd and httpd.conf. OpenBSD also provide an example for how to write httpd.conf which located in "/etc/example/"

man httpd
man httpd.conf
cat /etc/examples/httpd.conf

So, with that I first create a simple httpd.conf with this information.

lunatuna:~$ cat /etc/httpd.conf
# my external ip declare as variable
ext_ip = "xxx.xxx.xxx.xxx"

# Non-https
server "example.com" {
    listen on $ext_ip port 80 # Listen on which ip on which port
    block return 301 "http://www.example.com$REQUEST_URI" # Redirect to another one
}

server "www.example.com" {
    listen on $ext_ip port 80
    root "/htdocs/www.example.com" # Specified folder to redirect to
}

Please noted that, httpd chroot ( change your root ) to /var/www/ instead. As you can see from the above, the setting is quite simple. Just redirect this and that. Now you only need to do the following to start httpd

lunatuna:~# httpd -n #to check httpd.conf
configuration OK
lunatuna:-# rcctl enable httpd
lunatuna:-# rcctl start httpd

Now you just need to copy your static site to "/var/www/htdocs/www.example.com", and then your website is up and ready. However, this wasn't finished yet. We still need to SSL it too. We will enable our site with https by using "Let's Encrypt" and "OpenBSD's ACME client".

TLS Certificate
man acme-client
man acme-client.conf
cat /etc/examples/acme-client.conf

We will set our acme-client.conf up with let's encrypt profile which provided in examples of the "acme-client.conf" at "/etc/examples/acme-client.conf".

authority letsencrypt {
    api url "https://acme-v02.api.letsencrypt.org/directory"
    account key "/etc/acme/letsencrypt-privkey.pem"
}

authority letsencrypt-staging {
    api url "https://acme-staging-v02.api.letsencrypt.org/directory"
    account key "/etc/acme/letsencrypt-staging-privkey.pem"
}

domain www.example.com {
    alternative names { example.com }
    domain key "/etc/ssl/private/www.example.com.key"
    domain full chain certificate "/etc/ssl/www.example.com.fullchain.pem"
    sign with letsencrypt
}

Then we need to edit out httpd.conf to included the challenge line according to the man page of "acme-client" with the following.

lunatuna:~$ cat /etc/httpd.conf
# my external ip declare as variable
ext_ip = "xxx.xxx.xxx.xxx"

# Non-https
server "example.com" {
        listen on $ext_ip port 80 # Listen on which ip on which port
        block return 301 "http://www.example.com$REQUEST_URI" # Redirect to another one
}

server "www.example.com" {
        listen on $ext_ip port 80
    location "/.well-known/acme-challenge/*" {
        root "/acme"
        request strip 2
    }
        root "/htdocs/www.example.com" # Specified folder to redirect to
}

With this, we are ready to get our certificates from let's encrypt.

lunatuna:~#: acme-client -v www.example.com

If you see the line with "created" for ".key" and ".pem" then it is done. Yeah!. Not finished yet, as you still need to adjust your httpd.conf to use your new certificate.

# my external ip
ext_ip = "xxx.xxx.xxx.xxx"

# LunarThale personal blog server
# Https with certificate by openbsd's ACME client
server "www.example.com" {
  listen on $ext_ip tls port 443
  root "/htdocs/www.example.com"
  tls {
    certificate "/etc/ssl/www.example.com.fullchain.pem"
    key "/etc/ssl/private/www.example.com.key"
  }
  location "/.well-known/acme-challenge/*" {
    root "/acme"
    request strip 2
  }
}

server "example.com" {
  listen on $ext_ip tls port 443
  tls {
    certificate "/etc/ssl/www.example.com.fullchain.pem"
    key "/etc/ssl/private/www.example.com.key"
  }
  block return 301 "https://www.example.com$REQUEST_URI"
}

# Non-https
server "example.com" {
        listen on $ext_ip port 80 # Listen on which ip on which port
        block return 301 "http://www.example.com$REQUEST_URI" # Redirect to another one
}

server "www.example.com" {
    listen on $ext_ip port 80
    location "/.well-known/acme-challenge/*" {
        root "/acme"
        request strip 2
    }
    root "/htdocs/www.example.com" # Specified folder to redirect to
}

restart "httpd" again to reload the config, and don't forget to check the config first for any alerts or error. ("httpd -n"). Now your site will have that tiny lock nears it. But, as the certificate can last for 3 months, so we need to renew it when it almost expires. "acme-client" will automatically renew if it has less than a month left. Therefore, we should add the command into crontab for automatic renewal.

OpenBSD provides a daily, weekly, and monthly maintenance script that runs respectively. So, add this command.

"acme-client -v www.example.com && rcctl restart httpd" to "/etc/weekly.local"

For weekly check for certificate expiration. Done!!..


For questions and comments, please send it to my public mailing list. Thank you.