1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
// 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.
|