Gemini Servers, A user's persective.
▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
I actually am a software engineer, particularly experienced in Python/Django, with a smattering of dozens of languages. But for this experiment, I'm pretending for a moment that I'm a newbie to Geminispace and want to get a server up without building and maintaining the thing becoming my new hobby.
After all, if we want this to be a refuge for more than just tech people who want another hobby, we should consider the UX of sysadmin tasks.
My picks
Subject to change, obviously; I'm barely out of the "a"s.
- For serving Just A Bunch Of Files, agate and a-h/gemini gave me very little trouble, so long as you don't mind running binaries or compiling yourself.
- If you want interactivity, I don't have an answer yet. 'gemserv' seemed like a good option, and it does do cgi-bin, but older versions have a gaping security flaw and the latest version's cert setup is opaque and undocumented (see below if you insist...).
The To-Try List
Jetforce (Python, last updated 2 years ago)
https://github.com/michael-lazar/jetforce
- Astrobotany runs on it.
- It feels somewhat Flask-like, in that your published app is wrapped in a server class (jetforce.GeminiServer in this case) which handles the client/server layer.
The Tried List
agate (Rust, last updated 2 weeks ago)
https://github.com/mbrubeck/agate
- Binary download, that Just Worked. If I wanted to compile it myself for some reason, that'd be another story; every time I have ventured into the world of Rust, it seems that world has moved into an entirely new epoch.
- Accepted certs I generated for another server without fuss.
- Served "." just fine, making it fully portable. Your server and content could be backed up in a single zip file.
- Will it do more than static .gmi files? Nope.
- This is actually serving this page right now.
aiogemini (Python, last updated 9 months ago.)
https://github.com/rcarmo/aiogemini
- Source only. You could probably get there from the readme if you really wanted to.
- But you'll be reading Makefiles, because the server.py is extremely barebones and doesn't even take command line parameters, as far as I can tell.
apogee (kotlin, last updated 2 years ago)
https://github.com/bunburya/apogee
- kotlin, compile with gradlew. No binary builds.
- much heavier, does more than just static files. But being two years out-of-date, I don't have high hopes for more recent features, like Titan.
- compiling it took my server's load average to 79, ate all of the free memory, and then got OOM killed.
- This is probably not suited to small VPS servers or even raspberry Pis.
atlas (C# / dotnet8, last updated 1.5 years ago)
https://github.com/Alumniminium/atlas
- I'll have to come back to this later, if at all. No build instructions and no releases, so if you're not a C# person it's a steep hill.
- Does support CGI scripts and even provides an example one, showing how to support comments on pages.
blizanci (Erlang / Rebar, last updated 2 months ago)
https://github.com/mk270/blizanci
- I'm not allergic to Erlang myself, but getting a working Erlang stack on an arbitrary computer can be a tall ask, if it requires anything other than whatever your package manager will give you. Otherwise, you're in 'asdf' hell and I wouldn't wish that on anybody.
- On top of that, this needs Rebar3. Because of the aforementioned asdf hell that I'm in in order to maintain my Akkoma server, I'm not risking installing the 86 additional packages needed for rebar3. Maybe later, in a VM?
- But at least it has build instructions? Weird that this is worth a point.
- It does support CGI and Titan, and might be worth a deeper look later, but not for noobs.
gemeaux (Python, last updated 6 months ago)
https://github.com/brunobord/gemeaux
- This one hurts a bit, because they're trying hard to provide working build/install instructions. But the first commandline is "pip install gemeaux" and if you do that first, the rest of the instructions make no sens, as pip only installs the python library, not the Makefile.
- If you think of this one as a Python library, like Flask, the utility starts to make sense. It looks like it wouldn't be too hard to extend with custom route Handlers, which makes it pretty powerful.
- Similarly, request/response objects will be fairly familiar to web developers, and provide Gemini features needed for more than static files.
- Just not for noobs.
Warning DO NOT USE gemserv <0.6.6
It's a bit irresponsible that the github repo containing 0.4.5 is still up, and with no means of reporting issues. This isn't int80h's repo, it's just some rando who forked it to github and then forgot about it. Unfortunately, searches for gemini servers still return the unmaintained Awesome Gemini list on github, which links to a defunct site about gemserv, and then searches for gemserv turn up the github fork first. What a mess.
And because gemserv 0.6.x won't handle by existing certs and provides no guidance on the right way to create certs for it, I cannot recommend anybody use it.
gemserv 0.4.5 (Rust, last updated 5 years ago) DO NOT USE
https://github.com/GreatWizard/gemserv
- This almost built out-of-the-box. It required a small change to Cargo.toml to build on Ubuntu 24.04 using whatever rust/cargo I happened to have on-hand:
# Change this in Cargo.toml
#openssl = "0.10"
openssl = { version = "0.10.72", features = ["vendored"] }
- Once built, it supports cgi-bin, etc.
- It even supports "~/public_gemini" the way apache used to be used for serving userdirs ("~/public_html").
- It's still probably still not a great option for a novice, between needing to be able to compile the thing and opening up security concerns with cgi-bin. It can be done, but you need to trust your users or know how to handle security.
- GIANT WARNING: This has a huge path traversal security hole. Anybody can craft a url allowing it to read from anywhere on system running it, and it's not even that hard to do so.
gemserv v0.6.6 (Rust, last updated 3 years ago)
https://git.sr.ht/~int80h/gemserv
- This actually built out-of-the-box. They trimmed the dependencies to only things actually in use (it did not, in fact, need OpenSSL bindings).
- However, it doesn't use keys of the same format as the prior version, or even the same key both a-h/gemini and atlas successfully re-used. And the errors it produces when it fails are useless garbage:
This one means the key is the wrong format (e.g. EC vs RSA). Not that helpful.
thread 'main' panicked at src/lib/tls.rs:46:42:
removal index (is 0) should be < len (is 0)
This error means that it needs a "SAN extension" that matches the DNS, even if the CN is the domain. Again, not very helpful.
thread 'main' panicked at src/lib/tls.rs:55:14:
error loading key: General("The server certificate is not valid for the given name")
- I needed help from an LLM (ugh) to parse tls.rs and explain how to debug the certificate format and ultimately generate a new one (conversion alone was insufficient). In the end, this is how I generated a new cert that worked:
openssl req -x509 -newkey rsa:2048 -keyout gdorn.circuitlocution.com.key -out gdorn.circuitlocution.com.crt -days 3650 -nodes -subj "/CN=gdorn.circuitlocution.com" -addext "subjectAltName=DNS:gdorn.circuitlocution.com"
- Due to the poor README and poor error message legibility, I can't suggest gemserv for others. Maybe rust coders could work with it.