aboutsummaryrefslogtreecommitdiff

SpaceBeans Gemini Server

This is an experimental server for the Gemini protocol.

It is built using Scala and Akka Streams. The name tries to link the Gemini theme with the fact that the server runs on the Java Virtual Machine.

Some of the SpaceBeans features:

  • Static files, including optional directory listings
  • IPv4 and IPv6
  • Configurable MIME types, or a built-in resolver
  • Virtual hosting, with SNI support
  • User directories support
  • Classic CGI scripts
  • User provided certificates or auto-generated in memory (for development)
  • Configurable SSL engine (e.g. TLSv1.2 and/or TLSv1.3), with configurable ciphers

Check CHANGES to see what's new in the latest release.

If you have a Gemini browser, you can also visit: gemini://capsule.usebox.net/spacebeans/

How to run it

Download the jar distribution file and install Java Runtime Environment 11 (or later; OpenJDK's JRE recommended).

You can run the service with:

java -jar spacebeans-VERSION.jar -c spacebeans.conf

You can also run the server with --help flag for CLI help.

Please check the example configuration file for instructions on how to configure the service.

Running it as a service

Check this document on how to deploy on Debian.

On security

You should evaluate your security requirements when running SpaceBeans.

In this section TOFU refers to "Trust On First Use".

Auto-generated self-signed certificate

This is the easiest option, no need to store securely the certificate. The downside is that you get a new certificate every time you start the service, and that's bad for TOFU validation.

This is recommended only for development and not for a service facing the Internet.

Comment out the key-store section on your virtual host and you are done.

Self-signed certificate

You can generate a self signed certificate using Java's keytool:

keytool -genkey -keyalg RSA -alias ALIAS -keystore keystore.jks -storepass SECRET -noprompt -validity 36500 -keysize 2048

When entering the certificate details, use the domain name as CN.

In the configuration file provide the path to the keystore, the alias and the secret used when generating the certificate.

This is the recommended TOFU-compatible way of managing certificates. The certificate should be set to expire way in the future because changing certificates doesn't play well with TOFU validation.

Import a CA signed certificate

The certificate has to be converted and imported into a JKS keystore to be used by the server.

For example:

keytool -import -alias ALIAS -keystore keystore.jks -file cert.pem -storepass SECRET -noprompt

Answer "yes" when asked if the certificate should be trusted.

In the configuration file provide the path to the keystore, the alias and the secret used when importing the certificate.

CA signed certificates don't play well with TOFU, but if the client is properly validating the certificate, this is perfectly safe.

CGI support

Classic CGI is supported via the allow-cgi flag in the directories directive.

The flag only affects to the specified directory.

The environment variables provided to the CGIs are:

Variable Example
REMOTE_ADDR 127.0.0.1
SERVER_PORT 1965
GEMINI_URL gemini://localhost/mycgi/example/path?test=1
REMOTE_HOST 127.0.0.1
SERVER_PROTOCOL GEMINI
SERVER_SOFTWARE spacebeans/v1.1.3
SCRIPT_NAME mycgi
SERVER_NAME localhost
PATH_INFO /example/path
GATEWAY_INTERFACE CGI/1.1
QUERY_STRING test=1

These are described in RFC-3875.

The server expects:

  • the CGI must terminate with exit code 0 (success)
  • the response will be in CGI's standard output
  • it must be a valid Gemini response

An example of a CGI script written in Python that outputs the environment variables could be:

#!/usr/bin/env python3

import os

print("20 text/gemini\r\n")
print('\n'.join([k + "=" + v for k, v in os.environ.items()]))

Development

Requirements:

  • JDK 11 (or later)
  • git (the git repo is required to set the version; GitLab's source archives won't compile)

Run the server with ./mill server.run and the tests with ./mill server.test.

To build the jar bundle, run ./mill server.assembly and the result will be generated in out/server/assembly/dest/.

The sources must be formatted with scalafmt, either via your editor or running:

./mill mill.scalalib.scalafmt.ScalafmtModule/reformatAll __.sources

This will be enforced by CI.

License

Copyright (C) 2021, 2022 Juan J. Martinez jjm@usebox.net
This software is distributed under MIT license, unless stated otherwise.

See COPYING file.