Skip to content

Self-hosting a Gemini capsule

Published: 2025-04-12 23:57 +1200
Last Modified: 2025-04-12 23:57 +1200


Background

I did this on a Raspberry Pi 4 Model B with the Debian 12 Bookworm distro. I bought the zkbro.com domain a while back, and done nothing with it. I have decided to utilise this by using gmi.zkbro.com (gmi as the subdomain). This keeps zkbro.com free for HTTPS if I ever get around to it. I use the helix text editor to edit files. This uses hx command to load the application. Replace with nano, vim, micro or whatever if something else is used.

Method

Install server molly-brown

I'm using molly-brown as my gemini server software simply because it was available in the apt package manager, and I had tried agate previously without success (though after being through all this rigmarole I might be more successful a second time around).

sudo apt install molly-brown

Configure molly-brown

Create a molly.config file:

hx ~/.config/molly-brown/molly.conf

Enter in the following configurations:

Hostname = "gmi.zkbro.com"
Port = 1965
CertPath = "/home/zkbro/.config/molly-brown/certs/cert.pem"
KeyPath = "/home/zkbro/.config/molly-brown/certs/key.pem"
DocBase = "/home/zkbro/gemini"
AccessLog = "/home/zkbro/.var/log/molly/access.log"
ErrorLog = "/home/zkbro/.var/log/molly/error.log"

Note: Gemini clients by default use port 1965.

Create TLS certificate and key files:

Thanks to advice from @bacardi55, I use Gemcert to create my server certificates which simplifies things. These are stored in my ~/.config/molly-brown/certs/ folder.

gemcert --server --domain --nowild gmi.zkbro.com

This creates the server certificates. I renamed them to the above cert.pem and key.pem, though I could've changed the molly.conf file instead. If I were to use openssl it would look something like this:

openssl req -x509 -newkey rsa:2048 -keyout ~/.config/molly-brown/certs/key.pem -out ~/.config/molly-brown/certs/cert.pem -days 3650 -nodes -subj "/CN=gmi.zkbro.com"

Allow ports through firewall

sudo ufw allow 1965/tcp

Set up domain

In my namecheap.com dashboard, go to Domain List --> Manage (zkbro.com) --> Advanced DNS.

Enable Dynamic DNS: true - Given I'm using a standard ISP this ensures the IP address I assign to this host are updated dynamically if they ever change (which they do). This also requires a Dynamic DNS client to pass current IP address to namecheap regularly.

Install ddclient:

sudo apt install ddclient

Follow the basic configuration steps in ddclient and when prompted use the password generated back in the namecheap dashboard.

Back in namecheap, under "Host Records" add a new record with the following information:

Set modem configurations

Login to the modem GUI in browser at http://192.168.1.1/. Login and password is on the bottom of the modem. I am currently using an old ISP modem (Slingshot) so steps below may look different on different modems.

Set up virtual server: Go to "Advanced Setup" --> "NAT" --> "Virtual Servers" and add a new server with the following configuration:

  • Use interface: ETH WAN
  • Custom Service: MollyBrown (or whatever)
  • Enable LAN Loopback: true (so I can access the site on my own LAN).
  • Server IP Address: 192.168.1."18" (replace "18" with whatever the server machine is. Check with ip a.)
  • Status: Enable
  • External Port Start: 1965
  • External Port End: 1965
  • Protocol: TCP
  • Internal Port Start: 1965
  • Internal Port Start: 1965

Start server via a systemd.service

First check if a systemd.service file doesn't exist already with the name I'm going to use:

sudo systemctl list-unit-files --type=service

Create .service file:

hx /usr/lib/systemd/system/molly-brown.service

Insert text:

[Unit]
Description=Molly-Brown Startup
Wants=network.target
After=syslog.target network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/molly-brown -c /home/zkbro/.config/molly-brown/molly.conf
Restart=on-failure
RestartSec=10
KillMode=mixed

[Install]
WantedBy=multi-user.target

Check service is created via status:

systemctl status molly-brown.service

Reload systemctl:

sudo systemctl daemon-reload

Enable service:

sudo systemctl enable molly-brown

Reboot to check all working.

Start and stop service by:

sudo systemctl start molly-brown 
sudo systemctl stop molly-brown

Disable autostart on reboot with:

sudo systemctl disable molly-brown

Resources