Blob


1 .\" Copyright (c) 2021 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: July 29 2021$
15 .Dt GMID 1
16 .Os
17 .Sh NAME
18 .Nm gmid
19 .Nd simple and secure Gemini server
20 .Sh SYNOPSIS
21 .Nm
22 .Bk -words
23 .Op Fl fnv
24 .Op Fl c Ar config
25 .Op Fl D Ar macro Ns = Ns Ar value
26 .Op Fl P Ar pidfile
27 .Ek
28 .Nm
29 .Bk -words
30 .Op Fl 6hVv
31 .Op Fl d Pa certs-dir
32 .Op Fl H Ar hostname
33 .Op Fl p Ar port
34 .Op Fl x Pa cgi
35 .Op Pa dir
36 .Ek
37 .Sh DESCRIPTION
38 .Nm
39 is a simple and minimal gemini server that can serve static files,
40 execute CGI scripts and talk to FastCGI applications.
41 It can run without a configuration file with a limited set of features
42 available.
43 .Pp
44 .Nm
45 rereads the configuration file when it receives
46 .Dv SIGHUP .
47 .Pp
48 The options are as follows:
49 .Bl -tag -width 14m
50 .It Fl c Pa config
51 Specify the configuration file.
52 .It Fl D Ar macro Ns = Ns Ar value
53 Define
54 .Ar macro
55 to be set to
56 .Ar value
57 on the command line.
58 Overrides the definition of
59 .Ar macro
60 in the config file if present.
61 .It Fl f
62 Stays and logs on the foreground.
63 .It Fl n
64 Check that the configuration is valid, but don't start the server.
65 If specified two or more time, dump the configuration in addition to
66 verify it.
67 .It Fl P Pa pidfile
68 Write daemon's pid to the given location.
69 .Ar pidfile
70 will also act as lock: if another process is holding a lock on that
71 file,
72 .Nm
73 will refuse to start.
74 .El
75 .Pp
76 If no configuration file is given,
77 .Nm
78 will look for the following options
79 .Bl -tag -width 14m
80 .It Fl 6
81 Enable IPv6.
82 .It Fl d Pa certs-path
83 Directory where certificates for the config-less mode are stored.
84 By default it is
85 .Pa $XDG_DATA_HOME/gmid ,
86 i.e.
87 .Pa ~/.local/share/gmid .
88 .It Fl H Ar hostname
89 The hostname
90 .Po
91 .Ar localhost
92 by default
93 .Pc .
94 Certificates for the given
95 .Ar hostname
96 are searched inside the
97 .Pa certs-dir
98 directory given with the
99 .Fl d
100 option.
101 They have the form
102 .Pa hostname.cert.pem
103 and
104 .Pa hostname.key.pem .
105 If a certificate or a key doesn't exist for a given hostname, they
106 will be generated automatically.
107 .It Fl h , Fl -help
108 Print the usage and exit.
109 .It Fl p Ar port
110 The port to listen on, by default 1965.
111 .It Fl V , Fl -version
112 Print the version and exit.
113 .It Fl v
114 Verbose mode.
115 Multiple
116 .Fl v
117 options increase the verbosity.
118 .It Fl x Pa path
119 Enable execution of
120 .Sx CGI
121 scripts.
122 See the description of the
123 .Ic cgi
124 option in the
125 .Sq Servers
126 section below to learn how
127 .Pa path
128 is processed.
129 Cannot be provided more than once.
130 .It Pa dir
131 The root directory to serve.
132 By default the current working directory is assumed.
133 .El
134 .Sh CONFIGURATION FILE
135 The configuration file is divided into three sections:
136 .Bl -tag -width xxxx
137 .It Sy Macros
138 User-defined variables may be defined and used later, simplifying the
139 configuration file.
140 .It Sy Global Options
141 Global settings for
142 .Nm .
143 .It Sy Servers
144 Virtual hosts definition.
145 .El
146 .Pp
147 Within the sections, empty lines are ignored and comments can be put
148 anywhere in the file using a hash mark
149 .Pq Sq # ,
150 and extend to the end of the current line.
151 A boolean is either the symbol
152 .Sq on
153 or
154 .Sq off .
155 A string is a sequence of characters wrapped in double quotes,
156 .Dq like this .
157 Multiple strings one next to the other are joined into a single
158 string:
159 .Bd -literal -offset indent
160 # equivalent to "temporary-failure"
161 block return 40 "temporary" "-" "failure"
162 .Ed
163 .Pp
164 Furthermore, quoting is necessary only when a string needs to contain
165 special characters
166 .Pq like spaces or punctuation ,
167 something that looks like a number or a reserved keyword.
168 The last example could have been written also as:
169 .Bd -literal -offset indent
170 block return 40 temporary "-" failure
171 .Ed
172 .Pp
173 Strict ordering of the sections is not enforced, so that is possible
174 to mix macros, options and
175 .Ic server
176 blocks.
177 However, defining all the
178 .Ic server
179 blocks after the macros and the global options is recommended.
180 .Pp
181 Newlines are often optional, except around top-level instructions, and
182 semicolons
183 .Dq \&;
184 can also be optionally used to separate options.
185 .Pp
186 Additional configuration files can be included with the
187 .Ic include
188 keyword, for example:
189 .Bd -literal -offset indent
190 include "/etc/gmid.conf.local"
191 .Ed
192 .Ss Macros
193 Macros can be defined that will later be expanded in context.
194 Macro names must start with a letter, digit or underscore and may
195 contain any of those characters.
196 Macros names may not be reserved words.
197 Macros are not expanded inside quotes.
198 .Pp
199 Two kinds of macros are supported: variable-like and proper macros.
200 When a macro is invoked with a
201 .Dq $
202 before its name its expanded as a string, whereas when it's invoked
203 with a
204 .Dq @
205 its expanded in-place.
206 .Pp
207 For example:
208 .Bd -literal -offset indent
209 dir = "/var/gemini"
210 certdir = "/etc/keys"
211 common = "lang it; auto index on"
213 server "foo" {
214 root $dir "/foo" # -> /var/gemini/foo
215 cert $certdir "/foo.crt" # -> /etc/keys/foo.crt
216 key $certdir "/foo.pem" # -> /etc/keys/foo.pem
217 @common
219 .Ed
220 .Ss Global Options
221 .Bl -tag -width 12m
222 .It Ic chroot Pa path
223 .Xr chroot 2
224 the process to the given
225 .Pa path .
226 The daemon has to be run with root privileges and thus the option
227 .Ic user
228 needs to be provided, so privileges can be dropped.
229 Note that
230 .Nm
231 will enter the chroot after loading the TLS keys, but before opening
232 the virtual host root directories.
233 It's recommended to keep the TLS keys outside the chroot.
234 Future version of
235 .Nm
236 may enforce this.
237 .It Ic ipv6 Ar bool
238 Enable or disable IPv6 support, off by default.
239 .It Ic map Ar mime-type Cm to-ext Ar file-extension
240 Map
241 .Ar mime-type
242 to the given
243 .Ar file-extension .
244 Both argument are strings.
245 .It Ic port Ar portno
246 The port to listen on.
247 1965 by default.
248 .It Ic prefork Ar number
249 Run the specified number of server processes.
250 This increases the performance and prevents delays when connecting to
251 a server.
252 When not in config-less mode,
253 .Nm
254 runs 3 server processes by default.
255 The maximum number allowed is 16.
256 .It Ic protocols Ar string
257 Specify the TLS protocols to enable.
258 Refer to
259 .Xr tls_config_parse_protocols 3
260 for the valid protocol string values.
261 By default, both TLSv1.3 and TLSv1.2 are enabled.
262 Use
263 .Dq tlsv1.3
264 to enable only TLSv1.3.
265 .It Ic user Ar string
266 Run the daemon as the given user.
267 .El
268 .Ss Servers
269 Every virtual host is defined by a
270 .Ic server
271 block:
272 .Bl -tag -width Ds
273 .It Ic server Ar hostname Brq ...
274 Match the server name using shell globbing rules.
275 It can be an explicit name,
276 .Ar www.example.com ,
277 or a name including a wildcards,
278 .Ar *.example.com .
279 .El
280 .Pp
281 Followed by a block of options that is enclosed in curly brackets:
282 .Bl -tag -width Ds
283 .It Ic alias Ar name
284 Specify an additional alias
285 .Ar name
286 for this server.
287 .It Ic auto Ic index Ar bool
288 If no index file is found, automatically generate a directory listing.
289 Disabled by default.
290 .It Ic block Op Ic return Ar code Op Ar meta
291 Send a reply and close the connection;
292 by default
293 .Ar code
294 is 40
295 and
296 .Ar meta
297 is
298 .Dq temporary failure .
299 If
300 .Ar code
301 is in the 3x range, then
302 .Ar meta
303 is mandatory.
304 Inside
305 .Ar meta ,
306 the following special sequences are supported:
307 .Bl -tag -width Ds -compact
308 .It \&%\&%
309 is replaced with a single
310 .Sq \&% .
311 .It \&%p
312 is replaced with the request path.
313 .It \&%q
314 is replaced with the query string of the request.
315 .It \&%P
316 is replaced with the server port.
317 .It \&%N
318 is replaced with the server name.
319 .El
320 .It Ic cert Pa file
321 Path to the certificate to use for this server.
322 The
323 .Pa file
324 should contain a PEM encoded certificate.
325 This option is mandatory.
326 .It Ic cgi Pa path
327 Execute
328 .Sx CGI
329 scripts that matches
330 .Pa path
331 using shell globbing rules.
332 .It Ic default type Ar string
333 Set the default media type that is used if the media type for a
334 specified extension is not found.
335 If not specified, the
336 .Ic default type
337 is set to
338 .Dq application/octet-stream .
339 .It Ic entrypoint Pa path
340 Handle all the requests for the current virtual host using the
341 .Sx CGI
342 script at
343 .Pa path ,
344 relative to the current document root.
345 .It Ic env Ar name Cm = Ar value
346 Set the environment variable
347 .Ar name
348 to
349 .Ar value
350 when executing CGI scripts.
351 Can be provided more than once.
352 .\" don't document the "spawn <prog>" form because it probably won't
353 .\" be kept.
354 .It Ic fastcgi Oo Ic tcp Oc Pa socket Oo Cm port Ar port Oc
355 Enable
356 .Sx FastCGI
357 instead of serving files.
358 The
359 .Pa socket
360 can either be a UNIX-domain socket or a TCP socket.
361 If the FastCGI application is listening on a UNIX domain socket,
362 .Pa socket
363 is a local path name within the
364 .Xr chroot 2
365 root directory of
366 .Nm .
367 Otherwise, the
368 .Ic tcp
369 keyword must be provided and
370 .Pa socket
371 is interpreted as a hostname or an IP address.
372 .Ar port
373 can be either a port number or the name of a service enclosed in
374 double quotes.
375 If not specified defaults to 9000.
376 .It Ic index Ar string
377 Set the directory index file.
378 If not specified, it defaults to
379 .Pa index.gmi .
380 .It Ic key Pa file
381 Specify the private key to use for this server.
382 The
383 .Pa file
384 should contain a PEM encoded private key.
385 This option is mandatory.
386 .It Ic lang Ar string
387 Specify the language tag for the text/gemini content served.
388 If not specified, no
389 .Dq lang
390 parameter will be added in the response.
391 .It Ic location Pa path Brq ...
392 Specify server configuration rules for a specific location.
393 The
394 .Pa path
395 argument will be matched against the request path with shell globbing
396 rules.
397 In case of multiple location statements in the same context, the first
398 matching location will be put into effect and the later ones ignored.
399 Therefore is advisable to match for more specific paths first and for
400 generic ones later on.
402 .Ic location
403 section may include most of the server configuration rules
404 except
405 .Ic alias , Ic cert , Ic cgi , Ic entrypoint , Ic env , Ic key ,
406 .Ic location No and Ic param .
407 .It Ic log Ar bool
408 Enable or disable the logging for the current server or location block.
409 .It Ic param Ar name Cm = Ar value
410 Set the param
411 .Ar name
412 to
413 .Ar value
414 for FastCGI.
415 .It Ic ocsp Ar file
416 Specify an OCSP response to be stapled during TLS handshakes
417 with this server.
418 The
419 .Ar file
420 should contain a DER-format OCSP response retrieved from an
421 OCSP server for the
422 .Ic cert
423 in use.
424 If the OCSP response in
425 .Ar file
426 is empty, OCSP stapling will not be used.
427 The default is to not use OCSP stapling.
428 .It Ic root Pa directory
429 Specify the root directory for this server
430 .Pq alas the current Dq document root .
431 It's relative to the chroot if enabled.
432 .It Ic require Ic client Ic ca Pa path
433 Allow requests only from clients that provide a certificate signed by
434 the CA certificate in
435 .Pa path .
436 It needs to be a PEM-encoded certificate and it's not relative to the
437 chroot.
438 .It Ic strip Ar number
439 Strip
440 .Ar number
441 components from the beginning of the path before doing a lookup in the
442 root directory.
443 It's also considered for the
444 .Ar meta
445 parameter in the scope of a
446 .Ic block return .
447 .El
448 .Sh CGI
449 When a request for an executable file matches the
450 .Ic cgi
451 rule, that file will be executed and its output fed to the client.
452 .Pp
453 The CGI scripts are executed in the directory they reside and inherit
454 the environment from
455 .Nm
456 with these additional variables set:
457 .Bl -tag -width 24m
458 .It Ev GATEWAY_INTERFACE
459 .Dq CGI/1.1
460 .It Ev GEMINI_DOCUMENT_ROOT
461 The root directory of the virtual host.
462 .It Ev GEMINI_SCRIPT_FILENAME
463 Full path to the CGI script being executed.
464 .It Ev GEMINI_URL
465 The full IRI of the request.
466 .It Ev GEMINI_URL_PATH
467 The path of the request.
468 .It Ev PATH_INFO
469 The portion of the requested path that is derived from the the IRI
470 path hierarchy following the part that identifies the script itself.
471 Can be unset.
472 .It Ev PATH_TRANSLATED
473 Present if and only if
474 .Ev PATH_INFO
475 is set.
476 It represent the translation of the
477 .Ev PATH_INFO .
478 .Nm
479 builds this by appending the
480 .Ev PATH_INFO
481 to the virtual host directory root.
482 .It Ev QUERY_STRING
483 The decoded query string.
484 .It Ev REMOTE_ADDR , Ev REMOTE_HOST
485 Textual representation of the client IP.
486 .It Ev REQUEST_METHOD
487 This is present only for RFC3875 (CGI) compliance.
488 It's always set to the empty string.
489 .It Ev SCRIPT_NAME
490 The part of the
491 .Ev GEMINI_URL_PATH
492 that identifies the current CGI script.
493 .It Ev SERVER_NAME
494 The name of the server
495 .It Ev SERVER_PORT
496 The port the server is listening on.
497 .It Ev SERVER_PROTOCOL
498 .Dq GEMINI
499 .It Ev SERVER_SOFTWARE
500 The name and version of the server, i.e.
501 .Dq gmid/1.7.3
502 .It Ev AUTH_TYPE
503 The string "Certificate" if the client used a certificate, otherwise
504 unset.
505 .It Ev REMOTE_USER
506 The subject of the client certificate if provided, otherwise unset.
507 .It Ev TLS_CLIENT_ISSUER
508 The is the issuer of the client certificate if provided, otherwise
509 unset.
510 .It Ev TLS_CLIENT_HASH
511 The hash of the client certificate if provided, otherwise unset.
512 The format is
513 .Dq ALGO:HASH .
514 .It Ev TLS_VERSION
515 The TLS version negotiated with the peer.
516 .It Ev TLS_CIPHER
517 The cipher suite negotiated with the peer.
518 .It Ev TLS_CIPHER_STRENGTH
519 The strength in bits for the symmetric cipher that is being used with
520 the peer.
521 .It Ev TLS_CLIENT_NOT_AFTER
522 The time corresponding to the end of the validity period of the peer
523 certificate in the ISO 8601 format
524 .Pq e.g. Dq 2021-02-07T20:17:41Z .
525 .It Ev TLS_CLIENT_NOT_BEFORE
526 The time corresponding to the start of the validity period of the peer
527 certificate in the ISO 8601 format.
528 .El
529 .Sh FastCGI
530 .Nm
531 optionally supports FastCGI.
533 .Ic fastcgi
534 rule must be present in a server or location block.
535 Then, all requests matching that server or location will be handled
536 via the specified FastCGI backend.
537 .Pp
538 By default the following variables
539 .Pq parameters
540 are sent, and carry the same semantics as with CGI.
541 More parameters can be added with the
542 .Ic param
543 option.
544 .Pp
545 .Bl -bullet -compact
546 .It
547 GATEWAY_INTERFACE
548 .It
549 GEMINI_URL_PATH
550 .It
551 QUERY_STRING
552 .It
553 REMOTE_ADDR
554 .It
555 REMOTE_HOST
556 .It
557 REQUEST_METHOD
558 .It
559 SERVER_NAME
560 .It
561 SERVER_PROTOCOL
562 .It
563 SERVER_SOFTWARE
564 .It
565 AUTH_TYPE
566 .It
567 REMOTE_USER
568 .It
569 TLS_CLIENT_ISSUER
570 .It
571 TLS_CLIENT_HASH
572 .It
573 TLS_VERSION
574 .It
575 TLS_CIPHER
576 .It
577 TLS_CIPHER_STRENGTH
578 .It
579 TLS_CLIENT_NOT_BEFORE
580 .It
581 TLS_CLIENT_NOT_AFTER
582 .El
583 .Sh MIME
584 To auto-detect the MIME type of the response
585 .Nm
586 looks at the file extension and consults its internal table.
587 By default the following mappings are loaded, but they can be
588 overridden or extended using the
589 .Ic map
590 configuration option.
591 If no MIME is found, the value of
592 .Ic default type
593 matching the file
594 .Ic location
595 will be used, which is
596 .Dq application/octet-stream
597 by default.
598 .Pp
599 .Bl -tag -offset indent -width 14m -compact
600 .It diff
601 text/x-patch
602 .It gemini, gmi
603 text/gemini
604 .It gif
605 image/gif
606 .It jpeg
607 image/jpeg
608 .It jpg
609 image/jpeg
610 .It markdown, md
611 text/markdown
612 .It patch
613 text/x-patch
614 .It pdf
615 application/pdf
616 .It png
617 image/png
618 .It svg
619 image/svg+xml
620 .It txt
621 text/plain
622 .It xml
623 text/xml
624 .El
625 .Sh LOGGING
626 Messages and requests are logged by
627 .Xr syslog 3
628 using the
629 .Dv DAEMON
630 facility or printed on
631 .Em stderr .
632 .Pp
633 Requests are logged with the
634 .Dv NOTICE
635 severity.
636 Each request log entry has the following fields, separated by
637 whitespace:
638 .Pp
639 .Bl -bullet -compact
640 .It
641 Client IP address and the source port number, separated by a colon
642 .It
643 .Sy GET
644 keyword
645 .It
646 Request URL
647 .It
648 Response status
649 .It
650 Response meta
651 .El
652 .Sh EXAMPLES
653 Serve the current directory
654 .Bd -literal -offset indent
655 $ gmid .
656 .Ed
657 .Pp
658 To serve the directory
659 .Pa docs
660 and enable CGI scripts inside
661 .Pa docs/cgi
662 .Bd -literal -offset indent
663 $ mkdir docs/cgi
664 $ cat <<EOF > docs/cgi/hello
665 #!/bin/sh
666 printf "20 text/plain\er\en"
667 echo "hello world"
668 EOF
669 $ chmod +x docs/cgi/hello
670 $ gmid -x '/cgi/*' docs
671 .Ed
672 .Pp
673 An X.509 certificate must be provided to run
674 .Nm
675 using a configuration file.
676 First, the RSA certificate is created using a wildcard common name:
677 .Bd -literal -offset indent
678 # openssl genrsa \-out /etc/ssl/private/example.com.key 4096
679 # openssl req \-new \-x509 \e
680 \-key /etc/ssl/private/example.com.key \e
681 \-out /etc/ssl/example.com.crt \e
682 \-days 36500 \-nodes \e
683 \-subj "/CN=example.com"
684 # chmod 600 /etc/ssl/example.com.crt
685 # chmod 600 /etc/ssl/private/example.com.key
686 .Ed
687 .Pp
688 In the example above, a certificate is valid for one hundred years from
689 the date it was created, which is normal for TOFU.
690 .Pp
691 The following is an example of a possible configuration for a site
692 that enables only TLSv1.3, adds a mime type for the file extension
693 .Qq rtf
694 and defines two virtual host:
695 .Bd -literal -offset indent
696 ipv6 on # enable ipv6
698 protocols "tlsv1.3"
700 map "application/rtf" to-ext "rtf"
702 server "example.com" {
703 cert "/etc/ssl/example.com.crt"
704 key "/etc/ssl/private/example.com.key"
705 root "/var/gemini/example.com"
708 server "it.example.com" {
709 cert "/etc/ssl/example.com.crt"
710 key "/etc/ssl/private/example.com.key"
711 root "/var/gemini/it.example.com"
713 # enable cgi scripts inside "cgi-bin"
714 cgi "/cgi-bin/*"
716 # set the language for text/gemini files
717 lang "it"
719 .Ed
720 .Pp
721 Yet another example, showing how to enable a
722 .Ic chroot
723 and use
724 .Ic location
725 rule
726 .Bd -literal -offset indent
727 chroot "/var/gemini"
728 user "_gmid"
730 server "example.com" {
731 cert "/path/to/cert.pem" # absolute path
732 key "/path/to/key.pem" # also absolute
733 root "/example.com" # relative to the chroot
735 location "/static/*" {
736 # load the following rules only for
737 # requests that matches "/static/*"
739 auto index on
740 index "index.gemini"
743 .Ed
744 .Sh ACKNOWLEDGEMENTS
745 .Nm
746 uses the
747 .Dq Flexible and Economical
748 UTF-8 decoder written by
749 .An Bjoern Hoehrmann .
750 .Sh AUTHORS
751 .An -nosplit
752 The
753 .Nm
754 program was written by
755 .An Omar Polo Aq Mt op@omarpolo.com .
756 .Sh CAVEATS
757 .Bl -bullet
758 .It
759 All the root directories are opened during the daemon startup; if a
760 root directory is deleted and then re-created,
761 .Nm
762 won't be able to serve files inside that directory until a restart.
763 This restriction only applies to the root directories and not their
764 content.
765 .It
766 a %2F sequence is indistinguishable from a literal slash: this is not
767 RFC3986-compliant.
768 .It
769 a %00 sequence is treated as invalid character and thus rejected.
770 .El