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.
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.
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.
Shout out to N33R for suggesting some refinements that made it into this.