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).
Configure molly-brown
Create a molly.config file:
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.
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
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:
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:
- Type: A + Dynamic DNS
- Host: gmi
- Value: My current public IP address
- TTL: Automatic
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:
Create .service file:
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:
Reload systemctl:
Enable service:
Reboot to check all working.
Start and stop service by:
Disable autostart on reboot with: