-- Leo's gemini proxy

-- Connecting to esa.prk.st:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini; lang=en

Gemserv Gemini server on Alpine Linux

Categories: [IT] [Gemini] [Linux]

Back home


Gemserv[1] is a Rust-based Gemini server with a lot of nice features. It's a bit more complex than some competitors, but after Jetforce failed me[4], I had to migrate. So here is the (short) tale of my Alpine Linux Gemserv basic setup.


About Alpine Linux


Copy/paste from my previous article. Sue me.


Alpine Linux[2] is a stripped-down Linux distro mostly used for lightweight virtual machines or containers (LXC, docker, etc.). It is pretty rough compared to mainstream distros like Ubuntu or even Arch, having a different set of base utils:


Libc is not provided by glibc as usual but by musl, which is a low-footprint implementation, lacking some exotic features. As such, it's not 100% compatible with some pieces of software depending on glibc features.

Standard binaries (mostly POSIX CLI utils) are provided by BusyBox, a compact implementation lacking some GNU extensions to POSIX requirements.

Init system is not Systemd as with the vast majority of current distros but by OpenRC, a BSD-inspired init system.

Package system is not deb or rpm but apk (not related to Android packages).


Being a lightweight distro, many "implied" requirements for running about anything must be considered and specific actions taken.


About Gemserv


To be honest, I don't know much about Jetforce except that it works. It's a pretty mainstream server with frequent updates (most of those I've found haven't seen a commit in months). It is based on Rust ecosystem and gets a cargo deployment shortcut which comes really handy. Some system dependencies must be manually installed before cargo can do its job:


Rust and Cargo (off course).

Openssl for TLS stuff.


Installation steps


As Alpine Linux is a lightweight distro usually deployed on docker, containers, etc. It is assumed that no other service (except SSH) will be running on this server.


Installing Alpine Linux


Just follow the doc, nothing to see here. Just make sure to have up-to-date packages. It might be a good idea to switch repositories to rolling-release mode (there is more information about this on Alpine wiki).


# apk update
# apk upgrade

Install required packages


There are quite a lot of dependencies to install. It is mostly related to Rust, Cargo, and some build dependencies. Here is the full install command:


# apk add git build-base gcc libffi libffi-dev \
          openssl openssl-dev ca-certificates openssh \
          rust cargo

Install Gemserv


We will install Gemserv in /opt/gemserv/. Gemserv build will be done in user home directory and binary moved to /opt/gemserv/bin afterwards.


Build command is pretty simple:


# mkdir -p /opt/gemserv/bin
# cd
# cargo install gemserv

If compilation went good, you can then move binary to its final destination.


# mv .cargo/bin/gemserv /opt/gemserv/bin/

Setup environment for Gemserv


First, we'll create config directory, data directories, a new user for our new service and a group to manage gmi files ownership:


# mkdir -p /var/gemini/public
# mkdir /etc/gemserv
# adduser -S -h /var/gemini gemini
# addgroup -S gemini

Next we'll make sure Gemserv can read but not modify anything in our public directory:


# cd /var/gemini/
# chown root:nogroup .
# chown root:gemini pub
# chmod -R g+w .

Any Gemini server needs a keypair and certificate. Gemini doesn't care about self-signed certificates, so we'll take advantage of that. If you want to get better, cleaner keys, feel free to do so. Keypair and certificate generation is done this way (securing directories as we go. Don't forget to replace "esa.prk.st" with your server FQDN. Beware, due to rustls dependency (and not OpenSSL which is a bit more lenient), you *NEED* a subjectAltNAme on your certificate for it to be accepted as valid[3].


# mkdir -p /etc/gemserv/tls/
# chown gemini:root /etc/gemserv/tls
# chmod 500 /etc/gemserv/tls
# cd /etc/gemserv/tls/
# openssl req -newkey rsa:2048 -nodes \
    -keyout esa.prk.st.key -nodes -x509 \
    -out esa.prk.st.crt -subj "/CN=esa.prk.st" \
    -addext "subjectAltName = DNS:esa.prk.st" \
    -days 365
# chown gemini:root /etc/gemserv/tls/esa.*
# chmod 500 /etc/gemserv/tls/esa.*


We're almost done. Next step is setting up a user that will be allowed to update /var/gemini/pub (by adding this user to "gemini" group). Replace "whatever" with your desired username:


# adduser -G gemini whatever


Configuration


First, we'll create a configuration file based on the nice sample file provided with gemserv source tree at /etc/gemserv/config.toml. I won't need anything fancy, like multihost or CGI, so mine looks like this:


interface = [ "0.0.0.0:1965" ]
log = "info"

[[server]]
hostname = "esa.prk.st"
dir = "/var/gemini/pub"
key = "/etc/gemserv/tls/esa.prk.st.key"
cert = "/etc/gemserv/tls/esa.prk.st.crt"
# disable CGI and user directories
cgi = false
usrdir = false

Finally, we'll create a new service configuration. There is one provided with gemserv sourcetree, but it doesn't fit my need, so here is mine, at /etc/init.d/gemserv


#!/sbin/openrc-run

name=$RC_SVCNAME
description="Gemserv Gemini server"
command="/opt/gemserv/bin/gemserv"
command_user="gemini"
command_args="${GEMSERV_CONFIG:-/etc/gemserv/config.toml}"
command_background="true"
pidfile="/run/$RC_SVCNAME/$RC_SVCNAME.pid"
output_log="/var/log/$RC_SVCNAME/$RC_SVCNAME.log"
error_log="/var/log/$RC_SVCNAME/$RC_SVCNAME.err"

depend() {
  need net
  use dns
}

start_pre() {
  checkpath --directory --owner $command_user:gemini --mode 0755 /var/log/$RC_SVCNAME
  checkpath --directory --owner root:gemini --mode 0755 /run/$RC_SVCNAME
}

Test it all


You'll need to create a basic index.gmi file in /var/gemini/public as you new user (the one in gemini group, not root nor gemini itself) :


$ echo test > /var/gemini/public/index.gmi

Now time to start it all:


# rc-update add sshd
# rc-update add gemserv
# service sshd start
# service gemserv start

Your server should now be up&running. Your index page should be available using your Gemini client. If anything went wrong, you might find more information in /Var/log/gemserv/ directory.


Next steps


Log management is currently not handled by logrotate or other tools, please configure it as you see fit.

This setup is "mono-user", if you want to host multipe capsules, you'll have to add stuff to your gemserv config.

Setting up some access filter like failtoban may be a good idea to prevent some issues.


Links


[1] Gemserv repository

[2] Alpine Linux

[3] rustls and subjectAltName

[4] My previous setup with Jetforce

-- Response ended

-- Page fetched on Mon May 13 02:16:52 2024