=> Part One
Once I got the basic thing up and running I started working on deployment a little. My little VPS runs Debian 11. I don't use Docker currently, because Docker doesn't (last time I checked) support cleanly integrating with nftables. Docker integrates with iptables and fiddles with your iptables rules in order to route the "exposed" ports on your containers.
Anyway, I use nftables on my little server, with a simple custom ruleset. Docker doesn't play nicely with this. Hence I don't use docker.
I do use systemd, and the stuff running on the server is all set up as systemd services. This starts stuff when the server boots. Systemd is capable of doing various containerisation/sandboxing actions as part of managing its services. It also has this thing called "socket activation", which means that you can set it up so that systemd itself will create the listening socket for you, and then pass it into your service as an already-open file descriptor.
Systemd can also open a file to pass to the service as its stdin (fd 0). In fact more recent systemd (v253+) lets you open other files to pass in as other file descriptors, but previously it only had a mechanism for redirecting stdin like this.
This means I can do a few things with my systemd service configuration to try to make the server a little more secure:
Anyway, here's the bucket.service:
[Unit] Description=Bucket (Gemini sever) After=network.target network-online.target Requires=network-online.target [Service] User=bucket Group=bucket Type=exec StandardInput=file:/var/lib/bucket/gem.twunk.uk.pem ExecStart=/usr/local/bin/bucket -d gem.twunk.uk --cert-pem-fd 0 --listen-sock-fd 3 -s /var/lib/serverdata/gem Restart=always WorkingDirectory=/var/lib/serverdata Environment=USER=bucket Environment=HOME=/var/lib/bucket Environment=RUST_LOG=info,bucket=debug TimeoutStopSec=5s LimitNOFILE=1048576 LimitNPROC=512 CapabilityBoundingSet= NoNewPrivileges=true PrivateDevices=true PrivateNetwork=true PrivateTmp=true PrivateUsers=true ProtectClock=true ProtectHome=true ProtectHostname=true ProtectSystem=strict RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX RestrictNamespaces=true SystemCallArchitectures=native # Set up a somewhat restricted filesystem view. # Note this doesn't even include the server's own config directory, # since it doesn't need to read any files from there by path. TemporaryFileSystem=/var:ro BindReadOnlyPaths=/var/lib/serverdata/gem [Install] WantedBy=multi-user.target
And here's the socket unit used for socket activation:
[Unit] Description=Bucket (Gemini sever) socket [Socket] ListenStream=1965 [Install] WantedBy=sockets.target
I'm not sure that I've got the right dependencies specified yet, and I haven't looked through the other possible socket unit options. And I haven't actually looked through all the service options either (there are so many).
Anyway, I don't hugely like this as it seems like a "start open and lock down many individual features" design rather than a "start with nothing and add just the pieces needed by the server" design. Nevertheless, it's hopefully a little more secure than it was. At least as a second line of defence.
text/gemini
This content has been proxied by September (3851b).