21 Dec 2017

Gophermoon 0.1 - a Gopher-Server in Lua – Part 1


I'm writing a simple Gopher-Server in Lua. I want to play around with the Gopher Protocol, Systemd and Linux-Container and learn some Lua-Programming on the way.

Gopher is a document retrieval protocol that had been around the same time the world-wide-web was born, but it is much simpler that HTTP and HTML. It works with plain text and directories, and the protocol on the wire is ultra-simple.

The server will be named gophermoon.

Gopher (the protocol) is documented in RFC 1436 with some extension defined as Gopher+ in

Preparing systemd Socket-Activation

In the beginning, I will use Systemd to do the network part of the protocol (listening on port 70). The Lua program will just read and write to standard-input and -output.

Here are the Service-Unit and the Socket-Activation-Unit for Systemd. The Gophermoon Service is in /etc/systemd/system/gophermoon@.service

Description=GopherMoon Gopher Server in La

ExecStart=-/bin/lua /usr/local/sbin/gophermoon
  • and the Socket-Unit is stored in /etc/systemd/system/gophermoon.socket
Description=GopherMoon - Gopher-Server in Lua



the Gopher-Server

Below is a very simple Lua-Script implementing a Hello-World Gopher-Service. It just emits the lines for a static welcome message.

A Gopher-Server waits for a connection and reads the path the client sends (ignored for now). Then it writes the Gopher-Menue out. Each Menu-Line has five fields. The first field is 1 character wide, the other fields are separated by the tabulator character (/t). Each line is terminated by a CRLF sequence.

A line with a single dot "." marks the end of the communication, server and client will close the connection.

--- Gopher Moon Version 0.1
--- a simple Gopher Server in Lua
--- with some help from Systemd socket activation

path =
io.write("iWelcome to GopherMoon @\t\\t70\r\n")

starting the thing …

Systemd needs to know about the new unit-files, so we do a reload:

systemctl daemon-reload

Now we can enable and start the socket (no need to start/enable the service, as it will be started once a connection to Port 70 is made).

systemctl enable --now gophermoon.socket

The open socket on the Gopher-Port 70 now visible:

# lsof -i
systemd       1    root   40u  IPv6 3989631      0t0  TCP *:gopher (LISTEN)

And test …

Gopher is simple, it can be tested with the telnet command:

# telnet 70
Connected to
Escape character is '^]'.

iWelcome to GopherMoon @        70
i----------------------------------------        70
Connection closed by foreign host.


Figure 1: test with the lynx


Figure 2: test with OmniWeb (MacOS X)

Other posts
Creative Commons License by Carsten Strotmann is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License .