💾 Archived View for gsthnz.com › posts › 2020-11-25-writing-gemini-software.gmi captured on 2023-11-04 at 11:11:39. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2022-06-03)

-=-=-=-=-=-=-

Writing gemini software for fun and games

In my last post [^1] 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.

Hello Gemini

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 [^2] is my gemini server. For this I took some

inspirations on Drew DeVault's gmnisrv [^3], 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.

Satellite

Drew DeVault's gmnisrv

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:

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 [^4] 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.

gssg

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 [^5] and for me

to grok Go templates, and to my amazement, Go templating is really simple and

powerful.

kiln

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!

---

Writing gemini software for fun and games was published on 2020-11-25

Go back to the main page

The content on this site is licensed under CC-BY-SA-4.0