Gemini Server in C. From https://github.com/jovoro/geminid

Bob Mottram ff0d695551 Merge 2 months ago
docroot b370f8f433 Switch to .gmi ending for gemini files 5 months ago
.gitignore 29c4fdce34 Cleanup 5 months ago
LICENSE 7ce7673a44 Use real name in LICENSE 5 months ago
Makefile fcb49e4d10 Add SNI and vhost functionality 4 months ago
README.md 7e94019efc Update docs 3 months ago
config.c 952634014d Make usage of IPv6 configurable 3 months ago
config.h 952634014d Make usage of IPv6 configurable 3 months ago
example.conf 7e94019efc Update docs 3 months ago
file.c 4c5933d196 Make gcc shut up about string length 4 months ago
file.h 235783c651 Add support for directory listing 5 months ago
gemini.c 011dd72675 Better handling of requests exceeding 1024 bytes 3 months ago
gemini.h fcb49e4d10 Add SNI and vhost functionality 4 months ago
lexurl.l 1fbdc50bfd Add new URL parser and test program 5 months ago
log.c 559b06a3a6 Fix date in error log 5 months ago
log.h 292ac75f84 Introduce configuration via configuration file, make log date format configurable 5 months ago
main.c a0b2d654c0 Do not exit when accept fails 3 months ago
mime.c 06f6596a0e Add basic handling of mime types via libmagic. 5 months ago
mime.h 06f6596a0e Add basic handling of mime types via libmagic. 5 months ago
parseurl.c 2ea90e4806 Add missing license 4 months ago
tls.c 952634014d Make usage of IPv6 configurable 3 months ago
tls.h 952634014d Make usage of IPv6 configurable 3 months ago
url.c e84c6839c5 Handle userinfo according to spec, treat paths outside of document_root as status 51, handle potential NULL-pointer in build_request_string 4 months ago
url.h e6ea0912a4 Silence warnings on FreeBSD 4 months ago
util.c 19f6862347 Mark for later cleanup 4 months ago
util.h 06f6596a0e Add basic handling of mime types via libmagic. 5 months ago
vhost.c 2ea90e4806 Add missing license 4 months ago
vhost.h 2ea90e4806 Add missing license 4 months ago

README.md

geminid

A Gemini Server in C. Please note that this is not production-ready code. The current state is a result of a few hours of hacking, barely able to even serve content. But the goal is to have a compliant gemini server written in C.

Prerequisites

A Unix-like or POSIX-compliant OS is required. OpenSSL 1.1.1 is recommended. If you build with an earlier version, I assume it is one which at least supports TLS 1.2. You need to define TLS_USE_V1_2_METHOD if you want to use TLS 1.2. If you want to use even older versions, you need to modify the source code in tls.c to use the appropriate version-specific method.

I've added a more sophisticated URL parser which is based on lex/flex, so you need that, too. As of 2020-05-20 there is a new configuration file introduced which requires libconfig as a dependency.

Building

Edit Makefile and gemini.h to your needs, do make geminid. There is a test program for the URL parser, which can be built with make parseurl. If you have non-standard include or library paths, you can use INCDIRS and LIBDIRS, respectively. You are advised to include local modifications in a separate file Makefile.local, which will be included if it exists.

So, if you are on BSD, you might want to do

cat > Makefile.local <<EOF
INCDIRS=-I/usr/local/include
LIBDIRS=-L/usr/local/lib
EOF

to let the preprocessor and linker know where to look for libraries, i.e. libconfig.

If you are running CentOS 7 you may want to install and use the separately packaged version of OpenSSL 1.1.x, as mentioned by Jaroslaw Zachwieja:

# yum install gcc openssl11-devel file-devel libconfig-devel flex
$ cat > Makefile.local <<EOF
INCDIRS=-I/usr/include/openssl11
LIBDIRS=-L/usr/lib64/openssl11
EOF

Configuring

There's an example configuration file named example.conf in this repo. You can define multiple virtual hosts, of which the first definition is the default vhost. The default vhost is used if no servername is defined during the TLS handshake or if no vhost definition matches the provided hostname. Each vhost needs a separate TLS certificate.

The format of log times is described according to strftime(3). The docroot directive is relative to the serverroot. Log files are relative to logdir. Certificates are absolute or relative to the cwd of the geminid process, since they tend to live anywhere on the filesystem. I don't know if that makes sense to you. If it doesn't, let me know - I'd love to hear your thoughts.

There is the possibility to use IPv6. Only one address will be bound, though. If you want to use both IPv4 and IPv6 use have to use 4in6. On some systems this needs to be enabled explicitly, for example on FreeBSD you'd have to change the following sysctl parameter: net.inet6.ip6.v6only=0

Running

Just run the produced executable geminid. Some options are now configurable via command line parameters:

  • -c <config>: Path to the configuration file
  • -t: Test and print configuration

Complaining

To vent your anger, you may reach me at jr at vrtz dot ch.

You can find a demonstration of it running at gemini://gemini.uxq.ch/ and some more information on how I run it at gemini://gemini.uxq.ch/running.gmi