gsthnz's blog

Writing gemini software for fun and games

In my last post I’ve written about me jumping in the Gemini bandwagon and how I was really excited about it. In the past few weeks I wrote a Gemini server and a Gemini static site generator, both of them being currently in use for my gemlog.

This post is a bit of a status update and some cool stuff I’ve learned while coding my Gemini server and SSG.

Satellite

Satellite is my gemini server. For this I took some inspirations on Drew Devault’s gmnisrv, the main one is that the sysadmin should not need to manage TLS certificates. Since the gemini spec recommends the use of TOFU as a authentication method for TLS, there’s no need to have manual interaction in that regard. That way, we can just point satellite to a certificate directory in the filesystem and satellite will manage everything for me.

Turns out that satellite was really easy to make in Go. The only external library I needed was for parsing the toml configuration file. The rest of it was excellently provided by the stdlib.

Go provides a very good TLS library, so I was able to code a simple gemini server in a few minutes.

This is how simple it is to make a valid dummy gemini server in go:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main

import (
    "crypto/tls"
    "net"
)

func main() {
    // Load certficates
    cer, err := tls.LoadX509KeyPair("server.crt", "server.key")
    if err != nil {
        panic(err)
    }
    config := &tls.Config{Certificates: []tls.Certificate{cer}}
    // Listen on 1965 port
    ln, err := tls.Listen("tcp", ":1965", config)
    if err != nil {
        panic(err)
    }
    defer ln.Close()

    for {
        // Start accepting connections
        conn, err := ln.Accept()
        if err != nil {
            continue
        }
        // Return hello world to every request
        go handleConnection(conn)
    }
}

func handleConnection(conn net.Conn) {
    defer conn.Close()
    conn.Write([]byte("20 text/gemini\r\n# Hello World"))
}

Satellite also supports multiple virtual hosts and it’s really fast!

I do plan to add regex support for URL routes in the config and a form of CGI support in the future.

gssg

gssg is my static site generator. I’ve mainly started working on this because I like the way Hugo abstracts away the site structure and I only have to worry about the content of my blog posts.

Although the gemini content format is much, much simpler than HTML, and it’s much easier to maintain manually, I’ve wanted something on Gemini to create my index pages and add a little footer on all of my pages.

And that’s pretty much what gssg does, it initializes a gemini site with a basic default template, in which you can put content on the posts/ folder, and it will be automatically linked by date on the index page.

This started as alternative to kiln and for me to grok Go templates, and to my amazement, Go templating is really simple and powerful.

I’ve only used the text/template package for building gemini files, but there’s also a html/template which I haven’t played around with yet.

gssg was a one-day project, there’s a lot of rough edges and it needs a code cleanup, but it’s working nicely for my gemlog.


And that’s it, I had a lot of fun working on these projects and learned a lot of Go in the process. However, maybe I should start adding content to my gemini pages instead of writing software for it.

Until next time!


Have questions or comments? Use my public inbox by sending a plain text-email to ~gsthnz/public-inbox@lists.sr.ht