Skip to content

Commit

Permalink
Add systemd instantiated service file and per-session environment files
Browse files Browse the repository at this point in the history
Currently the management scripts allow for only a single instance of the
minecraft server to be run, but it's actually not hard at all to support
multiple instances. This commit makes the following changes:

  - Adds a new systemd service file, `[email protected]`, which
    is an instantiated variant that overrides `SERVER_ROOT` and
    `SESSION_NAME`
  - Modifies `minecraftd.sh` to support sourcing an `environment` file
    from `SERVER_ROOT`, in addition to the existing system-wide file
    `/etc/conf.d/GAME`.
  - Instantiated versions of the minecraftd-backup service and timer.

The one potentially unsafe assumption I'm making is that the
`MAIN_EXECUTABLE` lives in the original compile-time `SERVER_ROOT`,
which I know is the case for at least papermc and spigot. For
installations where this is not the case, the environment file can
override `SERVER_START_CMD`.

The intended use case for this change is fairly common: using the same
package to run multiple instances of a minecraft server on a single
host. This would commonly be seen with, for example, multi-server
bungeecord deployments.
  • Loading branch information
fuhry committed May 18, 2022
1 parent 703d029 commit cb7503b
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 2 deletions.
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ datarootdir = $(prefix)/share
mandir = $(prefix)/share/man
man1dir = $(mandir)/man1

SOURCES = minecraftd.sh.in minecraftd.conf.in minecraftd.service.in minecraftd.sysusers.in minecraftd.tmpfiles.in minecraftd-backup.service.in minecraftd-backup.timer.in
SOURCES = minecraftd.sh.in minecraftd.conf.in minecraftd.service.in minecraftd@.service.in minecraftd.sysusers.in minecraftd.tmpfiles.in minecraftd-backup.service.in minecraftd-backup@.service.in minecraftd-backup.timer.in minecraftd-backup@.timer.in
OBJECTS = $(SOURCES:.in=)

GAME = minecraft
Expand Down Expand Up @@ -92,6 +92,9 @@ install:
$(INSTALL_DATA) -D minecraftd.service "$(DESTDIR)$(libdir)/systemd/system/$(INAME).service"
$(INSTALL_DATA) -D minecraftd-backup.service "$(DESTDIR)$(libdir)/systemd/system/$(INAME)-backup.service"
$(INSTALL_DATA) -D minecraftd-backup.timer "$(DESTDIR)$(libdir)/systemd/system/$(INAME)-backup.timer"
$(INSTALL_DATA) -D [email protected] "$(DESTDIR)$(libdir)/systemd/system/$(INAME)@.service"
$(INSTALL_DATA) -D [email protected] "$(DESTDIR)$(libdir)/systemd/system/$(INAME)[email protected]"
$(INSTALL_DATA) -D [email protected] "$(DESTDIR)$(libdir)/systemd/system/$(INAME)[email protected]"
$(INSTALL_DATA) -D minecraftd.sysusers "$(DESTDIR)$(libdir)/sysusers.d/$(INAME).conf"
$(INSTALL_DATA) -D minecraftd.tmpfiles "$(DESTDIR)$(libdir)/tmpfiles.d/$(INAME).conf"

Expand Down
15 changes: 15 additions & 0 deletions [email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[Unit]
Description=@GAME@ Server World Backup
After=local-fs.target

[Service]
Type=oneshot
Environment=SERVER_ROOT=@SERVER_ROOT@/servers/%i
Environment=BACKUP_DEST=@SERVER_ROOT@/servers/%i/backup
Environment=SESSION_NAME=@GAME@-%i
ExecStart=/usr/bin/@INAME@ backup
User=@GAME_USER@
Group=@GAME_USER@

[Install]
WantedBy=multi-user.target
10 changes: 10 additions & 0 deletions [email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[Unit]
Description=Daily @GAME@ Server Backup

[Timer]
OnCalendar=daily
AccuracySec=5min
Persistent=true

[Install]
WantedBy=multi-user.target
6 changes: 5 additions & 1 deletion minecraftd.sh.in
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ declare -r GAME="@GAME@"
[[ -n "${GAME_COMMAND_DUMP}" ]] && declare -r GAME_COMMAND_DUMP=${GAME_COMMAND_DUMP} || GAME_COMMAND_DUMP="@GAME_COMMAND_DUMP@"

# Variables passed over the command line will always override the one from a config file
source /etc/conf.d/"${GAME}" 2>/dev/null || >&2 echo "Could not source /etc/conf.d/${GAME}"
for path in "/etc/conf.d/${GAME}" "${SERVER_ROOT}/environment"; do
if test -r "$path"; then
source "$path" || (echo "Could not source ${path}" >&2)
fi
done

# Preserve the content of IDLE_SERVER without making it readonly
[[ -n ${tmp_IDLE_SERVER} ]] && IDLE_SERVER=${tmp_IDLE_SERVER}
Expand Down
20 changes: 20 additions & 0 deletions [email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[Unit]
Description=@GAME@ Server - %i instance
After=local-fs.target network.target multi-user.target

[Service]
Type=forking
Environment=SERVER_ROOT=@SERVER_ROOT@/servers/%i
Environment=BACKUP_DEST=@SERVER_ROOT@/servers/%i/backup
Environment=SESSION_NAME=@GAME@-%i
Environment=MAIN_EXECUTABLE=../../@MAIN_EXECUTABLE@
# create the "servers" directory followed by the instance directory
ExecStartPre=/bin/bash -c "/bin/test -d @SERVER_ROOT@/servers || /bin/install -d -m 0750 -o @GAME_USER@ -g @GAME_USER@ @SERVER_ROOT@/servers"
ExecStartPre=/bin/bash -c "/bin/test -d @SERVER_ROOT@/servers/%i || /bin/install -d -m 0750 -o @GAME_USER@ -g @GAME_USER@ @SERVER_ROOT@/servers/%i"
ExecStart=/usr/bin/@INAME@ start
ExecStop=/usr/bin/@INAME@ stop
User=@GAME_USER@
Group=@GAME_USER@

[Install]
WantedBy=multi-user.target

0 comments on commit cb7503b

Please sign in to comment.