Life inside a machine

Working with Elpher

You're viewing a Gemini article on the web

It's much better to view it on Gemini!

I like Emacs quite a lot. There's something about the "everything app" (the real one, Elon) that can be quite liberating. However, Emacs has quite a steep learning curve. This, combined with the insistence on "self-documentation" can make using the software quite a challenge, particularly for those of us that don't work in elisp all that much.

Recently I took some time to sit down and... read some code. And some changelogs. All in the pursuit of a simple goal: making Elpher work with client certificates.

Elpher does support client certificates and has a really nice workflow for adding new ones. It also supports associating these certificates with specific sites so you don't need to be prompted. Sounds fantastic, but this second feature isn't very well documented nor is it particularly obvious. Really, it needs to be documented with an example.

Since I've worked this out and am a professional technical writer, I figured I'd give a short and sweet overview of the process of setting up the elpher-certificate-map.

Set up your certificate directory

As I mentioned, Elpher already does certificate generation and storage. Great. However, there's a wrinkle.

Once a certificate is selected, it will be used for all subsequent gemini requests involving URLs beginning with the URL for for which the certificate was created. It is immediately ``forgotten'' when a TLS connection to a non-matching URL is attempted.

For a site like Station, this means that your certificate is immediately forgotten once it's created because you get rerouted to a different subpath after login. Whoops.


So the first thing we need to do is create ourselves a directory in which to store our certificates. This is a place where you can put existing certificates or let Elpher store its certificates. It's up to you. I use ~/.local/share/elpher.

$ mkdir ~/.local/share/elpher

Next, customize the elpher-certificate-directory variable in your config.el or config.org file (or whatever you use).

(setq elpher-certificate-directory "~/.local/share/elpher")

Great. Now, whenever you save a persistent certificate, you can find it in this folder.

Generate a certificate for the site

Elpher discards certificates immediately after creating them if it detects a URL mismatch. This means that even if you created a persistent certificate for Station, the certificate was deleted the moment you tried to login. Not great.

To get around this, I generate the certificates using openssl on the command line and just stick the certificates in my elpher-certificate-directory. Elpher recognizes and certificates ending with .crt, and any keys ending with .key. So you can create your certificates with a given name and immediately access them with Elpher provided you use these extensions.

Here's an example of how to create a cert pair for Station with the name "Station":

$ openssl req -new -subj "/CN=<username>" -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -days 1825 -nodes -out ~/.local/share/elpher/Station.crt -keyout ~/.local/share/elpher/Station.key

Replace <username> with your Station username (or whatever you like). I just use this for neatness because some sites do read this information.

This command creates the following:

├── Station.crt
├── Station.key

Great. Now, if I open up Elpher and look at my keys, I'll see one named "Station".

Map your certificates

Okay, so now we have a certificate. That was the more understandable bit of the process. What got me a bit more confused was the latest feature: the elpher-certificate-map. Once I sat down and looked at it a bit, though, it started to make sense.

Basically, this is just a value of mapped strings that represent:

Given all that, we just need to specify this in the config.el/config.org file.

(setq elpher-certificate-map '(
      ("gemini://station.martinrue.com" "Station")))

Now go back to Elpher and log in to Station. Hopefully, you'll find it works!

Some sites use the site root as the prefix, others use a subpath. It depends on how the auth mechanism is set up. For example, astrobotany uses a subpath.

(setq elpher-certificate-map '(
      ("gemini://astrobotany.mozz.us/app" "Astrobotany")))


Others still simple don't work with this mechanism, such as Bubble. I don't know why this doesn't work, but I'd imagine it's just because it's doing something more advanced with the certificate than Elpher anticipates.


Why was this hard?

Without a written example, it wasn't that easy to work out:

An example in the documentation would have made this process a lot easier, but hopefully this example helps someone else out.