// SPDX-FileCopyrightText: V <v@anomalous.eu>
// SPDX-License-Identifier: OSL-3.0

= cgiserver

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

It's lightweightfootnote:[I really do mean this: roughly 100 lines of liberally commented code, most of which is boilerplate] 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 https://github.com/gnosek/fcgiwrap[fcgiwrap] and https://man.openbsd.org/slowcgi.8[slowcgi]—both of which speak https://en.wikipedia.org/wiki/FastCGI[FastCGI]footnote:[an obsolete binary protocol specifically created to allow CGI applications to run as a single, persistent process]—cgiserver just uses HTTP and https://en.wikipedia.org/wiki/X-Forwarded-For[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 https://git.zx2c4.com/cgit/about/[CGit], you might write the following:

.cgit.service
[source,systemd]
----
[Unit]
Description=Lightweight Git web interface

[Service]
ExecStart=cgiserver /usr/lib/cgit/cgit.cgi
DynamicUser=true
----

.cgit.socket
[source,systemd]
----
[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 https://www.freedesktop.org/software/systemd/man/systemd.socket.html[`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 https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Environment=[`Environment=`] and https://www.freedesktop.org/software/systemd/man/systemd.exec.html#EnvironmentFile=[`EnvironmentFile=`] directives.
Running with the previous example: if you want to change CGit's config location from the default,footnote:[`/etc/cgitrc`, in case you were wondering] you could add the following:

.cgit.service
[source,systemd]
----
[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 footprintfootnote:[roughly 4.5MiB per instance when I last checked, although I never seriously benchmarked it] and all mainstream web servers have templating functionality.
In https://caddyserver.com/[Caddy], you could do the following:

[source,Caddyfile]
reverse_proxy /cgi-bin/* //unix/run/cgi/{file}.sock

== License

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