> cd /

How to host a shared gemini server?


Today, I set up a secure multi-user gemini server, because I'd like to support this protocol. I wish more people can do the same, so here how I did it.

Multi-user gemini server on


We will use an OpenBSD system, SFTP chroot and vger gemini server. ("secure", we said).

Users capsules will be available at gemini://domain.tld/user/.

I choose "/home/gemini" as chroot because "/home" is my biggest slice. Feel free to use another path.

Only Pubkey authentication will be allowed : easier and more secure.

Group "gmiusers" is used to identify who must be chrooted.

Before going any further, create this group:

# groupadd gmiusers

SFTP configuration

Create chroot. Keep in mind permissions are crucial.

# mkdir /home/gemini
# chown root:gmiusers /home/gemini
# chmod 750 /home/gemini
# mkdir /home/gemini/home

/home/gemini/home will store users directories.

chmod is 750 because :

/etc/ssh/sshd_config :

Match Group gmiusers
        ChrootDirectory /home/gemini/
        ForceCommand internal-sftp
        AllowTcpForwarding no
        X11Forwarding no
        PasswordAuthentication no

Then reload ssh:

# rcctl reload sshd

vger gemini server setup

Download/compile/install vger

Create a dedicated user for vger. It must belong to "gmiusers" group to be able to read files to serve:

useradd -G gmiusers -s /sbin/nologin _gemini_server

Edit /etc/inetd.conf:

11965 stream tcp nowait _gemini_server /usr/local/bin/vger vger -d /home/gemini/home

Edit /etc/relayd.conf:

log connection
ext_ip4 = "xx.xx.xx.xx."
ext_ip6 = "xxxx:xxxx:xxxx:xxx::xxx"

tcp protocol "gemini" {
        tls keypair domain.tld

relay "gemini" {
        listen on $ext_ip4 port 1965 tls
        protocol "gemini"
        forward to port 11965
relay "gemini6" {
        listen on $ext_ip6 port 1965 tls
        protocol "gemini"
        forward to port 11965

Notice relayd will look for tls certificates for "domain.tld" with the above configuration. This means /etc/ssl/domain.tld.crt and /etc/ssl/private/domain.tld.key.

gemini requires TLS. To get a certificate, you can use acme-client or generate a self-signed one. This is out of the scope of this page.

Of course, enable and start these daemons:

# rcctl enable inetd relayd
# rcctl start inetd relayd

Add an user

You must create the user directory, set permissions, and add ssh pubkey so the user can identify. I do it with the script below. It will ask to paste user pubkey after creating it.

# addgmiuser <user>

if [ $# -lt 1 ]; then
	echo "usage: $0 user"

userinfo "${user}" && (echo "user already exists" || exit 1)

mkdir -p "${CHROOT}"
useradd -G gmiusers -s /sbin/nologin -m "${user}" || exit 1
install -d -o ${user} -g gmiusers -m 750 "${dir}"

while [ -z "${sshkey}" ] ; do
    echo "enter ssh pubkey"
	read -r sshkey

echo "${sshkey}" >> /home/${user}/.ssh/authorized_keys

# create an index file so the user see it works
echo "# ${user}'s capsule" > "${dir}/index.gmi"
echo "write here" > "${dir}/index.gmi"
chown "${user}":"${user}" "${dir}/index.gmi"

The end

Now users can start a sftp session, they are locked in the chroot and automatically in their own directory. They just have to upload gmi files and it's done :)

$ sftp -i ~/.ssh/sshkey user@domain.tld
Connected to domain.tld.
sftp> pwd
Remote working directory: /home/user

Something to say?

πŸ“§ Send a comment

πŸ“« Subscribe to get answers

πŸ“š Read archives.

πŸ’¨ Unsubscribe