futility(1) An idiot admires complexity

Werc is described as a 'Sane web anti-framework' written in rc by our 9friends. I don't live on plan9, but it's very refreshing to see that the minimal web lives on .

What is werc?

See werc. SSL not included.

Quoting directly from the website:

Werc is a minimalist web anti-framework built following the Unix and Plan 9 tool philosophy of software design.

Werc avoids the pain of managing collections of websites and developing web applications.

Why use werc?

werc is simple but extensible. Files can be written in HTML, md, or even plaintext. werc is editor agnostic, uses no database, supports multiple 'vhosts' out of the box, has a simple user system, etc. It's the simplest site generator I've ever touched, especially because rsync is not an unlisted but implied dependency.

The best part - all you need is a UNIX-like OS with a httpd that supports GCI and Plan9 utilities.

Mandatory Apache Setup

I'm dumping werc onto my existing FreeBSD webserver. My setup is . . . overly complicated . . . but I already run multiple subdomains on the same server so adding another one for werc should be very simple.


First, I installed plan9port

$ pkg install plan9port

Apache part 1

Then, I modified /usr/local/etc/apache24/httpd.conf to enable CGI. Check if mpmpreforkmodule is enabled in your conf, then uncomment the corresponding line. I don't have mpmpreforkmodule enabled so mine looks something like this:

#. . . 
<IfModule !mpm_prefork_module>
LoadModule cgid_module libexec/apache24/mod_cgid.so
<IfModule mpm_prefork_module>
#LoadModule cgi_module libexec/apache24/mod_cgi.so
#. . . 

The next part is tricky. I needed to add a vhost without ssl rewrites, get certs with acme.sh, then add the re-writes that force all traffic to use SSL. In /usr/local/etc/apache24/extra/httpd-vhosts.conf.

<VirtualHost *:80>
DocumentRoot "/usr/local/www/apache24/data/werc.0x19.org"
ServerName werc.0x19.org

SSL certs

I have a script that issues certs with acme.sh. You should write something similar. Every time I add a subdomain, I just add a -d flag to my list of domains, run the script, then modify my crontab to automatically renew the new domain. Once my certs installed successfully, I added rewrite rules.

Apache part 2

Once again, I opened /usr/local/etc/apache24/extra/httpd-vhosts.conf, this time to add SSL rewrites. Now, the vhost block looks like this:

<VirtualHost *:80>
DocumentRoot "/usr/local/www/apache24/data/werc.0x19.org"
ServerName werc.0x19.org
RewriteEngine on
RewriteCond %{SERVER_NAME} =werc.0x19.org
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

I needed to add a corresponding vhost that uses SSL and has all the configs for werc. Since werc supports user login, I want to prevent werc from ever running without SSL. That block begins like this:

<VirtualHost *:443>
ServerName werc.0x19.org:443
DocumentRoot "/usr/local/www/apache24/data/werc.0x19.org"
ErrorLog "/var/log/httpd-error.log"
TransferLog "/var/log/httpd-access.log"
RewriteEngine on
SSLEngine on
SSLCertificateFile "/usr/local/etc/apache24/ssl/cert.pem"
SSLCertificateKeyFile "/usr/local/etc/apache24/ssl/key.pem"
SSLCertificateChainFile "/usr/local/etc/apache24/ssl/fullchain.pem"
# . . . end of boilerplate, werc configs below

More boilerplate

I downloaded werc, extracted the tarball to my cgi directory, then modified the vhost config so it knows what it's doing.

$ cd 
$ fetch http://werc.cat-v.org/download/werc-1.5.0.tar.gz
$ tar czfv ./werc-1.5.0.tar.gz
$ cp -r ./werc-1.5.0 /usr/local/www/apache24/cgi-bin/werc

Very intentionally, I added werc configs to my vhost that supports SSL. Since werc has user login functionality, I wanted to force all users to connect with SSL to prevent accidental login leakage.

Pay very close attention to your vhost config. This one is specific to my server, not yours.

# . . . beginning of werc configs, boilerplate above
# tell cgi to run .rc scripts
AddHandler cgi-script .rc
AddHandler cgi-script .cgi
<Directory /usr/local/www/apache24/cgi-bin/werc/bin>
Options ExecCGI
AllowOverride None
Order allow,deny
Allow from all
# this is for sitemap.{txt,gz}
<Directory /usr/local/www/apache24/cgi-bin/werc/sites>
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
<IfModule mod_dir.c>
DirectoryIndex /werc.rc
#RewriteRule (.*) /usr/local/www/apache24/cgi-bin/werc/sites/%{SERVER_NAME}/$1
RewriteRule (.*) /usr/local/www/apache24/cgi-bin/werc/sites/werc.0x19.org/$1
RewriteRule /pub/style/style.css /usr/local/www/apache24/cgi-bin/werc/pub/style/style.css
RewriteRule /favicon.ico /usr/local/www/apache24/cgi-bin/werc/pub/favicon.ico
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /usr/local/www/apache24/cgi-bin/werc/bin/werc.rc
RewriteRule /werc.rc /usr/local/www/apache24/cgi-bin/werc/bin/werc.rc
DocumentRoot /usr/local/www/apache24/cgi-bin/werc/bin/
ErrorDocument 404 /werc.rc

Then finally, I restarted apache

$ service apache24 restart

Mandatory werc Configuration

Since I am running my webserver on Freebsd instead of 9, minor configuration tweaks are required. plan9port installs to /usr/local/plan9 but werc expects to be running natively on 9. The fix is easy. The first file I modified was /usr/local/www/apache24/cgi-bin/werc/werc.rc and changed the shebang to


After this, I copied the directory for the default site to my own site. If you look back up at the vhost config, we explicitly specified a directory for werc to serve.

$ cp -r sites/tst.cat-v.org sites/werc.0x19.org

Hey cool! It worked . . . almost.

"Why the hell won't this werc"?

I added a few markdown files, modified the headers and footers, changed the site metadata, name, etc. But there was one problem: werc was unable to convert my markdown files to html and was failing.

Like a good sysadmin I checked apache error logs only to see the following message that haunted me until approximately 45 minutes ago when I began writing this post:

 md2html.awk: No such file or directory 

At this point, it was already 4 in the morning. Instead of staying up later, I decided to sleep on it and allow the message to haunt me throughout the day. It wasn't until I realized that there was more breakage because FreeBSD != 9.

Turns out that FreeBSD awk is not in /bin/awk, but in /usr/bin/awk. At 4 in the morning, my instinctual Linux reactions begin to take control and I forget that awk is not required for core FreeBSD operations. It also turns out that plan9 binaries won't run on FreeBSD. To fix this, I did three things.

1. Modify werc/etc/initrc

# default line, commented because shit broke
#formatter=(fltr_cache md2html.awk) # no perl for old men
# new line, 9 bytecode != freebsd bytecode

2. Move md2html.awk into the path I explicitly stated in werc.rc

$ cp werc/bin/contrib/md2html.awk /usr/local/plan9/bin

3. Correct the shebang in md2html.awk so that it will actually run






I have not yet played with all of the apps, but they seem very promising. So far, I have only tried the comments (they work) and diri (it works but I'm not letting apache write files to my cgi dir). If I had known about werc, I likely would have just used it instead of the bootstrap+jekyll+php mess I have created. The simple design and easy customizability is very appealing to me and the 'plugin' 'infrastructure' seems promising since it's language agnostic.

Overall, I am ready for a refreshing web experience. Simplicity and 'anti-over-styling' has become more and more appealing to me lately. If you look closely at the design of 0x19.org, it's almost like I wanted something this simple all along