Hiawatha

Hiawatha
is an open source
web server
with security, ease of use and lightweight as its three key features. It supports among others
CGI
,
FastCGI
, IPv6, URL rewriting and reverse proxy and has security features no other webserver has, like blocking
SQL injections
,
XSS
,
CSRF
and exploit attempts.
Note
Hiawatha is no longer actively developed: its creator announced in February 2019 he was
scaling down the project
started in 2002.
Installation
Install
the
hiawatha
AUR
package.
Configuration
Directory structure
First, to give an overview of the overall directory structure of Hiawatha, the hierarchy suggested by the default configuration is shown below:
/etc/hiawatha/
- program configuration files
/etc/hiawatha/tls/
- website TLS certificate
/srv/http/hiawatha/
- root for the default blank website associated with the IP address
/var/lib/hiawatha/
- cache for http compression and uploads
/var/log/hiawatha/
- log files for the program and the default website
/srv/http/
my-domain
/public/
- website root
/srv/http/
my-domain
/log/
- website log files
Basic webserver setup
The Hiawatha configuration file is
/etc/hiawatha/hiawatha.conf
. A configuration file example
/etc/hiawatha/hiawatha.conf.sample
is provided.
In the sample setup, there is one default website attached to the IP address of the domain, it is a dummy one directing to a blank html page. This is the page IP scanning robots and hackers will face.
Then, the working webservers are defined with
VirtualHost
sections. Hiawatha can serve more than one webserver and each of these sections describes a different one. For initial testing purpose, you can create one
VirtualHost
for
my-domain
and save in its root directory
/srv/http/
my-domain
/public
a dummy
index.html
start file.
Next,
enable
and
start
hiawatha.service
and point your browser to
http://
my-domain
. At that stage you should be able to load the website start page.
For further details, see the official
how to
and the
hiawatha(1)
manual page.
Note
Hiawatha supports on-the-fly
gzip content encoding
. It will gzip the requested file and cache it on disk in
/var/lib/hiawatha/gzipped/
. Every time the file is requested again, the already gzipped version from disk will be used. It will notice (timestamp and size) file changes and the cache is cleared upon restart.
CGI
Common Gateway Interface
(
CGI
) scripts work with Hiawatha out of the box, the CGI module in the
VirtualHost
section just needs to be enabled as follows:
/etc/hiawatha/hiawatha.conf
VirtualHost {
    ...
    ExecuteCGI = yes
}
Interpreters for CGI scripts
To use CGI scripts in your website, you have to specify the common script file extension and the location of the binary that can run them. This is indicated in the main body of the configuration file:
CGIhandler = /usr/bin/php-cgi:php
CGIhandler = /usr/bin/perl:pl
CGIhandler = /usr/bin/python:py
Note
The corresponding language interpreters should be installed: for
php
both
php
and
php-cgi
are needed, for
python
python
is required.
For further details see the official
HowTo
.
FastCGI
Install
fcgi
.
Hiawatha supports two different methods to send information to the FastCGI process: the webserver can communicate over either a
Unix domain socket
or a
TCP connection
. The communication type is defined in the
FastCGIServer
section via the field
ConnectTo
.
Enable SSL/TLS
First, a
X.509 SSL/TLS
certificate is required to use TLS. If you do not have one, you can use a
#Self-signed certificate
or use one for free from
#Let's Encrypt certificate
authority.
The order of the items in the certificate file must be as follows:
serverkey.pem
-----BEGIN RSA PRIVATE KEY-----
[webserver private key]
-----END RSA PRIVATE KEY----- 

-----BEGIN CERTIFICATE-----
[webserver certificate]
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
[optional intermediate CA certificate]
-----END CERTIFICATE-----
For SSL/TLS support, the following
Binding
section that configures Hiawatha to use a certificate for HTTPS connections should be added:
/etc/hiawatha/hiawatha.conf
Binding {
    Port = 443
    TLScertFile = /etc/hiawatha/tls/serverkey.pem
}
Once it is done,
restart
hiawatha.service
.
Tip
Hiawatha supports
Server Name Indication
, which allows to serve multiple certificates on the same IP address and hence multiple secure websites. To use this functionality, add a
TLScertFile
setting inside the
VirtualHost
block for each virtual host that has its own SSL/TLS certificate. The certificate specified in the
Binding
section is used whenever no virtual host has been defined for a website.
/etc/hiawatha/hiawatha.conf
VirtualHost {
    Hostname = www.website.org
    ...
    TLScertFile = website.pem
}
Reverse proxy
Hiawatha's man pages suggest using the following:
ReverseProxy [!]<pattern> [<skip directories>] http[s]://<hostname>[:<port>][/<path>] [<timeout>] [keep-alive]
<timeout>
is the time in seconds Hiawatha tries to connect to the other webservice. Adding
keep-alive
enables keep-alive connections to the final webserver.
As an example, a webservice reverse proxy configuration which forwards requests from
https://service.domain.net
to another local running web service on port
8181
looks like (timout 10s):
/etc/hiawatha/hiawatha.conf
VirtualHost {
        Hostname = service.domain.net
        WebsiteRoot = /var/www/domain
        StartFile = index.html
        ReverseProxy .* http://127.0.0.1:8181/ 10
        RequireTLS = yes
}
If a UNIX socket is needed instead:
ReverseProxy .* /unix/socket 10
Certificates
Self-signed certificate
To get a local self-signed certificate for personal use, testing or web development, the procedure in
OpenSSL#Generate a self-signed certificate
to create both a private key and a self-signed certificate can be followed.
Make sure you did add the SSL bundle path to your
hiawatha.conf
as stated in
#Enable SSL/TLS
.
As this solution does not use an official certificate authority (CA), a security exception will need to be added the first time the website is visited.
Let's Encrypt certificate
Configure
Hiawatha provides a script to obtain a
Let’s Encrypt
certificate in an automated fashion using the
ACME
v2 protocol.
A configuration file example
letsencrypt.conf
is provided in the directory
/usr/lib/hiawatha/letsencrypt
. Two steps are needed to setup
lefh
:
Copy the sample configuration file to the user's area
~/.letsencrypt/
, typically
/root/.letsencrypt/
if hiawatha is run as a system service.
Edit the settings, in particular replace the value of
ACCOUNT_EMAIL_ADDRESS
by the chosen email address,
lefh
will not run with the initial example email address.
Obtain a certificate
The detailed instructions are described in
lefh(1)
and the tool's configuration is defined in
letsencrypt.conf
. In short, there are two steps to get a certificate:
Register an account with the Let's Encrypt certificate authority (CA). An account key file will be created.
# lefh register
Request a website certificate:
www.my-domain.org
must be the first hostname of a
VirtualHost
. Any following webserver's hostname will be used as an alternative hostname for the certificate. Note that wildcards can not be used in the hostname: even if Let's Encrypt accept this functionality, it can only be obtained via DNS challenge and this method is not supported by lefh.
The file
www.my-domain.org
.pem
will be created.
# lefh request
www.my-domain.org
If the above succeeds, you can switch from the
testing
to the
production
CA by changing the
LE_CA_HOSTNAME
setting in the configuration file and go through the
two steps
above again. Do not rush into production before making sure the test was successful: letsencrypt enforces rate limit for failed attempts and one may get temporarily banned.
Note
Let's Encrypt CA requests a file via HTTP during the challenge operation. This file must be accessible in a location like
http://
www.my-domain.org
/.well-known/acme-challenge/
Cl887Wpvc297mfkdNZRuAl48h_FTLnA_ZbhJo3FdExY
. Therefore your website must be reachable via HTTP: the external port
80
must be forwarded to your server and a binding to port
80
must be configured in hiawatha so that Let's Encrypt CA can fetch the challenge.
Auto renewal
The following command can be used to renew the certificate and restart the server upon renewal:
# lefh renew restart
By default, the certificate will be renewed whenever it has less than 7 days to go and it will be written in the directory indicated in
HIAWATHA_CERT_DIR
. The number of days before renewal can be controlled via the
RENEWAL_EXPIRE_THRESHOLD
setting.
A daily schedule of this script is appropriate as no action will be taken anyway before the threshold is reached.
This daily automation can be achieved using either
cron
or
systemd/Timers
:
Automation with cron
In order to automate the renewal of the certificate, schedule a cronjob for the root user to run the command line above.
Automation with a systemd timer
A
systemd timer
can be used for the repetition of the renewal process:
/etc/systemd/system/lefh-renew.service
[Unit]
Description=Renew Let's Encrypt certificates for Hiawatha
Wants=network-online.target
After=network-online.target

[Service]
User=root
WorkingDirectory=/tmp
Type=oneshot
ExecStart=/usr/bin/lefh renew restart
/etc/systemd/system/lefh-renew.timer
[Unit]
Description=Daily renewal of Let's Encrypt's certificates for Hiawatha

[Timer]
OnCalendar=daily
# Be kind to the Let's Encrypt servers: add a random delay of 12 hours
RandomizedDelaySec=12h
Persistent=true

[Install]
WantedBy=timers.target
Start
and
enable
lefh-renew.timer
.
Note
The service waits for the network to be up and online, for more information on the implementation of the network dependency, see
systemd#Running services after the network is up
.
See also
Hiawatha Support page
Hiawatha on GitLab