Installing rc-httpd on OpenBSD
Last updated: 2016-12-21T21:13:57-0500
Rc-httpd is a shell script that serves the requested file or an index of files found under a website's root directory, or, in the case of CGI, executes a specified CGI program. Compact, simple, works. It was written on OS X (of all things) but works fine on any system that can execute the rc shell. For example, rc-httpd now ships with the 9front fork of Plan 9 from Bell Labs. In fact, it serves the 9front.org and cat-v.org websites, as well as the page you are reading right now.
How this setup will work
Daemontools will run as root and ensure that the network listener listen1(8) continuously answers network queries on port 80. The listener will then run the setuidgid program from daemontools to become user _rc-httpd and pass the open file descriptors along to the shell script tcp80, which in turn will execute rc-httpd (and in our case, execute werc) which will display a simple website.
Optionally, the ucspi-tools tlss(1) program can be used in a pipeline to negotiate TLS connections, passing along its file descriptors to the shell script tcp443, which in turn will execute rc-httpd (and in our case, werc). If you don't need to serve TLS, the related steps can be safely omitted.
Note: Throughout this document, you will need to change all references to domain.com to the hostname of your site. You will also need to change all references to user to the correct username on your system.
Note: Many UNIX systems package a stand alone clone of rc written by Byron Rakitzis. It was originally created based on the rc paper by Tom Duff, and includes several incompatible changes to its syntax. Byron's rc is incompatible with rc-httpd and werc.
Begin by installing a compatible rc:
pkg_add plan9port # or your choice of p9p forks cp /usr/local/plan9/bin/rc /bin/ # to simplify bang paths cp /usr/local/plan9/bin/awk /bin/ # ""
rc-httpd comes with werc
Werc is a minimalist web anti-framework built following the Unix and Plan 9 tool philosophy of software design. It is likewise a shell script. Rc-httpd is included with werc as a proof-of-concept web server.
It is wise to install werc (and therefore, rc-httpd) as a non-root user:
# as user mkdir $HOME/www cd $HOME/www hg clone https://code.9front.org/hg/werc
But we'll still run rc-httpd from a dedicated user account:
groupadd _rc-httpd useradd -g _rc-httpd -d /home/user/www/werc/bin/contrib/rc-httpd _rc-httpd
The rc-httpd shell script can be launched and managed with daemontools:
cd /root/src wget http://openbsd.stanleylieber.com/src/daemontools-0.76.tar.gz tar zxvf daemontools-0.76.tar.gz cd admin/ wget http://openbsd.stanleylieber.com/src/daemontools-0.76.errno.patch cd daemontools-0.76 patch -p1 <../daemontools-0.76.errno.patch package/install mkdir -p /supervise/rc-httpd >/supervise/rc-httpd/run chmod 775 /supervise/rc-httpd/run ed /supervise/rc-httpd/run i #!/bin/sh exec /usr/local/plan9/bin/listen1 tcp!domain.com!80 \ /usr/local/bin/setuidgid _rc-httpd \ /home/user/www/werc/bin/contrib/tcp80 . w q # for TLS mkdir -p /supervise/rc-httpd-tls >/supervise/rc-httpd-tls/run chmod 775 /supervise/rc-httpd-tls/run ed /supervise/rc-httpd-tls/run i #!/bin/sh exec /usr/local/plan9/bin/listen1 tcp!domain.com!443 \ /usr/local/bin/setuidgid _rc-httpd \ /home/user/www/werc/bin/contrib/tcp443 . w q
We'll hold off on enabling the service until rc-httpd and werc are configured.
Create a log file
This can go wherever you like (or you can omit logging entirely), but for the sake of this example:
>/var/log/rc-httpd chgrp _rc-httpd /var/log/rc-httpd chmod g+w /var/log/rc-httpd
Edit the tcp80 script
The tcp80 script that ships with werc lists a default path to rc-httpd that probably doesn't exist on your system. Change your copy of tcp80 to point to the correct location:
The ucspi-tools tlss(1) program can be used to handle TLS for incoming TCP connections. After the TLS connection is established, tlss will spawn rc-httpd.
pkg_add ucspi-tools openssl genrsa -out /etc/ssl/rc-httpd.server.key 2048 openssl req -new -key /etc/ssl/rc-httpd.server.key \ -out /etc/ssl/rc-httpd.server.csr openssl x509 -sha256 -req -days 365 \ -in /etc/ssl/rc-httpd.server.csr \ -signkey /etc/ssl/rc-httpd.server.key \ -out /etc/ssl/rc-httpd.server.crt chown root:_rc-httpd /etc/ssl/rc-httpd.server.csr /etc/ssl/rc-httpd.server.key chmod 640 /etc/ssl/rc-httpd.server.csr /etc/ssl/rc-httpd.server.key
Create the tcp443 script
The tcp443 script is a counterpart to tcp80 that handles incoming TLS connections:
>/home/user/www/werc/bin/contrib/tcp443 chmod 775 /home/user/www/werc/bin/contrib/tcp443 ed /home/user/www/werc/bin/contrib/tcp443 i #!/bin/rc exec tlss \ -c /etc/ssl/rc-httpd.server.crt \ -k /etc/ssl/rc-httpd.server.key \ /home/user/www/werc/bin/contrib/rc-httpd/rc-httpd \ >>/var/log/rc-httpd . w q
Optional: Edit select-handler
The rc-httpd script needs to know what do with incoming requests. The default configuration hands any incoming requests to werc, which looks in werc/sites/$SERVER_NAME for a corresponding directory. The default configuration is sufficient for our example setup, but if a more granular approach is desired it may be customized thusly:
Several examples of different select-handler configurations are documented in the 9front source: /rc/bin/rc-httpd/select-handler
A simple werc site
mkdir /home/user/www/werc/sites/domain.com echo hello world >/home/user/www/werc/sites/domain.com/index.md
For more information about customizing werc see the werc website.
Finally, turn on the service:
ln -s /supervise/rc-httpd /service ln -s /supervise/rc-httpd-tls /service
Make use of the usual daemontools features to examine service state, etc.