Blob


1 # gmid
3 gmid is a Gemini server written with security in mind. I initially
4 wrote it to serve static files, but it has grown into a featureful
5 server that can be used from either the command line to serve local
6 directories
8 gmid docs # serve the directory docs over gemini
10 or as a traditional daemon
12 gmid -c /etc/gmid.conf
15 ## Features
17 (random order)
19 - reconfiguration: reload the running configuration without interruption
20 - sandboxed by default on OpenBSD, Linux and FreeBSD
21 - IRI support (RFC3987)
22 - punycode support
23 - dual stack (IPv4 and IPv6)
24 - automatic certificate generation for config-less mode
25 - CGI scripts
26 - (very) low memory footprint
27 - small codebase, easily hackable
28 - virtual hosts
29 - per-location rules
30 - optional directory listings
31 - configurable mime types
32 - chroot support
35 ## Drawbacks
37 - not suited for very busy hosts. If you receive an high number of
38 connection per-second you'd probably want to run multiple gmid
39 instances behind relayd/haproxy or a different server.
42 ## Internationalisation (IRIs, UNICODE, punycode, all that stuff)
44 Even thought the current Gemini specification doesn't mention anything
45 in this regard, I do think these are important things and so I tried
46 to implement them in the most user-friendly way I could think of.
48 For starters, gmid has full support for IRI (RFC3987 —
49 Internationalized Resource Identifiers). IRIs are a superset of URIs,
50 so there aren't incompatibilities with URI-only clients.
52 There is full support also for punycode. In theory, the user doesn't
53 even need to know that punycode is a thing. The hostname in the
54 configuration file can (and must be) in the decoded form (e.g. `naïve`
55 and not `xn--nave-6pa`), gmid will do the rest.
57 The only missing piece is UNICODE normalisation of the IRI path: gmid
58 doesn't do that (yet).
61 ## Configuration
63 gmid has a rich configuration file, heavily inspired by OpenBSD'
64 httpd. While you should definitely check the manpage because it
65 documents every option in depth, here's an example of what gmid can
66 do.
68 ```conf
69 ipv6 on # enable ipv6
71 server "example.com" {
72 cert "/path/to/cert.pem"
73 key "/path/to/key.pem"
74 root "/var/gemini/example.com"
75 lang "it"
76 cgi "/cgi/*"
78 location "/files/*" {
79 auto index on
80 }
82 location "/repo/*" {
83 # change the index file name
84 index "README.gmi"
85 }
87 # redirect /cgi/man/... to man.example.com/...
88 location "/cgi/man*" {
89 strip 2
90 block return 31 "gemini://man.example.com%p"
91 }
92 }
94 server "man.example.com" {
95 cert "..."
96 key "..."
97 root "/var/gemini/man.example.com"
99 # handle every request with the CGI script `man'
100 entrypoint "man"
102 ```
105 ## Building
107 gmid depends on a POSIX libc, OpenSSL/LibreSSL and libtls (provided
108 either by LibreSSL or libretls). At build time, flex and yacc (or GNU
109 bison) are also needed.
111 The build is as simple as
113 ./configure
114 make
116 If the configure scripts fails to pick up something, please open an
117 issue or notify me via email.
119 To install execute:
121 make install
123 ### Docker
125 If you have trouble installing LibreSSL or libretls, you can use
126 Docker to build a `gmid` image with:
128 docker build -t gmid .
130 and then run it with something along the lines of
132 docker run --rm -it -p 1965:1965 \
133 -v /path/to/gmid.conf:...:ro \
134 -v /path/to/docs:/var/gemini \
135 gmid -c .../gmid.conf
137 (ellipses used for brevity)
139 ### Local libretls
141 This is **NOT** recommended, please try to port LibreSSL/LibreTLS to
142 your distribution of choice or use docker instead.
144 However, it's possible to statically-link `gmid` to locally-installed
145 libretls quite easily. (It's how I test gmid on Fedora, for instance)
147 Let's say you have compiled and installed libretls in `$LIBRETLS`,
148 then you can build `gmid` with
150 ./configure CFLAGS="-I$LIBRETLS/include" \
151 LDFLAGS="$LIBRETLS/lib/libtls.a -lssl -lcrypto -lpthread"
152 make
154 ### Testing
156 Execute
158 make regress
160 to start the suite. Keep in mind that the regression tests will
161 create files inside the `regress` directory and bind the 10965 port.
164 ## Architecture/Security considerations
166 gmid is composed by two processes: a listener and an executor. The
167 listener process is the only one that needs internet access and is
168 sandboxed. When a CGI script needs to be executed, the executor
169 (outside of the sandbox) sets up a pipe and gives one end to the
170 listener, while the other is bound to the CGI script standard output.
171 This way, is still possible to execute CGI scripts without
172 restrictions even in the presence of a sandboxed network process.
174 On OpenBSD, the listener runs with the `stdio recvfd rpath inet`
175 pledges, while the executor has `stdio sendfd proc exec`; both have
176 unveiled only the served directories.
178 On FreeBSD, the executor process is sandboxed with `capsicum(4)`.
180 On Linux, a `seccomp(2)` filter is installed in the listener to allow
181 only certain syscalls, see [sandbox.c](sandbox.c) for more information
182 on the BPF program.
184 In any case, you are invited to run gmid inside some sort of
185 container/jail/chroot.