Gemini Protocol & Markup

The Gemini project defines a protocol and markup for serving documents. The server runs on port 1965 by default, it responds to gemini:// URLs, it uses TLS with client certificates, and it has a simple markdown that fixes the shortcomings of Gopher pages without adding much extra. There are GUI, terminal, and command line clients already available.

My own Gemini server is at gemini:// At least one web-based proxy has been made available by some kind soul, but I recommend using a proper client to get the full ‘other-worldliness’ experience. I’m only half-kidding here, because the separation of protocol makes Gemini potentially quite valuable – it’s a hostile environment for the crap that has devalued HTTP.

Seriously, not even inline images are supported. You have to choose to download an image, just like any other link, and that’s a matter of principle in the protocol design. Naturally, this is one of the things that will prevent it from ever evolving in the same way as the web, which is kind of the whole point. The principle is that you are in control of what you view.

So, if you want to publish stuff somewhere that’s separate from the world wide web, then this seems like a good alternative. The markdown is simple, yet gives headings, paragraphs, pre-formatted blocks, lists, and links. You literally type some words in a text file, and that’s your document ready to serve to the world. The immediacy and accessibility is refreshing (more so as I type this in WordPress, which is lagging in a browser on a fast 8-core Intel i7 laptop with 16GB of RAM).

There are barriers to entry – the most direct access for editing is via a shell, using a command line editor (I use Vim). I think this is well within the abilities of most people, but it will likely be daunting. The tilde communities seem to do a good job of making these things accessible, perhaps some of this could be applied to the fledgling Gemini community.

Below is a summary, but the full specification is at (it’s brief; it can currently be read in the time it takes to drink a coffee!)

# This would be an H1
## This would be an H2
### This would be an H3

=> Click me, I always exist on my own line.

> This line will show as a block-quote

* This is the first list item.
* This is another list item.

Pre-formatted blocks start and end with lines containing three back-ticks (```)

Anything else is just normal paragraph text, blank lines are always preserved.

The simplest Gemini client is Bash

Using ncat, it’s possible to make a request to a Gemini server with the following: –

echo -ne 'gemini://\r\n'|ncat --ssl 1965

This results in the following on stdout. The first line is the server’s response code, the rest is my index.gmi content: –

20 text/gemini
Hello from Gemini dot Susa dot Net

=> lua_api.txt The Official Minetest Lua API for modding.
=> lua_api.gmi The Official Minetest Lua API in Gemini markup.
=> xtract_lua_api.awk My awk script to extract sections of the API.

=> petz_functions.gmi a list of member functions in the Petz mod.
=> minetest_pointed_thing.gmi my explanation of above and under nodes.

=> hexchat_no_such_device_or_address.gmi Fix HexChat Disconnected (No such device or address)

My web site is at: -


I can be reached via SMTP at

So simple, this is a great initiative; decisions seem to have been well considered. I’m grateful! For more, see

A more featureful client: GemiNaut

A gemini (.gmi) page viewed in the GemiNaut browser.

For a server, I use agate gemserv:

I have tried agate, which I think serves static files for a single host. I then spent ages getting GLV-1.12556 running, which has lots of well considered features, but it required a lot of fiddling and hacking to get it to compile and run, so it might be too much of an admin hassle.

I have currently switched to gemserv, which seems to have similarly useful features (virtual hosts, CGI, home directories), but runs as a single binary like agate, and the Rust project builds easily with cargo. There are a couple of links to CGI examples at gemini:// if you want to see the server in action.

My server needs a private key and certificate (just issued locally using openssl).

# This command created a key and certificate that's valid for any host on
openssl req -x509 -newkey rsa:4096 -keyout key.rsa -out cert.pem -days 3650 -nodes -subj "/CN=*"

# This command lets you view your server's certificate as human-readable text for troubleshooting.
openssl x509 -in cert.pem -text

The following is some server output, including the command line that launched the server (in this case agate).

kevin@kakapo:~/gemini$ ./agate.x86_64-unknown-linux-gnu ./content/ cert.pem key.rsa
Got request for "gemini://"
Got request for "gemini://"
Got request for "gemini://"
Got request for "gemini://"
Got request for "gemini://"
Error: Os { code: 2, kind: NotFound, message: "No such file or directory" }
Got request for "gemini://"
Got request for "gemini://"
Error: Os { code: 2, kind: NotFound, message: "No such file or directory" }
Got request for "gemini://"

My index.gmi file to show a little markdown.

Hello from Gemini

=> petz_functions.gmi a list of member functions in the Petz mod.

You may check out my website at: -

-- Lua code to log my name minetest.log("Kevin")
Kevin said:
> This is quite a useable format to document Minetest mods. I think I'll use this in future.

### I'm signing off now
Good day to you sir. I bid you farewell.

If you have a gemini client, you can view this at gemini://

Leave a Reply

Your email address will not be published. Required fields are marked *