gemini server written in C used with inetd
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Go to file
Solene Rapenne e61ce5bd13
continuous-integration/drone/push Build was killed Details
continuous-integration/drone/pr Build was killed Details
continuous-integration/drone Build was killed Details
add some CI
11 months ago
tests fix cgi support for PATH_INFO 1 year ago
.drone.yml add some CI 11 months ago
.gitignore add .gitignore for build artifacts 2 years ago
LICENSE Bump LICENSE to include 2021 2 years ago
Makefile Add a configure script to make compiling on Linux easier 2 years ago README: use repology to list where vger is packaged 1 year ago Add a configure script to make compiling on Linux easier 2 years ago
configure Add configure script 2 years ago
main.c fix cgi support for PATH_INFO 1 year ago
mimes.c Fix virtualhost support changing the way request is parsed 2 years ago
mimes.h add mimetype and autoindex option + minor changes 2 years ago
opts.h Fix virtualhost support changing the way request is parsed 2 years ago
shell.nix add Nix shell file 2 years ago
utils.c fix NetBSD macro check 1 year ago
utils.h Add simple cgi support +: 2 years ago
vger.8 Fix virtualhost support changing the way request is parsed 2 years ago

A simplistic and secure Gemini server

Vger is a gemini server supporting chroot, virtualhosts, CGI, default language choice, redirections and MIME types detection.

Vger design is relying on inetd and a daemon to take care of TLS. The idea is to delegate TLS and network to daemons which proved doing it correctly, so vger takes its request from stdin and output the result to stdout.

The average setup should look like:

           ↓           TCP request on port 1965
       relayd or haproxy
       or stunnel on inetd
           ↓           TCP request to a port of choice on localhost
       vger on inetd

Vger is perfectly secure if run on OpenBSD, using unveil() the filesystem access is restricted to one directory (default to /var/gemini/) and with pledge() only systems calls related to reading files and reading input/output are allowed. More explanations about Vger security can be found on this link.

For all supported OS, it's possible to run Vger in a chroot and drop privileges to a dedicated user.


vger is available as a package for the following systems:

Packaging status

Building from sources

git clone
cd vger
./configure (only really useful for Linux)
doas make install

On GNU/Linux, make sure you installed libbsd, it has been reported that using clang was required too.

For NixOS/Nix users, there is a shell.nix listing the dependencies.

Running tests

Vger comes with a test suite you can use with make test.

Some files under /var/gemini/ are required to test the code path without a -d parameter.

Command line parameters

Vger has a few parameters you can use in inetd configuration.

  • -d PATH: use PATH as the data directory to serve files from. Default is /var/gemini
  • -l LANG: change the language in the status return code. Default is no language specified.
  • -v: enable virtualhost support, the hostname in the query will be considered as a directory name.
  • -u username: enable chroot to the data directory and drop privileges to username.
  • -m MIME : use MIME as default instead of "application/octet-stream".
  • -i : Enable auto index if no "index.gmi" file is found in a directory.
  • -c CGI_PATH : files in CGI_PATH are executed and their output is returned to the client.

How to configure Vger using relayd and inetd

Create directory /var/gemini/ (I'd allow this to be configured later), files will be served from there.

Create an user gemini_user.

Add this line to inetd.conf: stream tcp nowait gemini_user /usr/local/bin/vger vger

Add this to relayd.conf

log connection
tcp protocol "gemini" {
    tls keypair hostname.example

relay "gemini" {
    listen on hostname.example port 1965 tls
    protocol "gemini"
    forward to port 11965

Make sure certificates files match hostname: /etc/ssl/private/hostname.example.key and /etc/ssl/hostname.example.crt.

On OpenBSD, enable inetd and relayd and start them:

# rcctl enable relayd inetd
# rcctl start relayd inetd

Don't forget to open the TCP port 1965 in your firewall.

Vger will serve files named index.gmi if no explicit filename is given. If this file doesn't exist and auto index is enabled, an index file with a link to every file in the directory will be served.