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:
- 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:
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