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 root Pa directory
416 Specify the root directory for this server
417 .Pq alas the current Dq document root .
418 It's relative to the chroot if enabled.
419 .It Ic require Ic client Ic ca Pa path
420 Allow requests only from clients that provide a certificate signed by
421 the CA certificate in
422 .Pa path .
423 It needs to be a PEM-encoded certificate and it's not relative to the
424 chroot.
425 .It Ic strip Ar number
426 Strip
427 .Ar number
428 components from the beginning of the path before doing a lookup in the
429 root directory.
430 It's also considered for the
431 .Ar meta
432 parameter in the scope of a
433 .Ic block return .
434 .El
435 .Sh CGI
436 When a request for an executable file matches the
437 .Ic cgi
438 rule, that file will be executed and its output fed to the client.
439 .Pp
440 The CGI scripts are executed in the directory they reside and inherit
441 the environment from
442 .Nm
443 with these additional variables set:
444 .Bl -tag -width 24m
445 .It Ev GATEWAY_INTERFACE
446 .Dq CGI/1.1
447 .It Ev GEMINI_DOCUMENT_ROOT
448 The root directory of the virtual host.
449 .It Ev GEMINI_SCRIPT_FILENAME
450 Full path to the CGI script being executed.
451 .It Ev GEMINI_URL
452 The full IRI of the request.
453 .It Ev GEMINI_URL_PATH
454 The path of the request.
455 .It Ev PATH_INFO
456 The portion of the requested path that is derived from the the IRI
457 path hierarchy following the part that identifies the script itself.
458 Can be unset.
459 .It Ev PATH_TRANSLATED
460 Present if and only if
461 .Ev PATH_INFO
462 is set.
463 It represent the translation of the
464 .Ev PATH_INFO .
465 .Nm
466 builds this by appending the
467 .Ev PATH_INFO
468 to the virtual host directory root.
469 .It Ev QUERY_STRING
470 The decoded query string.
471 .It Ev REMOTE_ADDR , Ev REMOTE_HOST
472 Textual representation of the client IP.
473 .It Ev REQUEST_METHOD
474 This is present only for RFC3875 (CGI) compliance.
475 It's always set to the empty string.
476 .It Ev SCRIPT_NAME
477 The part of the
478 .Ev GEMINI_URL_PATH
479 that identifies the current CGI script.
480 .It Ev SERVER_NAME
481 The name of the server
482 .It Ev SERVER_PORT
483 The port the server is listening on.
484 .It Ev SERVER_PROTOCOL
485 .Dq GEMINI
486 .It Ev SERVER_SOFTWARE
487 The name and version of the server, i.e.
488 .Dq gmid/1.7.3
489 .It Ev AUTH_TYPE
490 The string "Certificate" if the client used a certificate, otherwise
491 unset.
492 .It Ev REMOTE_USER
493 The subject of the client certificate if provided, otherwise unset.
494 .It Ev TLS_CLIENT_ISSUER
495 The is the issuer of the client certificate if provided, otherwise
496 unset.
497 .It Ev TLS_CLIENT_HASH
498 The hash of the client certificate if provided, otherwise unset.
499 The format is
500 .Dq ALGO:HASH .
501 .It Ev TLS_VERSION
502 The TLS version negotiated with the peer.
503 .It Ev TLS_CIPHER
504 The cipher suite negotiated with the peer.
505 .It Ev TLS_CIPHER_STRENGTH
506 The strength in bits for the symmetric cipher that is being used with
507 the peer.
508 .It Ev TLS_CLIENT_NOT_AFTER
509 The time corresponding to the end of the validity period of the peer
510 certificate in the ISO 8601 format
511 .Pq e.g. Dq 2021-02-07T20:17:41Z .
512 .It Ev TLS_CLIENT_NOT_BEFORE
513 The time corresponding to the start of the validity period of the peer
514 certificate in the ISO 8601 format.
515 .El
516 .Sh FastCGI
517 .Nm
518 optionally supports FastCGI.
520 .Ic fastcgi
521 rule must be present in a server or location block.
522 Then, all requests matching that server or location will be handled
523 via the specified FastCGI backend.
524 .Pp
525 By default the following variables
526 .Pq parameters
527 are sent, and carry the same semantics as with CGI.
528 More parameters can be added with the
529 .Ic param
530 option.
531 .Pp
532 .Bl -bullet -compact
533 .It
534 GATEWAY_INTERFACE
535 .It
536 GEMINI_URL_PATH
537 .It
538 QUERY_STRING
539 .It
540 REMOTE_ADDR
541 .It
542 REMOTE_HOST
543 .It
544 REQUEST_METHOD
545 .It
546 SERVER_NAME
547 .It
548 SERVER_PROTOCOL
549 .It
550 SERVER_SOFTWARE
551 .It
552 AUTH_TYPE
553 .It
554 REMOTE_USER
555 .It
556 TLS_CLIENT_ISSUER
557 .It
558 TLS_CLIENT_HASH
559 .It
560 TLS_VERSION
561 .It
562 TLS_CIPHER
563 .It
564 TLS_CIPHER_STRENGTH
565 .It
566 TLS_CLIENT_NOT_BEFORE
567 .It
568 TLS_CLIENT_NOT_AFTER
569 .El
570 .Sh MIME
571 To auto-detect the MIME type of the response
572 .Nm
573 looks at the file extension and consults its internal table.
574 By default the following mappings are loaded, but they can be
575 overridden or extended using the
576 .Ic map
577 configuration option.
578 If no MIME is found, the value of
579 .Ic default type
580 matching the file
581 .Ic location
582 will be used, which is
583 .Dq application/octet-stream
584 by default.
585 .Pp
586 .Bl -tag -offset indent -width 14m -compact
587 .It diff
588 text/x-patch
589 .It gemini, gmi
590 text/gemini
591 .It gif
592 image/gif
593 .It jpeg
594 image/jpeg
595 .It jpg
596 image/jpeg
597 .It markdown, md
598 text/markdown
599 .It patch
600 text/x-patch
601 .It pdf
602 application/pdf
603 .It png
604 image/png
605 .It svg
606 image/svg+xml
607 .It txt
608 text/plain
609 .It xml
610 text/xml
611 .El
612 .Sh LOGGING
613 Messages and requests are logged by
614 .Xr syslog 3
615 using the
616 .Dv DAEMON
617 facility or printed on
618 .Em stderr .
619 .Pp
620 Requests are logged with the
621 .Dv NOTICE
622 severity.
623 Each request log entry has the following fields, separated by
624 whitespace:
625 .Pp
626 .Bl -bullet -compact
627 .It
628 Client IP address and the source port number, separated by a colon
629 .It
630 .Sy GET
631 keyword
632 .It
633 Request URL
634 .It
635 Response status
636 .It
637 Response meta
638 .El
639 .Sh EXAMPLES
640 Serve the current directory
641 .Bd -literal -offset indent
642 $ gmid .
643 .Ed
644 .Pp
645 To serve the directory
646 .Pa docs
647 and enable CGI scripts inside
648 .Pa docs/cgi
649 .Bd -literal -offset indent
650 $ mkdir docs/cgi
651 $ cat <<EOF > docs/cgi/hello
652 #!/bin/sh
653 printf "20 text/plain\er\en"
654 echo "hello world"
655 EOF
656 $ chmod +x docs/cgi/hello
657 $ gmid -x '/cgi/*' docs
658 .Ed
659 .Pp
660 An X.509 certificate must be provided to run
661 .Nm
662 using a configuration file.
663 First, the RSA certificate is created using a wildcard common name:
664 .Bd -literal -offset indent
665 # openssl genrsa \-out /etc/ssl/private/example.com.key 4096
666 # openssl req \-new \-x509 \e
667 \-key /etc/ssl/private/example.com.key \e
668 \-out /etc/ssl/example.com.crt \e
669 \-days 36500 \-nodes \e
670 \-subj "/CN=example.com"
671 # chmod 600 /etc/ssl/example.com.crt
672 # chmod 600 /etc/ssl/private/example.com.key
673 .Ed
674 .Pp
675 In the example above, a certificate is valid for one hundred years from
676 the date it was created, which is normal for TOFU.
677 .Pp
678 The following is an example of a possible configuration for a site
679 that enables only TLSv1.3, adds a mime type for the file extension
680 .Qq rtf
681 and defines two virtual host:
682 .Bd -literal -offset indent
683 ipv6 on # enable ipv6
685 protocols "tlsv1.3"
687 map "application/rtf" to-ext "rtf"
689 server "example.com" {
690 cert "/etc/ssl/example.com.crt"
691 key "/etc/ssl/private/example.com.key"
692 root "/var/gemini/example.com"
695 server "it.example.com" {
696 cert "/etc/ssl/example.com.crt"
697 key "/etc/ssl/private/example.com.key"
698 root "/var/gemini/it.example.com"
700 # enable cgi scripts inside "cgi-bin"
701 cgi "/cgi-bin/*"
703 # set the language for text/gemini files
704 lang "it"
706 .Ed
707 .Pp
708 Yet another example, showing how to enable a
709 .Ic chroot
710 and use
711 .Ic location
712 rule
713 .Bd -literal -offset indent
714 chroot "/var/gemini"
715 user "_gmid"
717 server "example.com" {
718 cert "/path/to/cert.pem" # absolute path
719 key "/path/to/key.pem" # also absolute
720 root "/example.com" # relative to the chroot
722 location "/static/*" {
723 # load the following rules only for
724 # requests that matches "/static/*"
726 auto index on
727 index "index.gemini"
730 .Ed
731 .Sh ACKNOWLEDGEMENTS
732 .Nm
733 uses the
734 .Dq Flexible and Economical
735 UTF-8 decoder written by
736 .An Bjoern Hoehrmann .
737 .Sh AUTHORS
738 .An -nosplit
739 The
740 .Nm
741 program was written by
742 .An Omar Polo Aq Mt op@omarpolo.com .
743 .Sh CAVEATS
744 .Bl -bullet
745 .It
746 All the root directories are opened during the daemon startup; if a
747 root directory is deleted and then re-created,
748 .Nm
749 won't be able to serve files inside that directory until a restart.
750 This restriction only applies to the root directories and not their
751 content.
752 .It
753 a %2F sequence is indistinguishable from a literal slash: this is not
754 RFC3986-compliant.
755 .It
756 a %00 sequence is treated as invalid character and thus rejected.
757 .El