about summary refs log tree commit diff

cgiserver

…​is a really simple web server for CGI applications.

It’s lightweight[1] and modern, relying on systemd for socket management and an execution environment. Each instance of cgiserver is responsible for a single application, which makes privilege separation straightforward and allows for fine-grained sandboxing. Unlike similar programs such as fcgiwrap and slowcgi—both of which speak FastCGI[2]—cgiserver just uses HTTP and standard proxy headers. Instead of handling routing logic itself, cgiserver leaves that and other such intricacies to your regular web server.

Basic usage

At minimum, cgiserver requires two things: a listening socket, and a CGI application. To run CGit, you might write the following:

cgit.service
[Unit]
Description=Lightweight Git web interface

[Service]
ExecStart=cgiserver /usr/lib/cgit/cgit.cgi
DynamicUser=true
cgit.socket
[Socket]
ListenStream=/run/cgit/cgit.sock

[Install]
WantedBy=sockets.target

You will then need to configure your web server to reverse proxy requests to /run/cgit/cgit.sock. Naturally, systemd also allows you to listen on TCP ports, but UNIX sockets are preferable as you can limit access to a specific user or group using filesystem permissions. For more information on socket configuration, see systemd.socket(5).

Warning
Do not expose cgiserver directly to the Internet! It respects proxy headers, which could make your application vulnerable if it uses the originating address for anything important. Only deploy it behind a web server that understands, filters, and sets these headers itself.

Environment

The CGI application inherits cgiserver’s environment, allowing for simple configuration via systemd’s Environment= and EnvironmentFile= directives. Running with the previous example: if you want to change CGit’s config location from the default,[3] you could add the following:

cgit.service
[Service]
Environment=CGIT_CONFIG=/etc/cgit/config

Multiple CGI applications

If you have multiple CGI applications, you will need to run a separate instance of cgiserver for each of them. This isn’t a huge issue, as cgiserver has a fairly low memory footprint[4] and all mainstream web servers have templating functionality. In Caddy, you could do the following:

reverse_proxy /cgi-bin/* //unix/run/cgi/{file}.sock

License

cgiserver is licensed under the Open Software License, version 3.0.


1. I really do mean this: roughly 100 lines of liberally commented code, most of which is boilerplate
2. an obsolete binary protocol specifically created to allow CGI applications to run as a single, persistent process
3. /etc/cgitrc, in case you were wondering
4. roughly 4.5MiB per instance when I last checked, although I never seriously benchmarked it