💾 Archived View for dyn.fussycoder.ninja › personal › linux › geminiserver.gmi captured on 2022-07-16 at 14:23:20. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

Setting up a gemini server

For security reasons, I stopped running a gemini server on my main PC, and opted instead to use an old Raspberry Pi 3 I had found instead.

The idea is that this server would contain only non-critical files that aren't a huge deal if they were to be leaked online.

Security measures that I hope to implement are:

The outcome is that this is, hopefully, slightly more secure than a typical gemini server hosted on a home PC.

Installing Alpine

I installed the aarch64 version, but I had to figure out how to install this without a keyboard or display connected at all.

It turns out this is quite well documented on the wiki.

I knew that this system supported aarch64 because my board is the "B+" version, previous models are probably not going to support aarch64.

Downloads for aarch64

Raspberry Pi Headless Installation

Set up a root account with a secure password.

Then of course, set up a "gemini" server account and an admin account. We will use these to actually run the service later.

Installing rsync

This is... Remarkably trivial:

apk add rsync

Installing bubblerwrap

Again, very simple. I like alpine!

apk add bubblewrap

Using it is pretty simple, but one gotcha is that the program interpreter must exist, so in alpine, that means ensuring that `/lib` exists.

Example:

bwrap --unshare-all --ro-bind /lib /lib --ro-bind /bin /bin ash

Another example is provided by "ericonr" at:

ericonr's example of running gemini in bubblewrap

Configuring ssh

ssh is *constantly* being attacked on the internet, so it is sensible to lock it down tight, by editing /etc/ssh/sshd_config

Configuring a build environment

This is less trivial, we ideally don't want the build system installed on the rpi system.

For Go, this is very very simple:

env GOOS=linux GOARCH=arm64 go build

For haskell, this is far less simple. We need to set up an arm64 emulator and install haskell in there.

Update: Actually setting up haskell on an aarch64 musl based linux system is non-trivial.

Starting the gemini server:

Writing an init system service is documented here for alpine linux:

Writing Init Scripts

And even better, the authoritative docsa are at:

OpenRC service script guide.

With that in mind, the following seems sensible:

#!/sbin/openrc-run

command=/usr/bin/bwrap
command_args="--unshare-all --share-net --ro-bind /home/gemadmin/bin /bin --ro-bind /home/gemadmin/certs /certs --ro-bind /home/gemadmin/public /public /bin/gmifs -cert /certs/cert.pem -key /certs/key.rsa
pidfile="/var/run/${RC_SVCNAME}.pid"
output_log="/var/log/${RC_SVCNAME}"
error_log="/var/log/${RC_SVCNAME}.error"
command_background=true
command_user="gemini:gemini"

In general, everything is owned by gemadmin, but run by gemini, to try and keep the privilages as separate as possible.

The logs do need to be owned by "gemini:gemini"

The user running bwrap and gmifs is gemini, gemadmin is never used by the service.

(We use gemadmin to set up the files, etc, though, but not for running anything).

Other resources

Linux Hardening Guide