Hiawatha in front of a Hilde service

What Hiawatha is, and why it is ours

Hiawatha is an open source web server by Hugo Leisink, built for security, ease of use and a small footprint. It speaks FastCGI, TLS and HTTP/2, rewrites URLs, proxies, and blocks SQL injection, XSS, CSRF and exploit attempts by itself; it runs on Linux, the BSDs and macOS. Its manual is hiawatha(1), on the website and in its source.

Hiawatha is the preferred web server for everything built in Hilde. Heiko Zimmermann, who makes Hilde, has run Hiawatha since 2010 and is a contributor to it by now. A Hilde programme does not listen on the network itself: it serves FastCGI on a Unix socket, and Hiawatha takes the connections, holds TLS, serves the static files and hands every other request to the socket. The services built in Hilde run that way.

How it fits together:

browser --TLS--> Hiawatha (:443) --FastCGI over a Unix socket--> the Hilde programme

What this page covers

The settings of Hiawatha a Hilde service needs, each with the reason and where it comes from. The examples are those of an OpenID provider written in Hilde, its host auth.example.org. Standard.Doctor's init prints the FastCGIserver and UrlToolkit blocks for a service with a socket.

Hiawatha's configuration is read at start only: there is no reload. After a change, check it with hiawatha -k, then restart Hiawatha (rcctl restart hiawatha on OpenBSD, systemctl restart hiawatha on Linux).

Global settings (hiawatha.conf, outside every VirtualHost)

SettingValueWhy
MaxUrlLength8192An ID token of ML-DSA-44 travels in the query of a logout (id_token_hint). Hiawatha's default is 1000, and it answers a longer URL with 414 before the service sees it. On a test instance: ID token 3688 bytes, logout URL 3710, refused with 414 under the default, answered with 8192. The setting is one of the whole server; a VirtualHost cannot set it (hiawatha(1)).

The FastCGI server and the toolkit

FastCGIserver {
    FastCGIid = Auth
    ConnectTo = /var/run/auth/auth.sock
}

UrlToolkit {
    ToolkitId = auth
    Match ^/static/[A-Za-z0-9._-]+$ Exit
    Match ^/favicon\.ico$ Exit
    Match .* UseFastCGI Auth
}

The virtual host

VirtualHost {
    Hostname = auth.example.org
    WebsiteRoot = /usr/local/share/auth/www
    UseToolkit = auth
    RequireTLS = yes, 31536000; includeSubDomains
    TLScertFile = tls/auth.example.org.pem
    BanByCGI = yes, 3600
    HTTPAuthToCGI = yes
    CustomHeaderClient = X-Content-Type-Options: nosniff
    CustomHeaderClient = Referrer-Policy: no-referrer
    CustomHeaderClient = X-Frame-Options: DENY
}
SettingWhy
HTTPAuthToCGI = yesHiawatha passes the Authorization header to FastCGI only with it; a client of an OpenID provider authenticates at /token with client_secret_basic in that header.
BanByCGI = yes, <seconds>The service may have Hiawatha ban an address after repeated failed sign-ins; the seconds are the most a ban may last, so the service's own ban time stays at or under them.
RequireTLS, TLScertFileThe service sets Secure and __Host- cookies, which a browser keeps over TLS only.
CustomHeaderClientFor the static files Hiawatha serves itself; the service sets the same headers on its own pages.

Hiawatha's confinement

For a load measurement only

A measurement of a service behind Hiawatha sets ThreadPoolSize = 50, ListenBacklog = 128, ConnectionsPerIP and ConnectionsTotal = 1000, MaxKeepAlive = 1000 on the binding and SetResourceLimits = no, so that Hiawatha's limits are not what is measured. They are not settings for production.