Hosting OpenHTTPd

Goal

This is a guide for providing web hosting for multiple users. This setup will support multiple, custom domain names. Afterwards, we will use relayd to provide TLS encryption.

This guide assumes you have read the basic openhttpd configuration guide. This is a slightly more advanced setup.

Configuration

For each user we want to support, we must add two blocks to /etc/httpd.conf. Here's the first block:

server "example.com" {
        alias "www.example.com"
        listen on * port 80
        root "/htdocs/example.com/"
        location "/.well-known/acme-challenge/*" {
                root "/acme"
                request strip 2
        }
}

Line 1 says that this block is for the hostname "example.com". On other web servers, this might be known as the virtual host. Replace this with the domain that your user signed up for, such as username.fruit.ircnow.org. Your user can also custom request a domain. If your user has an alternative domain name he wishes to use, replace www.example.com with that name. For each extra domain name, add a new alias line. If he does not have an alternative name, you can delete the alias "www.example.com" line.

Line 3 tells the web server to listen on all IPs on port 80.

Line 4 tells us that the root directory for all web documents are in /var/www/htdocs/example.com/. A request to https://example.com/webpage.html would reply with the file in /var/www/htdocs/example.com/webpage.html.

Lines 5-8 (the location block) is used for requesting certificates using ACME. It says that for any request that begins with http://example.com/.well-known/acme-challenge/, look for the documents in the new root /acme. By default, openhttpd chroots to /var/www, so the document root is actually /var/www/acme/. The directive request strip 2 is needed so that openhttpd searches in /var/www/acme/ and not /var/www/acme/.well-known/acme-challenge/.

Note: You must have a server block listening on port 80. Do not delete this block or else acme-client will not work.

Note: Unlike in /etc/examples/httpd.conf, we will not automatically redirect to port 443. This is because some web browsers do not support TLS, and we do not want to break backwards compatibility.

Notice that we do not add any blocks with TLS. TLS will be provided by relayd.

Creating Web Files

Next, we'll create a directory for each web folder, and a symbolic link in each user's home folder that points to that web folder:

$ doas mkdir -p /var/www/htdocs/example.com/
$ doas ln -s /var/www/htdocs/example.com/ /home/username/htdocs
$ doas chown -R username:daemon /var/www/htdocs/example.com/

Make sure to replace username with the user's actual username, and example.com with his actual domain.

From now on, users will be able to create new web files by putting them in ~/htdocs/. For your test below, you may want to create the file /home/username/htdocs/index.html.

Start the Server and Test

Enable and restart the web server:

$ doas rcctl enable httpd
$ doas rcctl restart httpd

Testing Port 80

Let's test to see if the web server is working on port 80. This test should be run on some other computer besides your web server (your home PC or phone is fine). Let's use telnet:

$ telnet example.com 80
GET /index.html HTTP/1.1
Host: example.com

You should a response similar to the one below:

HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 34
Content-Type: text/html
Date: Sun, 28 Feb 2021 02:07:55 GMT
Last-Modified: Sat, 27 Feb 2021 10:22:27 GMT
Server: OpenBSD httpd

Troubleshooting

If you were unable to establish the connection above, it may be because your firewall is blocking port 80.

You can ensure pf allows incoming http connections by putting this line into /etc/pf.conf:

pass in quick proto tcp to port {http https}

Then, reload the pf rulesets:

$ doas pfctl -f /etc/pf.conf

Adding TLS

Next, you'll want to request an SSL cert using acme-client for each domain the user requested.

TLS Acceleration

Finally, you'll want to configure relayd for TLS acceleration.

Troubleshooting

To check for any configuration errors, run:

$ doas httpd -n

At any time, you can run openhttpd in debug mode:

$ doas httpd -dvv