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 - IRI support (RFC3987)
20 - punycode support
21 - dual stack (IPv4 and IPv6)
22 - automatic certificate generation for config-less mode
23 - CGI scripts
24 - (very) low memory footprint
25 - small codebase, easily hackable
26 - virtual hosts
27 - per-location rules
28 - optional directory listings
29 - configurable mime types
30 - sandboxed by default on OpenBSD, Linux and FreeBSD
31 - chroot support
34 ## Drawbacks
36 - not suited for very busy hosts. If you receive an high number of
37 connection per-second you'd probably want to run multiple gmid
38 instances behind relayd/haproxy or a different server.
41 ## Internationalisation (IRIs, UNICODE, punycode, all that stuff)
43 Even thought the current Gemini specification doesn't mention anything
44 in this regard, I do think these are important things and so I tried
45 to implement them in the most user-friendly way I could think of.
47 For starters, gmid has full support for IRI (RFC3987 —
48 Internationalized Resource Identifiers). IRIs are a superset of URIs,
49 so there aren't incompatibilities with URI-only clients.
51 There is full support also for punycode. In theory, the user doesn't
52 even need to know that punycode is a thing. The hostname in the
53 configuration file can (and must be) in the decoded form (e.g. `naïve`
54 and not `xn--nave-6pa`), gmid will do the rest.
56 The only missing piece is UNICODE normalisation of the IRI path: gmid
57 doesn't do that (yet).
60 ## Building
62 gmid depends on a POSIX libc, OpenSSL/LibreSSL and libtls (provided
63 either by LibreSSL or libretls). At build time, flex and yacc (or GNU
64 bison) are also needed.
66 The build is as simple as
68 ./configure
69 make
71 If the configure scripts fails to pick up something, please open an
72 issue or notify me via email.
74 To install execute:
76 make install
78 ### Docker
80 If you have trouble installing LibreSSL or libretls, you can use
81 Docker to build a `gmid` image with:
83 docker build -t gmid .
85 and then run it with something along the lines of
87 docker run --rm -it -p 1965:1965 \
88 -v /path/to/gmid.conf:...:ro \
89 -v /path/to/docs:/var/gemini \
90 gmid -c .../gmid.conf
92 (ellipses used for brevity)
94 ### Local libretls
96 This is **NOT** recommended, please try to port LibreSSL/LibreTLS to
97 your distribution of choice or use docker instead.
99 However, it's possible to statically-link `gmid` to locally-installed
100 libretls quite easily. (It's how I test gmid on Fedora, for instance)
102 Let's say you have compiled and installed libretls in `$LIBRETLS`,
103 then you can build `gmid` with
105 ./configure CFLAGS="-I$LIBRETLS/include" \
106 LDFLAGS="$LIBRETLS/lib/libtls.a -lssl -lcrypto -lpthread"
107 make
109 ### Testing
111 Execute
113 make regress
115 to start the suite. Keep in mind that the regression tests will
116 create files inside the `regress` directory and bind the 10965 port.
119 ## Architecture/Security considerations
121 gmid is composed by two processes: a listener and an executor. The
122 listener process is the only one that needs internet access and is
123 sandboxed. When a CGI script needs to be executed, the executor
124 (outside of the sandbox) sets up a pipe and gives one end to the
125 listener, while the other is bound to the CGI script standard output.
126 This way, is still possible to execute CGI scripts without
127 restrictions even in the presence of a sandboxed network process.
129 On OpenBSD, the listener runs with the `stdio recvfd rpath inet`
130 pledges, while the executor has `stdio sendfd proc exec`; both have
131 unveiled only the served directories.
133 On FreeBSD, the executor process is sandboxed with `capsicum(4)`.
135 On Linux, a `seccomp(2)` filter is installed in the listener to allow
136 only certain syscalls, see [sandbox.c](sandbox.c) for more information
137 on the BPF program.
139 In any case, you are invited to run gmid inside some sort of
140 container/jail/chroot.