ShadowKat Studios
Blog
Projects
About

systemd Socket Activation for Game Server Containers

I play a reasonably wide variety of (mostly sandbox) games; most recently, Starbound. The issue with sandbox games is that they tend to use a lot of memory, and I only have so much to go around. Today I went ahead and sorted out how to start and stop game servers on demand. In theory, this could also be used for any other service that communicates over TCP.

The situation

I have a Starbound server in an LXC container, debian11-starbound, running on my host, asakura. This container is started and stopped via systemd, as lxc@debian11-starbound. The actual Starbound server is started by systemd also, by a unit in the container itself.

Sockets and services

On debian11-starbound, I already have a template unit to start the server, as /etc/systemd/system/starbound-server@.service.

[Unit]
Description=StarboundServer
After=network.target
[Service]
WorkingDirectory=/home/sbserver/%i/linux
User=sbserver
Group=sbserver
Type=simple
ExecStart=/home/sbserver/%i/linux/starbound_server
RestartSec=15
Restart=always
KillSignal=SIGINT
[Install]
WantedBy=multi-user.target

In /home/sbserver I have an arbitrary set of server instances, and they can be enabled with, for example, systemctl enable starbound-server@sks1.

On asakura, I create /etc/systemd/system/starbound-proxy@.service, to handle the actual proxying.

[Unit]
; After= and Requires= makes sure that the proxy starts after the LXC container has been (forced to) start
Requires=lxc@debian11-starbound.service
After=lxc@debian11-starbound.service
; BindsTo= ensures that if the container stops of its own volition, the proxy stops running and will be
; able to start the container again.
BindsTo=lxc@debian11-starbound.service

[Service]
ExecStart=/lib/systemd/systemd-socket-proxyd --exit-idle-time=60m starbound.sks.local:%i
ExecStop=/usr/bin/systemctl stop lxc@debian11-starbound

The two important parts here are ExecStart and ExecStop. ExecStart uses systemd-socket-proxyd to forward a port to the container itself, with the argument to exit after an hour if nobody is using it. ExecStop will take over at that point, and tell the container to shut down.

Last of all, it’s tied together with /etc/systemd/system/starbound-proxy@.socket, which is almost pure boilerplate.

[Socket]
ListenStream=%i
[Install]
WantedBy=sockets.target

Then, as my Starbound server is running on port 21025, I can disable the LXC container service, and start/enable starbound-proxy@21025.socket.

The last thing to do is to forward the ports from the internet to my main server, and let it do its thing.

Limitations and further refinements

Shout out to N33R for suggesting some refinements that made it into this.

By Izaya
2022-02-20 21:04 +1100

Tags: tech software systemd

<---
Fediring
--->

© ShadowKat Studios
The software used to generate this page is licensed under the Mozilla Public License version 2 and can be found here