Blob


1 .\" Copyright (c) 2020 Omar Polo <op@omarpolo.com>
2 .\"
3 .\" Permission to use, copy, modify, and distribute this software for any
4 .\" purpose with or without fee is hereby granted, provided that the above
5 .\" copyright notice and this permission notice appear in all copies.
6 .\"
7 .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 .Dd $Mdocdate: October 2 2020$
15 .Dt GMIND 1
16 .Os
17 .Sh NAME
18 .Nm gmid
19 .Nd dead simple zero configuration gemini server
20 .Sh SYNOPSIS
21 .Nm
22 .Bk -words
23 .Op Fl 6fh
24 .Op Fl c Ar cert.pem
25 .Op Fl d Ar docs
26 .Op Fl k Ar key.pem
27 .Op Fl p Ar port
28 .Op Fl x Ar cgi-bin
29 .Ek
30 .Sh DESCRIPTION
31 .Nm
32 is a simple and minimal gemini server that can serve static files and
33 execute CGI scripts.
34 .Pp
35 .Nm
36 won't serve files outside the given directory and won't follow
37 symlinks.
38 Furthermore, on
39 .Ox ,
40 .Xr pledge 2
41 and
42 .Xr unveil 2
43 are used to ensure that
44 .Nm
45 dosen't do anything else than read files from the given directory,
46 accept network connections and, optionally, execute CGI scripts.
47 .Pp
48 .Nm
49 fully supports IRIs (Internationalized Resource Identifiers, see
50 RFC3987).
51 .Pp
52 It should be noted that
53 .Nm
54 is very simple in its implementation, and so it may not be appropriate
55 for serving sites with lots of users.
56 After all, the code is single threaded and use a single process,
57 although it can handle multiple clients at the same time.
58 .Pp
59 If a user request path is a directory,
60 .Nm
61 will try to serve a
62 .Pa index.gmi
63 file inside that directory.
64 .Pp
65 The options are as follows:
66 .Bl -tag -width 12m
67 .It Fl 6
68 Enable IPv6.
69 .It Fl c Ar cert.pem
70 The certificate to use, by default is
71 .Pa cert.pem .
72 .It Fl d Ar docs
73 The root directory to serve.
74 .Nm
75 won't serve any file that is outside that directory.
76 By default is
77 .Pa docs .
78 .It Fl f
79 stays and log in the foreground, do not daemonize the process.
80 .It Fl h
81 Print the usage and exit.
82 .It Fl k Ar key.pem
83 The key for the certificate, by default is
84 .Pa key.pem .
85 .It Fl p Ar port
86 The port to bind to, by default 1965.
87 .It Fl x Ar dir
88 Enable execution of CGI scripts inside the given directory (relative
89 to the document root.) Cannot be provided more than once.
90 .El
91 .Sh CGI
92 When CGI scripts are enabled for a directory, a request for an
93 executable file will execute it and fed its output to the client.
94 .Pp
95 The CGI scripts will inherit the environment from
96 .Nm
97 with these additional variables set:
98 .Bl -tag -width 18m
99 .It Ev SERVER_SOFTWARE
100 "gmid"
101 .It Ev SERVER_PORT
102 "1965"
103 .It Ev SCRIPT_NAME
104 The (public) path to the script.
105 .It Ev SCRIPT_EXECUTABLE
106 The full path to the executable.
107 .It Ev REQUEST_URI
108 The user request (without the query parameters.)
109 .It Ev REQUEST_RELATIVE
110 The request relative to the script.
111 .It Ev QUERY_STRING
112 The query parameters.
113 .It Ev REMOTE_HOST
114 The remote IP address.
115 .It Ev REMOTE_ADDR
116 The remote IP address.
117 .It Ev DOCUMENT_ROOT
118 The root directory being served, the one provided with the
119 .Ar d
120 parameter to
121 .Nm
122 .It Ev AUTH_TYPE
123 The string "Certificate" if the client used a certificate, otherwise unset.
124 .It Ev REMOTE_USER
125 The subject of the client certificate if provided, otherwise unset.
126 .It Ev TLS_CLIENT_ISSUER
127 The is the issuer of the client certificate if provided, otherwise unset.
128 .It Ev TLS_CLIENT_HASH
129 The hash of the client certificate if provided, otherwise unset.
130 The format is "ALGO:HASH".
131 .El
132 .Pp
133 Let's say you have a script in
134 .Pa /cgi-bin/script
135 and the user request is
136 .Pa /cgi-bin/script/foo/bar?quux .
137 Then
138 .Ev SCRIPT_NAME
139 will be
140 .Pa cgi-bin/script ,
141 .Ev SCRIPT_EXECUTABLE
142 will be
143 .Pa $DOCUMENT_ROOT/cgi-bin/script ,
144 .Ev REQUEST_URI
145 will be
146 .Pa cgi-bin/script/foo/bar ,
147 .Ev REQUEST_RELATIVE
148 will be
149 .Pa foo/bar
150 and
151 .Ev QUERY_STRING
152 will be
153 .Ar quux .
154 .Sh EXAMPLES
155 To quickly getting started
156 .Bd -literal -offset indent
157 $ # generate a cert and a key
158 $ openssl req -x509 -newkey rsa:4096 -keyout key.pem \\
159 -out cert.pem -days 365 -nodes
160 $ mkdir docs
161 $ cat <<EOF > docs/index.gmi
162 # Hello world
163 test paragraph...
164 EOF
165 $ gmid -c cert.pem -k key.pem -d docs
166 .Ed
167 .Pp
168 Now you can visit gemini://localhost/ with your preferred gemini
169 client.
170 .Pp
171 To add some CGI scripts, assuming a setup similar to the previous
172 example, you can
173 .Bd -literal -offset indent
174 $ mkdir docs/cgi-bin
175 $ cat <<EOF > docs/cgi-bin/hello-world
176 #!/bin/sh
177 printf "20 text/plain\\r\\n"
178 echo "hello world!"
179 EOF
180 $ gmid -x cgi-bin
181 .Ed
182 .Pp
183 Note that the argument to the
184 .Fl x
185 option is
186 .Pa cgi-bin
187 and not
188 .Pa docs/cgi-bin ,
189 since it's relative to the document root.
190 .Sh ACKNOWLEDGEMENTS
191 .Nm
192 uses the "Flexible and Economical" UTF-8 decoder written by
193 .An Bjoern Hoehrmann .
194 .Sh CAVEATS
195 .Bl -bullet
196 .It
197 it doesn't support virtual hosts: the host part of the request URL is
198 completely ignored.
199 .It
200 a %2F sequence in the path part is indistinguishable from a literal
201 slash: this is not RFC3986-compliant.
202 .It
203 a %00 sequence either in the path or in the query part is treated as
204 invalid character and thus rejected.
205 .El