How to host a shared gemini server?
2020-12-31T21:07:51Z
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 si3t.ch
Forewords
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 :
- "7" : owner can read, write and cd in this directory
- "5" : group gmiusers can read in this directory. It is necessary so the gemini server can serve files :)
- "0" : Others can't access this directory at all.
/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
https://tildegit.org/solene/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 127.0.0.1 port 11965 } relay "gemini6" { listen on $ext_ip6 port 1965 tls protocol "gemini" forward to 127.0.0.1 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.
https://www.romanzolotarev.com/openbsd/acme-client.html
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.
#!/bin/sh # addgmiuser <user> if [ $# -lt 1 ]; then echo "usage: $0 user" exit fi CHROOT=/home/gemini/ user="$1" dir="${CHROOT}/home/${user}" sshkey="" 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 done 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" exit
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