Compare commits

..

123 Commits

Author SHA1 Message Date
Toboshii Nakama
2b7f923865 Add ttf-dejavu to package list (#556) 2020-06-14 11:20:37 -05:00
Geoff Bourne
80099ad63d Added debug option to dump managed server.properties 2020-06-14 11:14:11 -05:00
Geoff Bourne
b273bf2947 Removed cirleci config 2020-06-10 18:50:40 -05:00
Geoff Bourne
2241ba8819 Added build image action 2020-06-10 18:43:07 -05:00
Luis Marroquin
3cf58e3caf Fixed docker-compose-proxied.yml link (#554) 2020-06-10 06:56:07 -05:00
Geoff Bourne
450442a916 Enhanced WORLD to support path to zip file 2020-06-06 20:41:09 -05:00
Geoff Bourne
8c866bd17d Un-flipped forge and FTBA examples compose files 2020-05-31 18:46:17 -05:00
Geoff Bourne
8deaf1850b Fixed TYPE=FTBA in example compose file 2020-05-31 18:43:40 -05:00
Geoff Bourne
6da2aca975 Updated examples for FTBA support 2020-05-31 18:40:13 -05:00
Geoff Bourne
11989d17e3 Updated README for FTBA server type support
For #524
2020-05-31 18:34:21 -05:00
Geoff Bourne
5aa6e5c2a9 Refactored autopause setup into its own start-file (#545) 2020-05-25 10:20:14 -05:00
Kevin Klinemeier
825398f4d4 removed version entries except for the version section (#541)
Co-authored-by: BuildTools <unconfigured@null.spigotmc.org>
2020-05-23 17:57:11 -05:00
Geoff Bourne
ccac249c01 Added server-start.sh support for CF modpacks
Fixes #540
2020-05-23 09:55:38 -05:00
Michael Kirsch
f2806d9335 Autopause logs (#539) 2020-05-23 09:15:10 -05:00
Geoff Bourne
b11806e341 Consolidated armv7 branch into multiarch 2020-05-21 20:59:13 -05:00
Michael Kirsch
71a7afab17 Autopause functionality (#531) 2020-05-20 08:17:58 -05:00
Mitchell Skaggs
ede58d9159 Update flags as of 5/2/2020 (#534) 2020-05-18 19:55:32 -05:00
Geoff Bourne
b271b529ea Improved handling of building bukkit vs spigot 2020-05-11 20:14:01 -05:00
Geoff Bourne
d24690ab8c Used versionLessThan to simplify buildSpigotFromSource check 2020-05-11 18:54:28 -05:00
hejamu
89fa3ff8fe Short hotfix until version helper function is done (#520) 2020-05-11 18:53:29 -05:00
Geoff Bourne
5c0a3a64ab Upgraded mc-server-runner to 1.4.3 to fix curse instance mod cleanup 2020-05-08 18:01:37 -05:00
Geoff Bourne
b66629b951 Added helper script for building multiarch image 2020-05-06 16:08:05 -05:00
Sharif Nassar
de866a322f Add resource-pack-sha1 to server.properties (#519) 2020-05-03 16:30:12 -05:00
orblazer
79ac19937f Add possibility to use secrets in environment variables (#512) 2020-04-28 19:07:45 -05:00
Gabriel Oliveira
08e8fcdc7c Add explanation for timezone config on README (#510) 2020-04-28 18:57:55 -05:00
Geoff Bourne
6941e63a2c Added skipping of log4j config for Paper
For #476
2020-04-28 07:27:33 -05:00
Geoff Bourne
c68997936a Added units description for DEBUG_MEMORY option 2020-04-27 08:04:11 -05:00
Geoff Bourne
40547439b2 Added DEBUG_MEMORY option 2020-04-27 07:55:38 -05:00
Geoff Bourne
691fe638e4 Fixed spelling of Tuinity 2020-04-24 19:13:51 -05:00
Geoff Bourne
fbdee6a7a7 Added support for Tunity server type 2020-04-24 18:56:15 -05:00
Geoff Bourne
664f3d7eaa Fixed latest Paper build to be "latest" 2020-04-22 17:08:07 -05:00
orblazer
c2846fc586 Allow specify paper build and don't use legacy gamemode and difficulty (#503) 2020-04-22 07:06:57 -05:00
Geoff Bourne
e9b1332119 Added support for Magma servers
For #497
2020-04-21 18:30:48 -05:00
Geoff Bourne
757a5146a1 Added forge example compose file 2020-04-19 13:47:14 -05:00
Geoff Bourne
f9defda106 Fixed wording of CF/FTB pre-downloads 2020-04-19 13:42:39 -05:00
Geoff Bourne
e6a3ca0a1f Added JVM property to skip Spigot update check
For #417
2020-04-18 18:42:55 -05:00
Geoff Bourne
1cf478f5b3 Removed pre-creating /mods /config /plugins 2020-04-17 21:16:04 -05:00
Geoff Bourne
9ff94f9bd5 Fixed versionLessThan comparison for snapshots 2020-04-17 21:15:44 -05:00
Geoff Bourne
9842a52820 Added env var mapping for player-idle-timeout 2020-04-16 11:40:49 -05:00
Geoff Bourne
dbca9c30b0 Removed empty ENV declarations since they complicate QNAP, etc 2020-04-15 09:00:24 -05:00
Matthieu Berthomé
220f2fbd79 add some /data prefixes in missing places (#493)
Co-authored-by: rienafairefr <rienafairefr@gmail.com>
2020-04-15 08:20:11 -05:00
Geoff Bourne
8dbbdd8cd2 Added logic to skip --noconsole on newer versions
Fixes #452
2020-04-13 18:29:44 -05:00
Geoff Bourne
1c2a0c506c Added support for TYPE=CURSE_INSTANCE 2020-04-12 14:31:19 -05:00
Chip Wolf ‮
90a6707280 Enable upgrades with GENERIC_PACK (#491) 2020-04-12 09:39:28 -05:00
Geoff Bourne
e7cc54092a Fixing health check description to reference mc-monitor
For #426
2020-04-11 10:51:30 -05:00
Geoff Bourne
cd70cbcbea Enhanced Aikar's flag logic to adjust for >12GB memory
For #483
2020-04-11 10:41:20 -05:00
Geoff Bourne
7910005086 Added option to use Aikar's flags 2020-04-11 08:43:17 -05:00
Geoff Bourne
b8ace17b7c ci: ignore non-amd64 branches 2020-04-10 15:33:16 -05:00
Geoff Bourne
f70814d6b6 Updated paper build example to use stdin/tty 2020-04-10 11:00:22 -05:00
Geoff Bourne
8440e57118 Fixed support for modpacks that has multiple forge jars
HR New Beginnings was one such modpack
2020-04-10 10:59:30 -05:00
Julien Bérubé
29eda3530c fixed the link to curseforge mod list (#487) 2020-04-07 19:15:49 -05:00
Geoff Bourne
558544f1e4 Fixed WORLD cloning when path has spaces 2020-04-06 18:59:26 -05:00
Geoff Bourne
56c2f0b466 Disabled log4j config when TYPE=SPIGOT
Helps #482
2020-04-05 17:32:26 -05:00
Geoff Bourne
4bbc7d142f Fixed /plugins support for Paper servers 2020-04-04 10:13:51 -05:00
Geoff Bourne
26cc3943ce Removed ToF buildtools section since that was moved downstream 2020-04-04 09:34:21 -05:00
Geoff Bourne
6521f45f0b Added adopt13 to docker-versions-create.sh 2020-04-03 13:30:57 -05:00
Geoff Bourne
d62c2ffb42 Added ENABLE_JMX option 2020-04-03 12:32:46 -05:00
Geoff Bourne
d131941b62 Revert "Checking health of the container using SERVER_IP variable (#473)"
This reverts commit 6465bca6
2020-04-02 10:14:22 -05:00
Geoff Bourne
98f0b36cfc Changed FTB exec to always use shell
For #469
2020-04-01 18:50:07 -05:00
Alexei
6465bca640 Checking health of the container using SERVER_IP variable (#473) 2020-04-01 09:49:21 -05:00
Geoff Bourne
4ad447ba6c Used shell when FTB server script missing shebang line
For #467
2020-03-29 11:43:26 -05:00
Geoff Bourne
736979c20b Removed description of FTB/CF URL option 2020-03-29 09:48:50 -05:00
Geoff Bourne
0c34a61332 Upgraded mc-server-runner to 1.3.5
Related to #467
2020-03-29 09:30:46 -05:00
Geoff Bourne
67d58678a3 Added grep in FTB logic to avoid re-adding queryResult flag
Fixes #468
2020-03-29 08:55:53 -05:00
Geoff Bourne
fb92a74084 Added README section about running on raspberrypi 2020-03-28 14:05:16 -05:00
Geoff Bourne
8b5430ca44 Added textual link to full docs
Fixes #448
2020-03-28 14:01:57 -05:00
Geoff Bourne
f24827f558 Removed forced creation of /mods and /config volumes
Related to #464
2020-03-28 14:00:22 -05:00
Geoff Bourne
f49b967d5a Added logging of given VERSION and TYPE 2020-03-28 13:56:48 -05:00
Geoff Bourne
111ca85c4f Upgraded mc-server-runner to 1.3.4 2020-03-28 13:48:47 -05:00
Geoff Bourne
c73bedc63c Removed logging change from docker-versions-create.sh 2020-03-26 20:53:10 -05:00
Geoff Bourne
6f67f76eef Upgraded easy-add to 0.7.1 2020-03-26 20:50:13 -05:00
Geoff Bourne
002ed4bc77 Added armv7 to docker-versions-create.sh 2020-03-26 09:41:55 -05:00
Geoff Bourne
9d48e79c64 Added multiarch to docker-versions-create.sh 2020-03-25 20:13:05 -05:00
Geoff Bourne
ba7db26157 Added README section for Helm charts and examples (#461) 2020-03-25 11:24:19 -05:00
Timo Meijer
fc6129261b Add customized log file with 7 day retention (#455) 2020-03-20 16:29:52 -05:00
Pascal Sthamer
7702d98766 Allow to modify server-ip in server.properties (#454)
Needed when your machine has multiple ip adresses assigned and you want to host your server on another ip than the default one.
2020-03-20 09:56:50 -05:00
Alexei
04ed016175 Running Minecraft on a different Java version (#450)
Co-authored-by: Geoff Bourne <itzgeoff@gmail.com>
2020-03-16 10:06:35 -05:00
Geoff Bourne
1aaaf95950 Upgraded easy-add to 0.7.0 2020-03-14 15:42:28 -05:00
Malcolm Nihlén
1e334ca7d5 Added log prefixes (#444) 2020-03-06 09:52:17 -06:00
Geoff Bourne
74df4b6a9c Unified easy-add usage with multiarch and common 'file' template 2020-02-06 15:34:14 -06:00
Geoff Bourne
f63463e654 Removed mcadmin.jq since it was no longer used 2020-02-06 15:33:21 -06:00
Geoff Bourne
a24b633ccb Added support for buildx multi-arch builds 2020-02-04 17:36:03 -06:00
Geoff Bourne
5b8cd8cdcc Upgraded easy-add and used templated URLs 2020-02-02 15:16:09 -06:00
Geoff Bourne
c35c85e9b5 Included resolved version in bukkit/spigot jar name to support auto-update
Fixes #431
2020-02-02 08:09:54 -06:00
Geoff Bourne
2ffc1641a0 Added a git pull when docker-versions-create.sh starts with each branch 2020-02-01 08:52:39 -06:00
Geoff Bourne
9d67dceff3 Removed the remaining use of python 2020-01-30 21:39:35 -06:00
Geoff Bourne
c449a31b37 Removed the need for xq 2020-01-30 21:24:36 -06:00
Geoff Bourne
efd3427fc0 Added back yq/xq pip package until full conversion can be done
For #428
2020-01-29 18:02:19 -06:00
Geoff Bourne
88ed017ca7 Simplified mcstatus shim to allow for any command
Fixes #426
2020-01-29 08:57:31 -06:00
Geoff Bourne
30ba3a4b78 Restored python temporarily until jq usage can replace it
For #427
2020-01-27 14:24:09 -06:00
Geoff Bourne
c8380daee5 Fixed mcstatus shim to actually call mc-monitor
For #426
2020-01-27 08:30:54 -06:00
Geoff Bourne
8afb1651fd Added shim for mcstatus
For #426
2020-01-27 07:16:22 -06:00
Geoff Bourne
9560903c80 Replaced mcstatus with mc-monitor, so removed python 2020-01-26 16:57:14 -06:00
Geoff Bourne
e94f6608d2 Fixed UID/GID startup logic to properly handle running as root
Fixes #425
2020-01-17 08:27:11 -06:00
Geoff Bourne
949faf1620 docs: added example kube manifest with statefulset 2019-12-29 15:18:31 -06:00
Geoff Bourne
5b3259b1ef docs: added Discord chat badge 2019-12-28 14:23:04 -06:00
Geoff Bourne
485d7b0612 docs: added info in README about upgrading LATEST/SNAPSHOT versions
For #418
2019-12-27 22:04:16 -06:00
Geoff Bourne
94b037428e Add SKIP_NSSWITCH_CONF option
For #416
2019-11-26 21:34:56 -06:00
Geoff Bourne
b401873298 docs: Revert "update proxy section with correct env vars"
This reverts commit 1c9bbee3

Those env vars already get set by the startup script given PROXY
2019-11-26 08:56:29 -06:00
Geoff Bourne
1c9bbee3b3 docs: update proxy section with correct env vars
Fixes #415
2019-11-23 14:08:32 -06:00
hannah98
5fa33c7813 Better handle CurseForge manifest.json (#414) 2019-11-21 13:50:06 -06:00
Geoff Bourne
581d5fde1d ci: add adopt11 to docker-versions-create.sh 2019-11-16 09:30:39 -06:00
Geoff Bourne
382336d39d ci: add batch mode to docker-versions-create.sh 2019-11-16 09:30:06 -06:00
Geoff Bourne
5bd3a818a3 ci: fix SC2162 in docker-versions-create.sh 2019-11-16 09:29:48 -06:00
Geoff Bourne
97874f3481 ci: pre-declare merge commit message to avoid need for interaction 2019-11-16 09:04:03 -06:00
Alexei
135bafefeb docker-versions-create init (#408) 2019-11-16 08:46:52 -06:00
Dwight Spencer
15b8c5a7e7 (improvement) Offsets healthcheck to T+1m (#397) 2019-11-13 16:52:57 -06:00
jmyoung
15990071d4 Fixed JVM_XX_OPTS for FTB servers (#400) 2019-10-14 11:24:26 -05:00
Geoff Bourne
d00f9d3609 Normalize EULA value to lowercase to match Forge expectations
For #394
2019-10-01 13:54:14 -05:00
Geoff Bourne
5ad745de75 Initial support for GENERIC_PACK
For #392
2019-09-29 11:45:39 -05:00
Pavel Andreyev
b67580af2c Support .conf extension for config files (#388)
* Support .conf extension for config files

* Update the docs for env variables
2019-09-24 10:21:59 -05:00
Geoff Bourne
2900062df5 Always update whitelist from env since it is processed additive anyway
For #283
2019-09-22 16:48:59 -05:00
Geoff Bourne
67fe8931dd Upgrade easy-add, which now logs to stdout 2019-09-22 16:40:54 -05:00
Geoff Bourne
e6f593e8c4 Updating tools to support ARCH=386 builds 2019-09-18 21:14:08 -05:00
Geoff Bourne
8924740cfe Bump mc-server-runner to 1.3.3 to allow for 386 builds 2019-09-17 21:06:29 -05:00
Björn Richter
34d4ae0b59 Only write EULA when it's set to TRUE (#387)
* Only write EULA when it's set to `TRUE`

- This prevents a false value to be written while not being able to correct it afterwards using the environment variable.

* Convert EULA value to upper case to allow lower case `true` as value
2019-09-15 17:15:33 -05:00
Geoff Bourne
62a4541df5 Fix upgrade support for Paper
For #361
2019-09-15 14:09:27 -05:00
Geoff Bourne
401958c0d6 Add debugs for Fabric setup
For #361
2019-09-15 09:54:13 -05:00
Geoff Bourne
8859d223bf Track Minecraft version also in Fabric install marker
For #361
2019-09-14 22:29:54 -05:00
Geoff Bourne
621962ad9c Always populate ops.txt to allow for additive config
For #283
2019-09-08 17:22:20 -05:00
Aurélien Bertron
5c238af3df Add spawn protection setting (#386) 2019-09-08 16:40:45 -05:00
Geoff Bourne
8e148095f0 Adding link for github README 2019-08-24 11:12:41 -05:00
DocQuantum
3c55a05b1c Added ability to add resource-pack from environment vars (#379) 2019-08-24 10:38:59 -05:00
56 changed files with 1630 additions and 523 deletions

View File

@@ -1,17 +0,0 @@
version: 2
jobs:
minecraft_server:
docker:
- image: circleci/buildpack-deps:19.10
steps:
- checkout
- setup_remote_docker
- run:
name: Build image
command: docker build -t mc:$CIRCLE_BUILD_NUM .
workflows:
version: 2
build:
jobs:
- minecraft_server

View File

@@ -1,4 +1,5 @@
data
examples
k8s-examples
.idea
.idea
.git

28
.github/workflows/main.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
# This is a basic workflow to help you get started with Actions
name: build
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build and push Docker images
uses: docker/build-push-action@v1.1.0
with:
repository: itzg/minecraft-server
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
tag_with_ref: true
tag_with_sha: true
cache_froms: itzg/minecraft-server:latest
add_git_labels: true
push: false

View File

@@ -16,53 +16,71 @@ RUN apk add --no-cache -U \
tzdata \
rsync \
nano \
python python-dev py2-pip
RUN pip install mcstatus yq
HEALTHCHECK CMD mcstatus localhost:$SERVER_PORT ping
sudo \
knock \
ttf-dejavu
RUN addgroup -g 1000 minecraft \
&& adduser -Ss /bin/false -u 1000 -G minecraft -h /home/minecraft minecraft \
&& mkdir -m 777 /data /mods /config /plugins \
&& chown minecraft:minecraft /data /config /mods /plugins /home/minecraft
&& mkdir -m 777 /data \
&& chown minecraft:minecraft /data /home/minecraft
COPY files/sudoers* /etc/sudoers.d
EXPOSE 25565 25575
RUN echo 'hosts: files dns' > /etc/nsswitch.conf
# hook into docker BuildKit --platform support
# see https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
ARG TARGETOS=linux
ARG TARGETARCH=amd64
ARG TARGETVARIANT=""
ARG RESTIFY_VER=1.1.6
ARG RCON_CLI_VER=1.4.6
ARG MC_SERVER_RUNNER_VER=1.3.2
ARG ARCH=amd64
ARG EASY_ADD_VER=0.7.1
ADD https://github.com/itzg/easy-add/releases/download/${EASY_ADD_VER}/easy-add_${TARGETOS}_${TARGETARCH}${TARGETVARIANT} /usr/bin/easy-add
RUN chmod +x /usr/bin/easy-add
ADD https://github.com/itzg/restify/releases/download/${RESTIFY_VER}/restify_${RESTIFY_VER}_linux_${ARCH}.tar.gz /tmp/restify.tgz
RUN tar -x -C /usr/local/bin -f /tmp/restify.tgz restify && \
rm /tmp/restify.tgz
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=1.2.0 --var app=restify --file {{.app}} \
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
ADD https://github.com/itzg/rcon-cli/releases/download/${RCON_CLI_VER}/rcon-cli_${RCON_CLI_VER}_linux_${ARCH}.tar.gz /tmp/rcon-cli.tgz
RUN tar -x -C /usr/local/bin -f /tmp/rcon-cli.tgz rcon-cli && \
rm /tmp/rcon-cli.tgz
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=1.4.7 --var app=rcon-cli --file {{.app}} \
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
ADD https://github.com/itzg/mc-server-runner/releases/download/${MC_SERVER_RUNNER_VER}/mc-server-runner_${MC_SERVER_RUNNER_VER}_linux_${ARCH}.tar.gz /tmp/mc-server-runner.tgz
RUN tar -x -C /usr/local/bin -f /tmp/mc-server-runner.tgz mc-server-runner && \
rm /tmp/mc-server-runner.tgz
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=0.1.7 --var app=mc-monitor --file {{.app}} \
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
COPY mcadmin.jq /usr/share
RUN chmod +x /usr/local/bin/*
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=1.4.3 --var app=mc-server-runner --file {{.app}} \
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
VOLUME ["/data","/mods","/config"]
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=0.1.1 --var app=maven-metadata-release --file {{.app}} \
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
COPY mcstatus /usr/local/bin
VOLUME ["/data"]
COPY server.properties /tmp/server.properties
COPY log4j2.xml /tmp/log4j2.xml
WORKDIR /data
ENTRYPOINT [ "/start" ]
ENV UID=1000 GID=1000 \
JVM_XX_OPTS="-XX:+UseG1GC" MEMORY="1G" \
TYPE=VANILLA VERSION=LATEST FORGEVERSION=RECOMMENDED SPONGEBRANCH=STABLE SPONGEVERSION= FABRICVERSION=LATEST LEVEL=world \
PVP=true DIFFICULTY=easy ENABLE_RCON=true RCON_PORT=25575 RCON_PASSWORD=minecraft \
LEVEL_TYPE=DEFAULT GENERATOR_SETTINGS= WORLD= MODPACK= MODS= SERVER_PORT=25565 ONLINE_MODE=TRUE CONSOLE=true SERVER_NAME="Dedicated Server" \
REPLACE_ENV_VARIABLES="FALSE" ENV_VARIABLE_PREFIX="CFG_"
LEVEL_TYPE=DEFAULT SERVER_PORT=25565 ONLINE_MODE=TRUE SERVER_NAME="Dedicated Server" \
REPLACE_ENV_VARIABLES="FALSE" ENV_VARIABLE_PREFIX="CFG_" \
ENABLE_AUTOPAUSE=false AUTOPAUSE_TIMEOUT_EST=3600 AUTOPAUSE_TIMEOUT_KN=120 AUTOPAUSE_TIMEOUT_INIT=600 AUTOPAUSE_PERIOD=10
COPY start* /
COPY health.sh /
ADD files/autopause /autopause
RUN dos2unix /start* && chmod +x /start*
RUN dos2unix /health.sh && chmod +x /health.sh
RUN dos2unix /autopause/* && chmod +x /autopause/*.sh
ENTRYPOINT [ "/start" ]
HEALTHCHECK --start-period=1m CMD /health.sh

471
README.md
View File

@@ -1,13 +1,16 @@
[![Docker Pulls](https://img.shields.io/docker/pulls/itzg/minecraft-server.svg)](https://hub.docker.com/r/itzg/minecraft-server/)
[![Docker Stars](https://img.shields.io/docker/stars/itzg/minecraft-server.svg?maxAge=2592000)](https://hub.docker.com/r/itzg/minecraft-server/)
[![GitHub Issues](https://img.shields.io/github/issues-raw/itzg/docker-minecraft-server.svg)](https://github.com/itzg/docker-minecraft-server/issues)
[![](https://img.shields.io/gitter/room/itzg/dockerfiles.svg?style=flat)](https://gitter.im/itzg/dockerfiles)
[![Discord](https://img.shields.io/discord/660567679458869252)](https://discord.gg/DXfKpjB)
[![](https://img.shields.io/badge/Donate-Buy%20me%20a%20coffee-orange.svg)](https://www.buymeacoffee.com/itzg)
This docker image provides a Minecraft Server that will automatically download the latest stable
version at startup. You can also run/upgrade to any specific version or the
latest snapshot. See the *Versions* section below for more information.
latest snapshot. See the _Versions_ section below for more information.
[![Click for more docs](https://i.imgur.com/jS02ebD.png)](https://github.com/itzg/docker-minecraft-server/blob/master/README.md)
[Full docs available in Github](https://github.com/itzg/docker-minecraft-server/blob/master/README.md)
To simply use the latest stable version, run
@@ -90,6 +93,24 @@ such as
docker run -d -it -e EULA=TRUE -p 25565:25565 --name mc itzg/minecraft-server
## Timezone Configuration
You can configure the timezone to match yours by setting the `TZ` environment variable:
-e TZ=Europe/London
such as:
docker run -d -it -e TZ=Europe/London -p 25565:25565 --name mc itzg/minecraft-server
Or mounting `/etc/timezone` as readonly (not supported on Windows):
-v /etc/timezone:/etc/timezone:ro
such as:
docker run -d -it -v /etc/timezone:/etc/timezone:ro -p 25565:25565 --name mc itzg/minecraft-server
## Attaching data directory to host filesystem
In order to readily access the Minecraft data, use the `-v` argument
@@ -104,9 +125,9 @@ and start the server again with `docker start CONTAINERID` to pick up the new co
To use a different Minecraft version, pass the `VERSION` environment variable, which can have the value
* LATEST
* SNAPSHOT
* (or a specific version, such as "1.7.9")
- LATEST (the default)
- SNAPSHOT
- or a specific version, such as "1.7.9"
For example, to use the latest snapshot:
@@ -116,10 +137,34 @@ or a specific version:
docker run -d -e VERSION=1.7.9 ...
When using "LATEST" or "SNAPSHOT" an upgrade can be performed by simply restarting the container.
During the next startup, if a newer version is available from the respective release channel, then
the new server jar file is downloaded and used. _NOTE: over time you might see older versions of
the server jar remain in the `/data` directory. It is safe to remove those._
## Running Minecraft server on different Java version
To use a different version of Java, please use a docker tag to run your Minecraft server.
| Tag name | Description | Linux |
| -------------- | ------------------------------------------- | ------------ |
| latest | **Default**. Uses Java version 8 update 212 | Alpine Linux |
| adopt13 | Uses Java version 13 latest update | Alpine Linux |
| adopt11 | Uses Java version 11 latest update | Alpine Linux |
| openj9 | Uses Eclipse OpenJ9 JVM | Alpine Linux |
| openj9-nightly | Uses Eclipse OpenJ9 JVM testing builds | Alpine Linux |
| multiarch | Uses Java version 8 latest update | Debian Linux |
For example, to use a Java version 13:
docker run --name mc itzg/minecraft-server:adopt13
Keep in mind that some versions of Minecraft server can't work on the newest versions of Java. Also, FORGE doesn't support openj9 JVM implementation.
## Healthcheck
This image contains [Dinnerbone's mcstatus](https://github.com/Dinnerbone/mcstatus) and uses
its `ping` command to continually check on the container's. That can be observed
This image contains [mc-monitor](https://github.com/itzg/mc-monitor) and uses
its `status` command to continually check on the container's. That can be observed
from the `STATUS` column of `docker ps`
```
@@ -134,23 +179,58 @@ You can also query the container's health in a script friendly way:
healthy
```
Finally, since `mcstatus` is on the `PATH` you can exec into the container
and use mcstatus directly and invoke any of its other commands:
## Autopause
### Description
> There are various bug reports on [Mojang](https://bugs.mojang.com) about high CPU usage of servers with newer versions, even with few or no clients connected (e.g. [this one](https://bugs.mojang.com/browse/MC-149018), in fact the functionality is based on [this comment in the thread](https://bugs.mojang.com/browse/MC-149018?focusedCommentId=593606&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-593606)).
An autopause functionality has been added to this image to monitor whether clients are connected to the server. If for a specified time no client is connected, the Java process is stopped. When knocking on the server port (e.g. by the ingame Multiplayer server overview), the process is resumed. The experience for the client does not change.
Of course, even loaded chunks are not ticked when the process is stopped.
From the server's point of view, the pausing causes a single tick to take as long as the process is stopped, so the server watchdog might intervene after the process is continued, possibly forcing a container restart. To prevent this, ensure that the `max-tick-time` in the `server.properties` file is set correctly.
On startup the `server.properties` file is checked and, if applicable, a warning is printed to the terminal. When the server is created (no data available in the persistent directory), the properties file is created with the Watchdog disabled.
The autopause functionality is not compatible with docker's host network_mode, as the `knockd` utility cannot properly listen for connections in that mode.
### Enabling Autopause
Enable the Autopause functionality by setting:
```
> docker exec mc mcstatus localhost status
version: v1.12 (protocol 335)
description: "{u'text': u'A Minecraft Server Powered by Docker'}"
players: 0/20 No players online
-e ENABLE_AUTOPAUSE=TRUE
```
There are 4 more environment variables that define the behaviour:
* `AUTOPAUSE_TIMEOUT_EST`, default `3600` (seconds)
describes the time between the last client disconnect and the pausing of the process (read as timeout established)
* `AUTOPAUSE_TIMEOUT_INIT`, default `600` (seconds)
describes the time between server start and the pausing of the process, when no client connects inbetween (read as timeout initialized)
* `AUTOPAUSE_TIMEOUT_KN`, default `120` (seconds)
describes the time between knocking of the port (e.g. by the main menu ping) and the pausing of the process, when no client connects inbetween (read as timeout knocked)
* `AUTOPAUSE_PERIOD`, default `10` (seconds)
describes period of the daemonized state machine, that handles the pausing of the process (resuming is done independently)
## Deployment Templates and Examples
### Helm Charts
- [stable/minecraft](https://hub.helm.sh/charts/stable/minecraft) ([chart source](https://github.com/helm/charts/tree/master/stable/minecraft))
- [mcsh/server-deployment](https://github.com/mcserverhosting-net/charts)
### Examples
The [examples directory](https://github.com/itzg/docker-minecraft-server/tree/master/examples) also provides examples of deploying the [itzg/minecraft-server](https://hub.docker.com/r/itzg/minecraft-server/) Docker image.
## Running a Forge Server
Enable Forge server mode by adding a `-e TYPE=FORGE` to your command-line.
By default the container will run the `RECOMMENDED` version of [Forge server](http://www.minecraftforge.net/wiki/)
but you can also choose to run a specific version with `-e FORGEVERSION=10.13.4.1448`.
$ docker run -d -v /path/on/host:/data -e VERSION=1.7.10 \
$ docker run -d -v /path/on/host:/data \
-e TYPE=FORGE -e FORGEVERSION=10.13.4.1448 \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
@@ -202,7 +282,7 @@ up:
This is the easiest way if you are using an ephemeral `/data` filesystem,
or downloading a world with the `WORLD` option.
There are two additional volumes that can be mounted; `/mods` and `/config`.
There are two additional volumes that can be mounted; `/mods` and `/config`.
Any files in either of these filesystems will be copied over to the main
`/data` filesystem before starting Minecraft.
@@ -222,7 +302,7 @@ For those cases there is the option to replace defined variables inside your con
with environment variables defined at container runtime.
If you set the enviroment variable `REPLACE_ENV_VARIABLES` to `TRUE` the startup script
will go thru all files inside your `/data` volume and replace variables that match your
will go thru all files inside your `/data` volume and replace variables that match your
defined environment variables. Variables that you want to replace need to be wrapped
inside `${YOUR_VARIABLE}` curly brackets and prefixed with a dollar sign. This is the regular
syntax for enviromment variables inside strings or config files.
@@ -231,6 +311,8 @@ Optionally you can also define a prefix to only match predefined enviroment vari
`ENV_VARIABLE_PREFIX="CFG_"` <-- this is the default prefix
If you want use file for value (like when use secrets) you can add suffix `_FILE` to your variable name (in run command).
There are some limitations to what characters you can use.
| Type | Allowed Characters |
@@ -238,20 +320,24 @@ There are some limitations to what characters you can use.
| Name | `0-9a-zA-Z_-` |
| Value | `0-9a-zA-Z_-:/=?.+` |
Variables will be replaced in files with the following extensions:
`.yml`, `.yaml`, `.txt`, `.cfg`, `.conf`, `.properties`.
Here is a full example where we want to replace values inside a `database.yml`.
```yml
...
---
database:
host: ${CFG_DB_HOST}
name: ${CFG_DB_NAME}
password: ${CFG_DB_PASSWORD}
host: ${CFG_DB_HOST}
name: ${CFG_DB_NAME}
password: ${CFG_DB_PASSWORD}
```
This is how your `docker-compose.yml` file could look like:
```yml
version: '3'
version: "3"
# Other docker-compose examples in /examples
services:
@@ -273,7 +359,7 @@ services:
# and here are the actual variables
CFG_DB_HOST: "http://localhost:3306"
CFG_DB_NAME: "minecraft"
CFG_DB_PASSWORD: "ug23u3bg39o-ogADSs"
CFG_DB_PASSWORD_FILE: "/run/secrets/db_password"
restart: always
rcon:
image: itzg/rcon
@@ -286,30 +372,38 @@ services:
volumes:
mc:
rcon:
secrets:
db_password:
file: ./db_password
```
The content of `db_password`:
ug23u3bg39o-ogADSs
## Running a Bukkit/Spigot server
Enable Bukkit/Spigot server mode by adding a `-e TYPE=BUKKIT -e VERSION=1.8` or `-e TYPE=SPIGOT -e VERSION=1.8` to your command-line.
Enable Bukkit/Spigot server mode by adding a `-e TYPE=BUKKIT` or `-e TYPE=SPIGOT` to your command-line.
docker run -d -v /path/on/host:/data \
-e TYPE=SPIGOT -e VERSION=1.8 \
-e TYPE=SPIGOT \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
If you are hosting your own copy of Bukkit/Spigot you can override the download URLs with:
* -e BUKKIT_DOWNLOAD_URL=<url>
* -e SPIGOT_DOWNLOAD_URL=<url>
- -e BUKKIT_DOWNLOAD_URL=<url>
- -e SPIGOT_DOWNLOAD_URL=<url>
You can build spigot from source by adding `-e BUILD_FROM_SOURCE=true`
__NOTE: to avoid pegging the CPU when running Spigot,__ you will need to
**NOTE: to avoid pegging the CPU when running Spigot,** you will need to
pass `--noconsole` at the very end of the command line and not use `-it`. For example,
docker run -d -v /path/on/host:/data \
-e TYPE=SPIGOT -e VERSION=1.8 \
-e TYPE=SPIGOT \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server --noconsole
You can install Bukkit plugins in two ways...
### Using the /data volume
@@ -342,7 +436,7 @@ up:
This is the easiest way if you are using an ephemeral `/data` filesystem,
or downloading a world with the `WORLD` option.
There is one additional volume that can be mounted; `/plugins`.
There is one additional volume that can be mounted; `/plugins`.
Any files in this filesystem will be copied over to the main
`/data/plugins` filesystem before starting Minecraft.
@@ -350,36 +444,31 @@ This works well if you want to have a common set of plugins in a separate
location, but still have multiple worlds with different server requirements
in either persistent volumes or a downloadable archive.
### Building an image with plugins
You can also create your own Docker images by extending the `itzg/minecraft-server` image.
The image contains an `ONBUILD` trigger that will copy a `plugins.yml` file from you build directory and download any plugins specified in it.
You can read about the [`ToF-BuildTools` and how to use them here](https://git.faldoria.de/tof/server/build-tools).
You can also find [an example](examples/ToF-build/) with a custom image in the examples dir.
## Running a PaperSpigot server
Enable PaperSpigot server mode by adding a `-e TYPE=PAPER -e VERSION=1.9.4` to your command-line.
Enable PaperSpigot server mode by adding a `-e TYPE=PAPER` to your command-line.
By default the container will run the latest build of [Paper server](https://papermc.io/downloads)
but you can also choose to run a specific build with `-e PAPERBUILD=205`.
docker run -d -v /path/on/host:/data \
-e TYPE=PAPER -e VERSION=1.9.4 \
-e TYPE=PAPER \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
__NOTE: to avoid pegging the CPU when running PaperSpigot,__ you will need to
**NOTE: to avoid pegging the CPU when running PaperSpigot,** you will need to
pass `--noconsole` at the very end of the command line and not use `-it`. For example,
docker run -d -v /path/on/host:/data \
-e TYPE=PAPER -e VERSION=1.9.4 \
-e TYPE=PAPER \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server --noconsole
If you are hosting your own copy of PaperSpigot you can override the download URL with:
* -e PAPER_DOWNLOAD_URL=<url>
- -e PAPER_DOWNLOAD_URL=<url>
You can install Bukkit plugins in two ways...
An example compose file is provided at
An example compose file is provided at
[examples/docker-compose-paper.yml](examples/docker-compose-paper.yml).
### Using the /data volume
@@ -412,7 +501,7 @@ up:
This is the easiest way if you are using an ephemeral `/data` filesystem,
or downloading a world with the `WORLD` option.
There is one additional volume that can be mounted; `/plugins`.
There is one additional volume that can be mounted; `/plugins`.
Any files in this filesystem will be copied over to the main
`/data/plugins` filesystem before starting Minecraft.
@@ -420,59 +509,71 @@ This works well if you want to have a common set of plugins in a separate
location, but still have multiple worlds with different server requirements
in either persistent volumes or a downloadable archive.
## Running a Server with a Feed-The-Beast (FTB) / CurseForge modpack
## Running a Tuinity server
Enable this server mode by adding a `-e TYPE=FTB` or `-e TYPE=CURSEFORGE` to your command-line,
A [Tuinity](https://github.com/Spottedleaf/Tuinity) server, which is a fork of Paper aimed at improving server performance at high playercounts.
-e TYPE=TUINITY
> **NOTE** only `VERSION=LATEST` is supported
## Running a Magma server
A [Magma](https://magmafoundation.org/) server, which is a combination of Forge and PaperMC, can be used with
-e TYPE=MAGMA
> **NOTE** there are limited base versions supported, so you will also need to set `VERSION`, such as "1.12.2"
## Running a server with a Feed the Beast modpack
> **NOTE** requires `itzg/minecraft-server:multiarch` image
[Feed the Beast application](https://www.feed-the-beast.com/) modpacks are supported by using `-e TYPE=FTBA` (**note** the "A" at the end of the type). This server type will automatically take care of downloading and installing the modpack and appropriate version of Forge, so the `VERSION` does not need to be specified.
### Environment Variables:
- `FTB_MODPACK_ID`: **required**, the numerical ID of the modpack to install. The ID can be located by finding the modpack at [Neptune FTB](https://ftb.neptunepowered.org/) and using the "Pack ID"
- `FTB_MODPACK_VERSION_ID`: optional, the numerical Id of the version to install. If not specified, the latest version will be installed. The "Version ID" can be obtained by drilling into the Versions tab and clicking a specific version.
### Upgrading
If a specific `FTB_MODPACK_VERSION_ID` was not specified, simply restart the container to pick up the newest modpack version. If using a specific version ID, recreate the container with the new version ID.
### Example
The following example runs the latest version of [FTB Presents Direwolf20 1.12](https://ftb.neptunepowered.org/pack/ftb-presents-direwolf20-1-12/):
```
docker run -d --name mc-ftb -e EULA=TRUE \
-e TYPE=FTBA -e FTB_MODPACK_ID=31 \
-p 25565:25565 \
itzg/minecraft-server:multiarch
```
> Normally you will also add `-v` volume for `/data` since the mods and config are installed there along with world data.
## Running a server with a CurseForge modpack
Enable this server mode by adding `-e TYPE=CURSEFORGE` to your command-line,
but note the following additional steps needed...
You need to specify a modpack to run, using the `FTB_SERVER_MOD` or `CF_SERVER_MOD` environment
variable. An FTB/CurseForge server modpack is available together with its respective
client modpack on https://www.feed-the-beast.com under "Additional Files." Similar you can
locate the modpacks for CurseForge at https://minecraft.curseforge.com/modpacks .
You need to specify a modpack to run, using the `CF_SERVER_MOD` environment
variable. A CurseForge server modpack is available together with its respective
client modpack at <https://www.curseforge.com/minecraft/modpacks> .
There are a couple of options for obtaining an FTB/CurseForge modpack.
One options is that you can pre-download the **server** modpack and copy the modpack to the `/data`
directory (see "Attaching data directory to host filesystem”).
Now you can add a `-e CF_SERVER_MOD=name_of_modpack.zip` to your command-line.
Now you can add a `-e FTB_SERVER_MOD=name_of_modpack.zip` to your command-line.
docker run -d -v /path/on/host:/data -e TYPE=FTB \
-e FTB_SERVER_MOD=FTBPresentsSkyfactory3Server_3.0.6.zip \
docker run -d -v /path/on/host:/data -e TYPE=CURSEFORGE \
-e CF_SERVER_MOD=SkyFactory_4_Server_4.1.0.zip \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
Instead of pre-downloading a modpack from the FTB/CurseForge site, you
can you set `FTB_SERVER_MOD` (or `CF_SERVER_MOD`) to the **server** URL of a modpack, such as
If you want to keep the pre-download modpacks separate from your data directory,
then you can attach another volume at a path of your choosing and reference that.
The following example uses `/modpacks` as the container path as the pre-download area:
docker run ... \
-e TYPE=FTB \
-e FTB_SERVER_MOD=https://www.feed-the-beast.com/projects/ftb-infinity-lite-1-10/files/2402889
or for a CurseForce modpack:
docker run ... \
-e TYPE=CURSEFORGE \
-e CF_SERVER_MOD=https://minecraft.curseforge.com/projects/enigmatica2expert/files/2663153/download
### Using the /data volume
You must use a persistent `/data` mount for this type of server.
To do this, you will need to attach the container's `/data` directory
(see "Attaching data directory to host filesystem”).
If the modpack is updated and you want to run the new version on your
server, you stop and remove the container:
docker stop mc
docker rm mc
Do not erase anything from your /data directory (unless you know of
specific mods that have been removed from the modpack). Download the
updated FTB server modpack and copy it to `/data`. Start a new container
with `FTB_SERVER_MOD` specifying the updated modpack file.
$ docker run -d -v /path/on/host:/data -e TYPE=FTB \
-e FTB_SERVER_MOD=FTBPresentsSkyfactory3Server_3.0.7.zip \
docker run -d -v /path/on/host:/data -v /path/to/modpacks:/modpacks \
-e TYPE=CURSEFORGE \
-e CF_SERVER_MOD=/modpacks/SkyFactory_4_Server_4.1.0.zip \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
### Fixing "unable to launch forgemodloader"
@@ -485,42 +586,6 @@ then you apply a workaround by adding this to the run invocation:
-e FTB_LEGACYJAVAFIXER=true
### Using a client-made curseforge modpack
If you use something like curseforge, you may end up creating/using modpacks that do not
contain server mod jars. Instead, the curseforge setup has `manifest.json` files, which
will show up under `/data/FeedTheBeast/manifest.json`.
To use these packs you will need to:
- Specify the manifest location with env var `MANIFEST=/data/FeedTheBeast/manifest`
- Pick a relevant ServerStart.sh and potentially settings.cfg and put them in `/data/FeedTheBeast`
An example of the latter would be to use https://github.com/AllTheMods/Server-Scripts
There, you'll find that all you have to do is put `ServerStart.sh` and `settings.cfg` into
`/data/FeedTheBeast`, taking care to update `settings.cfg` to specify your desired version
of minecraft and forge. You can do this in the cli with something like:
```
$ wget https://raw.githubusercontent.com/AllTheMods/Server-Scripts/master/ServerStart.sh
$ wget https://raw.githubusercontent.com/AllTheMods/Server-Scripts/master/settings.cfg
$ vim settings.cfg #update the forge version to the one you want. Your manifest.json will have it
$ chmod +x ServerStart.sh
$ docker run -itd --name derpcraft \
-e MANIFEST=/data/FeedTheBeast/manifest.json \
-v $PWD/ServerStart.sh:/data/FeedTheBeast/ServerStart.sh \
-v $PWD/settings.cfg:/data/FeedTheBeast/settings.cfg \
-e VERSION=1.12.2\
-e TYPE=CURSEFORGE\
-e CF_SERVER_MOD=https://minecraft.curseforge.com/projects/your_amazing_modpack/files/2670435/download\
-p 25565:25565\
-e EULA=TRUE\
--restart=always\
itzg/minecraft-server
```
Note the `CF_SERVER_MOD` env var should match the url to download the modpack you are targeting.
## Running a SpongeVanilla server
Enable SpongeVanilla server mode by adding a `-e TYPE=SPONGEVANILLA` to your command-line.
@@ -542,7 +607,7 @@ Enable Fabric server mode by adding a `-e TYPE=FABRIC` to your command-line.
By default the container will run the latest version of [Fabric server](http://fabricmc.net/use/)
but you can also choose to run a specific version with `-e FABRICVERSION=0.5.0.32`.
$ docker run -d -v /path/on/host:/data -e VERSION=1.14.3 \
$ docker run -d -v /path/on/host:/data \
-e TYPE=FABRIC -e FABRICVERSION=0.5.0.32 \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
@@ -594,7 +659,7 @@ up:
This is the easiest way if you are using an ephemeral `/data` filesystem,
or downloading a world with the `WORLD` option.
There are two additional volumes that can be mounted; `/mods` and `/config`.
There are two additional volumes that can be mounted; `/mods` and `/config`.
Any files in either of these filesystems will be copied over to the main
`/data` filesystem before starting Minecraft.
@@ -605,23 +670,23 @@ in either persistent volumes or a downloadable archive.
## Running with a custom server JAR
If you would like to run a custom server JAR, set `-e TYPE=CUSTOM` and pass the custom server
JAR via `CUSTOM_SERVER`. It can either be a URL or a container path to an existing JAR file.
JAR via `CUSTOM_SERVER`. It can either be a URL or a container path to an existing JAR file.
If it is a URL, it will only be downloaded into the `/data` directory if it wasn't already. As
such, if you need to upgrade or re-download the JAR, then you will need to stop the container,
remove the file from the container's `/data` directory, and start again.
remove the file from the container's `/data` directory, and start again.
## Force re-download of the server file
For VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, CURSEFORGE, SPONGEVANILLA server types, set
`$FORCE_REDOWNLOAD` to some value (e.g. 'true) to force a re-download of the server file for
For VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, CURSEFORGE, SPONGEVANILLA server types, set
`$FORCE_REDOWNLOAD` to some value (e.g. 'true) to force a re-download of the server file for
the particular server type. by adding a `-e FORCE_REDOWNLOAD=true` to your command-line.
For example, with PaperSpigot, it would look something like this:
```
docker run -d -v /path/on/host:/data \
-e TYPE=PAPER -e VERSION=1.14.1 -e FORCE_REDOWNLOAD=true \
-e TYPE=PAPER -e FORCE_REDOWNLOAD=true \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
```
@@ -653,8 +718,8 @@ and in the same directory as that file run
docker-compose up -d
Now, go play...or adjust the `environment` section to configure
this server instance.
Now, go play...or adjust the `environment` section to configure
this server instance.
## Server configuration
@@ -697,7 +762,7 @@ values.
To whitelist players for your Minecraft server, pass the Minecraft usernames separated by commas via the `WHITELIST` environment variable, such as
docker run -d -e WHITELIST=user1,user2 ...
docker run -d -e WHITELIST=user1,user2 ...
If the `WHITELIST` environment variable is not used, any user can join your Minecraft server if it's publicly accessible.
@@ -705,7 +770,7 @@ If the `WHITELIST` environment variable is not used, any user can join your Mine
To add more "op" (aka adminstrator) users to your Minecraft server, pass the Minecraft usernames separated by commas via the `OPS` environment variable, such as
docker run -d -e OPS=user1,user2 ...
docker run -d -e OPS=user1,user2 ...
### Server icon
@@ -728,19 +793,17 @@ By default the query port will be `25565` (UDP) but can easily be changed with t
docker run -d -e ENABLE_QUERY=true
### Max players
By default max players is 20, you can increase this with the `MAX_PLAYERS` variable.
docker run -d -e MAX_PLAYERS=50
### Max world size
This sets the maximum possible size in blocks, expressed as a radius, that the world border can obtain.
docker run -d -e MAX_WORLD_SIZE=10000
docker run -d -e MAX_WORLD_SIZE=10000
### Allow Nether
@@ -752,9 +815,9 @@ Allows players to travel to the Nether.
Allows server to announce when a player gets an achievement.
docker run -d -e ANNOUNCE_PLAYER_ACHIEVEMENTS=true
docker run -d -e ANNOUNCE_PLAYER_ACHIEVEMENTS=true
### Enable Command Block
### Enable Command Block
Enables command blocks
@@ -764,19 +827,19 @@ Enables command blocks
Force players to join in the default game mode.
* false - Players will join in the gamemode they left in.
* true - Players will always join in the default gamemode.
- false - Players will join in the gamemode they left in.
- true - Players will always join in the default gamemode.
`docker run -d -e FORCE_GAMEMODE=false`
`docker run -d -e FORCE_GAMEMODE=false`
### Generate Structures
Defines whether structures (such as villages) will be generated.
* false - Structures will not be generated in new chunks.
* true - Structures will be generated in new chunks.
- false - Structures will not be generated in new chunks.
- true - Structures will be generated in new chunks.
`docker run -d -e GENERATE_STRUCTURES=true`
`docker run -d -e GENERATE_STRUCTURES=true`
### Hardcore
@@ -822,7 +885,14 @@ Determines if villagers will be spawned.
docker run -d -e SPAWN_NPCS=true
### Set spawn protection
Sets the area that non-ops can not edit (0 to disable)
docker run -d -e SPAWN_PROTECTION=0
### View Distance
Sets the amount of world data the server sends the client, measured in chunks in each direction of the player (radius, not diameter).
It determines the server-side viewing distance.
@@ -841,10 +911,10 @@ change the mode using `MODE` where you can either provide the [standard
numerical values](http://minecraft.gamepedia.com/Game_mode#Game_modes) or the
shortcut values:
* creative
* survival
* adventure
* spectator (only for Minecraft 1.8 or later)
- creative
- survival
- adventure
- spectator (only for Minecraft 1.8 or later)
For example:
@@ -877,12 +947,12 @@ environment variable set to `false`, such as
By default, a standard world is generated with hills, valleys, water, etc. A different level type can
be configured by setting `LEVEL_TYPE` to an expected type, such as
* DEFAULT
* FLAT
* LARGEBIOMES
* AMPLIFIED
* CUSTOMIZED
* BUFFET
- DEFAULT
- FLAT
- LARGEBIOMES
- AMPLIFIED
- CUSTOMIZED
- BUFFET
Descriptions are available at the [gamepedia](http://minecraft.gamepedia.com/Server.properties).
@@ -894,6 +964,14 @@ For example (just the `-e` bits):
-e LEVEL_TYPE=flat -e 'GENERATOR_SETTINGS=3;minecraft:bedrock,3*minecraft:stone,52*minecraft:sandstone;2;'
### Custom Server Resource Pack
You can set a link to a custom resource pack and set it's checksum using the `RESOURCE_PACK` and `RESOURCE_PACK_SHA1` options respectively, the default is blank:
docker run -d -e 'RESROUCE_PACK=http\://link.com/to/pack.zip?\=1' -e 'RESOURCE_PACK_SHA1=d5db29cd03a2ed055086cef9c31c252b4587d6d0'
**NOTE:** `:` and `=` must be escaped using `\`. The checksum plain-text hexadecimal.
### World Save Name
You can either switch between world saves or run multiple containers with different saves by using the `LEVEL` option,
@@ -906,37 +984,26 @@ where the default is "world":
### Downloadable world
Instead of mounting the `/data` volume, you can instead specify the URL of
a ZIP file containing an archived world. This will be downloaded, and
unpacked in the `/data` directory; if it does not contain a subdirectory
called `world/` then it will be searched for a file `level.dat` and the
containing subdirectory renamed to `world`. This means that most of the
archived Minecraft worlds downloadable from the Internet will already be in
the correct format.
The ZIP file may also contain a `server.properties` file and `modules`
directory, if required.
Instead of mounting the `/data` volume, you can instead specify the URL of a ZIP file containing an archived world. It will be searched for a file `level.dat` and the containing subdirectory moved to the directory named by `$LEVEL`. This means that most of the archived Minecraft worlds downloadable from the Internet will already be in the correct format.
docker run -d -e WORLD=http://www.example.com/worlds/MySave.zip ...
**NOTE:** Unless you also mount `/data` as an external volume, this world
will be deleted when the container is deleted.
**NOTE:** This URL must be accessible from inside the container. Therefore,
you should use an IP address or a globally resolveable FQDN, or else the
**NOTE:** This URL must be accessible from inside the container. Therefore,
you should use an IP address or a globally resolvable FQDN, or else the
name of a linked container.
**NOTE:** If the archive contains more than one `level.dat`, then the one to select can be picked with `WORLD_INDEX`, which defaults to 1.
### Cloning world from a container path
The `WORLD` option can also be used to reference a directory that will be used
as a source to clone the world directory.
The `WORLD` option can also be used to reference a directory or zip file that will be used as a source to clone or unzip the world directory.
For example, the following would initially clone the world's content
from `/worlds/basic`. Also notice in the example that you can use a
read-only volume attachment to ensure the clone source remains pristine.
```
docker run ... -v $HOME/worlds:/worlds:ro -e WORLD=/worlds/basic
docker run ... -v $HOME/worlds:/worlds:ro -e WORLD=/worlds/basic
```
### Downloadable mod/plugin pack for Forge, Bukkit, and Spigot Servers
@@ -954,7 +1021,7 @@ particular `TYPE` of server you are running.
You may also download individual mods using the `MODS` environment variable and supplying the URL
to the jar files. Multiple mods/plugins should be comma separated.
docker run -d -e MODS=https://www.example.com/mods/mod1.jar,https://www.example.com/mods/mod2.jar ...
docker run -d -e MODS=https://www.example.com/mods/mod1.jar,https://www.example.com/mods/mod2.jar ...
### Remove old mods/plugins
@@ -966,7 +1033,7 @@ To use this option pass the environment variable `REMOVE_OLD_MODS="TRUE"`, such
docker run -d -e REMOVE_OLD_MODS="TRUE" -e MODPACK=http://www.example.com/mods/modpack.zip ...
**WARNING:** All content of the `mods` or `plugins` directory will be deleted
before unpacking new content from the MODPACK or MODS.
before unpacking new content from the MODPACK or MODS.
### Online mode
@@ -980,6 +1047,12 @@ Allows users to use flight on your server while in Survival mode, if they have a
-e ALLOW_FLIGHT=TRUE|FALSE
### Other server property mappings
Environment Variable | Server Property
---------------------|-----------------
PLAYER_IDLE_TIMEOUT | player-idle-timeout
## Miscellaneous Options
### Running as alternate user/group ID
@@ -998,10 +1071,10 @@ is passed to `docker run`.
By default, the image declares a Java initial and maximum memory limit of 1 GB. There are several
ways to adjust the memory settings:
* `MEMORY`, "1G" by default, can be used to adjust both initial (`Xms`) and max (`Xmx`)
- `MEMORY`, "1G" by default, can be used to adjust both initial (`Xms`) and max (`Xmx`)
memory settings of the JVM
* `INIT_MEMORY`, independently sets the initial heap size
* `MAX_MEMORY`, independently sets the max heap size
- `INIT_MEMORY`, independently sets the initial heap size
- `MAX_MEMORY`, independently sets the max heap size
The values of all three are passed directly to the JVM and support format/units as
`<size>[g|G|m|M|k|K]`. For example:
@@ -1015,12 +1088,30 @@ environment variable. Options like `-X` that need to proceed general JVM options
via a `JVM_XX_OPTS` environment variable.
For some cases, if e.g. after removing mods, it could be necessary to startup minecraft with an additional `-D` parameter like `-Dfml.queryResult=confirm`. To address this you can use the environment variable `JVM_DD_OPTS`, which builds the params from a given list of values separated by space, but without the `-D` prefix. To make things running under systems (e.g. Plesk), which doesn't allow `=` inside values, a `:` (colon) could be used instead. The upper example would look like this:
`JVM_DD_OPTS=fml.queryResult:confirm`, and will be converted to `-Dfml.queryResult=confirm`.
`JVM_DD_OPTS=fml.queryResult:confirm`, and will be converted to `-Dfml.queryResult=confirm`.
### Enable Remote JMX for Profiling
To enable remote JMX, such as for profiling with VisualVM or JMC, add the environment variable `ENABLE_JMX=true` and add a port forwarding of TCP port 7091, such as:
-e ENABLE_JMX=true -p 7091:7091
### Enable Aikar's Flags
[Aikar has does some research](https://mcflags.emc.gs/) into finding the optimal JVM flags for GC tuning, which becomes more important as more users are connected concurrently. The set of flags documented there can be added using
-e USE_AIKAR_FLAGS=true
When `MEMORY` is greater than or equal to 12G, then the Aikar flags will be adjusted according to the article.
Large page support can also be enabled by adding
-e USE_LARGE_PAGES=true
### HTTP Proxy
You may configure the use of an HTTP/HTTPS proxy by passing the proxy's URL via the `PROXY`
environment variable. In [the example compose file](docker-compose-proxied.yml) it references
environment variable. In [the example compose file](examples/docker-compose-proxied.yml) it references
a companion squid proxy by setting the equivalent of
-e PROXY=proxy:3128
@@ -1033,4 +1124,12 @@ pass that at the end of `docker run` after the image name or set `-e CONSOLE=FAL
### Explicitly disable GUI
Some older servers get confused and think that the GUI interface is enabled. You can explicitly
disable that by passing `-e GUI=FALSE`.
disable that by passing `-e GUI=FALSE`.
## Running on RaspberryPi
To run this image on a RaspberryPi 3 B+, 4, or newer, use the image tag
itzg/minecraft-server:armv7
> NOTE: you may need to lower the memory allocation, such as `-e MEMORY=750m`

34
build-multiarch.sh Normal file
View File

@@ -0,0 +1,34 @@
#!/bin/bash
# manually purge any pre-existing manifest list
# since docker manifest command lacks a "remove" operation
rm -rf ~/.docker/manifests/docker.io_itzg_minecraft-server-multiarch
export DOCKER_BUILDKIT=1
docker build --platform linux/arm64 -t itzg/minecraft-server:arm64 .
docker push itzg/minecraft-server:arm64
armv7tag=armv7-buildkit
armv7workDir=/tmp/armv7-$$
git worktree add $armv7workDir armv7
# sub-shell for build of armv7
(
cd $armv7workDir
docker build --platform linux/arm/v7 -t itzg/minecraft-server:$armv7tag .
docker push itzg/minecraft-server:$armv7tag
)
git worktree remove $armv7workDir
docker pull itzg/minecraft-server
# use the rpi build one for now since armv7-buildkit is giving ABI mismatch on curl
docker pull itzg/minecraft-server:armv7
docker manifest create itzg/minecraft-server:multiarch \
itzg/minecraft-server \
itzg/minecraft-server:armv7 \
itzg/minecraft-server:arm64
docker manifest inspect itzg/minecraft-server:multiarch
docker manifest push -p itzg/minecraft-server:multiarch

96
docker-versions-create.sh Executable file
View File

@@ -0,0 +1,96 @@
#!/bin/bash
#set -x
# Use this variable to indicate a list of branches that docker hub is watching
branches_list=('openj9' 'openj9-nightly' 'adopt11' 'adopt13' 'multiarch')
function TrapExit {
echo "Checking out back in master"
git checkout master
}
batchMode=false
while getopts "b" arg
do
case $arg in
b)
batchMode=true
;;
*)
echo "Unsupported arg $arg"
exit 2
;;
esac
done
${batchMode} && echo "Using batch mode"
trap TrapExit EXIT SIGTERM
test -d ./.git || { echo ".git folder was not found. Please start this script from root directory of the project!";
exit 1; }
# Making sure we are in master
git checkout master
git pull --all || { echo "Can't pull the repo!"; \
exit 1; }
git_branches=$(git branch -a)
for branch in "${branches_list[@]}"; do
if [[ "$git_branches" != *"$branch"* ]]; then
echo "Can't update $branch because I can't find it in the list of branches."
exit 1
else
echo "Branch $branch found. Working with it."
git checkout "$branch" || { echo "Can't checkout into the branch. Don't know the cause."; \
exit 1; }
proceed='False'
while [[ "$proceed" == "False" ]]; do
# Ensure local branch is aligned with remote since docker-versions-create may have been run elsewhere
git pull
if git merge -m 'Auto-merging via docker-versions-create' master; then
proceed="True"
echo "Branch $branch updated to current master successfully"
# pushing changes to remote for this branch
git commit -m "Auto merge branch with master" -a
# push may fail if remote doesn't have this branch yet. In this case - sending branch
git push || git push -u origin "$branch" || { echo "Can't push changes to the origin."; exit 1; }
elif ${batchMode}; then
status=$?
echo "Git merge failed in batch mode"
exit ${status}
# and trap exit gets us back to master
else
cat<<EOL
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Master merge in the branch $branch encountered an error!
You may try to fix the error and merge again. (Commit changes)
Or skip this branch merge completely.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
EOL
printf "Should we try again? (y):"
read -r answer
if [[ "$answer" == '' ]] || [[ "$answer" == 'y' ]] || [[ "$answer" == 'Y' ]]; then
# If you use non-local editor or files are changed in repo
cat <<EOL
The following commands may encounter an error!
This is completely fine if the changes were made locally and remote branch doesn't know about them.
EOL
# Updating branch from remote before trying again
git checkout master
git fetch --all
git pull -a
git checkout "$branch"
continue
else
break
fi
fi
done
fi
done

3
examples/README.md Normal file
View File

@@ -0,0 +1,3 @@
# Deployment Examples
This directory contains various deployment examples of the [itzg/minecraft-server](https://hub.docker.com/r/itzg/minecraft-server/) Docker image.

View File

@@ -1,3 +0,0 @@
FROM itzg/minecraft-server
ENV TYPE=SPIGOT

View File

@@ -1,13 +0,0 @@
plugins:
worldedit:
file: WorldEdit.jar
url: https://dev.bukkit.org/projects/worldedit/files/latest
FastAsyncWorldEdit:
file: FastAsyncWorldEdit.jar
url: https://empcraft.com/fawe/latest.php?bukkit
worldguard:
file: WorldGuard.jar
url: https://dev.bukkit.org/projects/worldguard/files/latest
citizens:
file: Citizens.jar
url: https://dev.bukkit.org/projects/citizens/files/latest

View File

@@ -3,9 +3,11 @@ version: '3.2'
services:
mc:
image: itzg/minecraft-server
volumes:
- ./modpacks:/modpacks:ro
environment:
EULA: "true"
TYPE: FTB
FTB_SERVER_MOD: https://minecraft.curseforge.com/projects/all-the-mods-expert-remastered/files/2493900/download
TYPE: CURSEFORGE
CF_SERVER_MOD: /modpacks/SkyFactory_4_Server_4.1.0.zip
ports:
- 25565:25565

View File

@@ -0,0 +1,20 @@
version: "3.7"
services:
mc:
image: itzg/minecraft-server
ports:
- 25565:25565
volumes:
# Attach .../Curse/Minecraft/Instances for use at /instances
- ./Instances:/instances:ro
# Attach /data as usual
- ./ServerData:/data
environment:
EULA: "TRUE"
# Modpacks generally need more memory, so let's give at 2 GB
MEMORY: 2G
# Use new CURSE_INSTANCE type
TYPE: CURSE_INSTANCE
# Reference directory of or full path to minecraftinstance.json
CURSE_INSTANCE_JSON: /instances/FTB Presents SkyFactory 3

View File

@@ -0,0 +1,23 @@
version: "3.7"
services:
mc:
image: itzg/minecraft-server
ports:
# expose the Minecraft server port outside of container
- 25565:25565
environment:
# REQUIRED for all types
EULA: "TRUE"
# Set server type (vs the default of vanilla)
TYPE: FORGE
volumes:
# use a named, managed volume for data volume
- mc_forge:/data
# attach local host directory "mods" in same directory as this compose file
# all mods in this directory get copied into /data/mods at startup
- ./mods:/mods:ro
volumes:
# declared the named volume, but use default/local storage engine
mc_forge: {}

View File

@@ -1,16 +0,0 @@
version: '3.2'
services:
mc:
image: itzg/minecraft-server
environment:
EULA: "true"
TYPE: FTB
FTB_SERVER_MOD: https://www.feed-the-beast.com/projects/ftb-presents-skyfactory-3/files/2481284
ports:
- 25565:25565
volumes:
- mc-ftb:/data
volumes:
mc-ftb:

View File

@@ -0,0 +1,23 @@
version: "3.7"
services:
mc:
# FTBA support is only available in multiarch image tag
image: itzg/minecraft-server:multiarch
ports:
# expose the Minecraft server port outside of container
- 25565:25565
environment:
# REQUIRED for all types
EULA: "TRUE"
# Set server type (vs the default of vanilla)
TYPE: FTBA
# Use Pack ID from https://ftb.neptunepowered.org/pack/ftb-presents-direwolf20-1-12/
FTB_MODPACK_ID: "31"
volumes:
# use a named, managed volume for data volume
- mc_ftb:/data
volumes:
# declared the named volume, but use default/local storage engine
mc_ftb: {}

View File

@@ -0,0 +1,11 @@
version: "3.7"
services:
mc:
image: itzg/minecraft-server
ports:
- 25565:25565
environment:
EULA: "TRUE"
VERSION: 1.7.2
WORLD: https://www.minecraftmaps.com/survival-maps/cube-survival/download

View File

@@ -0,0 +1,50 @@
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: example
name: example
spec:
replicas: 1
serviceName: example
selector:
matchLabels:
app: example
template:
metadata:
labels:
app: example
spec:
containers:
- name: mc
image: itzg/minecraft-server
env:
- name: EULA
value: "TRUE"
volumeMounts:
- mountPath: /data
name: data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
labels:
service: example
name: example
spec:
ports:
- port: 25565
targetPort: 25565
selector:
app: example
type: LoadBalancer

1
examples/modpacks/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.zip

View File

@@ -0,0 +1,3 @@
Please server [modpacks downloaded from CurseForge](https://www.curseforge.com/minecraft/modpacks) in this directory.
The example [`docker-compose-curseforge.yml`](../docker-compose-curseforge.yml) references a modpack downloaded from <https://www.curseforge.com/minecraft/modpacks/skyfactory-4/files/2787018>.

View File

@@ -0,0 +1,5 @@
FROM itzg/minecraft-server
ENV TYPE=PAPER
COPY plugins/*.jar /plugins/

View File

@@ -0,0 +1,11 @@
version: '3.7'
services:
mc:
build: .
environment:
EULA: "TRUE"
ports:
- 25565:25565
stdin_open: true
tty: true

View File

@@ -0,0 +1 @@
*.jar

View File

@@ -0,0 +1 @@
Download Bukkit/Spigot plugin jars, such as [WorldEdit](https://dev.bukkit.org/projects/worldedit/files) and place them here. At image build time the `COPY` step will place those jars in `/plugins`. At container startup, the contents of `/plugins` are sync'ed into `/data/plugins` for use with Bukkit/Spigot/Paper server types.

View File

@@ -0,0 +1,97 @@
#!/bin/bash
. /autopause/autopause-fcns.sh
. /start-utils
sudo /usr/sbin/knockd -c /autopause/knockd-config.cfg -d
if [ $? -ne 0 ] ; then
while :
do
if [[ -n $(ps -o comm | grep java) ]] ; then
break
fi
sleep 0.1
done
logAutopause "Failed to start knockd daemon."
logAutopause "Possible cause: docker's host network mode."
logAutopause "Recreate without host mode or disable autopause functionality."
logAutopause "Stopping server."
killall -SIGTERM java
exit 1
fi
STATE=INIT
while :
do
case X$STATE in
XINIT)
# Server startup
if mc_server_listening ; then
TIME_THRESH=$(($(current_uptime)+$AUTOPAUSE_TIMEOUT_INIT))
logAutopause "MC Server listening for connections - stopping in $AUTOPAUSE_TIMEOUT_INIT seconds"
STATE=K
fi
;;
XK)
# Knocked
if java_clients_connected ; then
logAutopause "Client connected - waiting for disconnect"
STATE=E
else
if [[ $(current_uptime) -ge $TIME_THRESH ]] ; then
logAutopause "No client connected since startup / knocked - stopping"
/autopause/pause.sh
STATE=S
fi
fi
;;
XE)
# Established
if ! java_clients_connected ; then
TIME_THRESH=$(($(current_uptime)+$AUTOPAUSE_TIMEOUT_EST))
logAutopause "All clients disconnected - stopping in $AUTOPAUSE_TIMEOUT_EST seconds"
STATE=I
fi
;;
XI)
# Idle
if java_clients_connected ; then
logAutopause "Client reconnected - waiting for disconnect"
STATE=E
else
if [[ $(current_uptime) -ge $TIME_THRESH ]] ; then
logAutopause "No client reconnected - stopping"
/autopause/pause.sh
STATE=S
fi
fi
;;
XS)
# Stopped
if rcon_client_exists ; then
/autopause/resume.sh
fi
if java_running ; then
if java_clients_connected ; then
logAutopause "Client connected - waiting for disconnect"
STATE=E
else
TIME_THRESH=$(($(current_uptime)+$AUTOPAUSE_TIMEOUT_KN))
logAutopause "Server was knocked - waiting for clients or timeout"
STATE=K
fi
fi
;;
*)
logAutopause "Error: invalid state: $STATE"
;;
esac
if [[ "$STATE" == "S" ]] ; then
# before rcon times out
sleep 2
else
sleep $AUTOPAUSE_PERIOD
fi
done

View File

@@ -0,0 +1,38 @@
#!/bin/bash
current_uptime() {
echo $(awk '{print $1}' /proc/uptime | cut -d . -f 1)
}
java_running() {
[[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]]
}
rcon_client_exists() {
[[ -n "$(ps -a -o comm | grep 'rcon-cli')" ]]
}
mc_server_listening() {
[[ -n $(netstat -tln | grep "0.0.0.0:$SERVER_PORT" | grep LISTEN) ]]
}
java_clients_connected() {
local connections
connections=$(netstat -tn | grep ":$SERVER_PORT" | grep ESTABLISHED)
if [[ -z "$connections" ]] ; then
return 1
fi
IFS=$'\n'
connections=($connections)
unset IFS
# check that at least one external address is not localhost
# remember, that the host network mode does not work with autopause because of the knockd utility
for (( i=0; i<${#connections[@]}; i++ ))
do
if [[ ! $(echo "${connections[$i]}" | awk '{print $5}') =~ ^\s*127\.0\.0\.1:.*$ ]] ; then
# not localhost
return 0
fi
done
return 1
}

View File

@@ -0,0 +1,12 @@
[options]
logfile = /dev/null
[unpauseMCServer-server]
sequence = 25565
seq_timeout = 1
command = /sbin/su-exec minecraft:minecraft /autopause/resume.sh
tcpflags = syn
[unpauseMCServer-rcon]
sequence = 25575
seq_timeout = 1
command = /sbin/su-exec minecraft:minecraft /autopause/resume.sh
tcpflags = syn

21
files/autopause/pause.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
. /start-utils
if [[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]] ; then
# save world
rcon-cli save-all >/dev/null
# wait until mc-monitor is no longer connected to the server
while :
do
if [[ -z "$(netstat -nt | grep "127.0.0.1:$SERVER_PORT" | grep 'ESTABLISHED')" ]]; then
break
fi
sleep 0.1
done
# finally pause the process
logAutopauseAction "Pausing Java process"
killall -q -STOP java
fi

8
files/autopause/resume.sh Executable file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
. /start-utils
if [[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^T.*$ ]] ; then
logAutopauseAction "Knocked, resuming Java process"
killall -q -CONT java
fi

2
files/sudoers-mc Normal file
View File

@@ -0,0 +1,2 @@
%minecraft ALL=(ALL) NOPASSWD:/usr/bin/killall
%minecraft ALL=(ALL) NOPASSWD:/usr/sbin/knockd

11
health.sh Normal file
View File

@@ -0,0 +1,11 @@
#!/bin/bash
. /start-utils
if isTrue "${ENABLE_AUTOPAUSE}" && [[ "$( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }')" =~ ^T.*$ ]]; then
echo "Java process suspended by Autopause function"
exit 0
else
mc-monitor status --host localhost --port $SERVER_PORT
exit $?
fi

34
log4j2.xml Normal file
View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" packages="com.mojang.util">
<Appenders>
<Console name="SysOut" target="SYSTEM_OUT">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
</Console>
<Queue name="ServerGuiConsole">
<PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n" />
</Queue>
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
<Policies>
<TimeBasedTriggeringPolicy />
<OnStartupTriggeringPolicy />
</Policies>
<DefaultRolloverStrategy>
<Delete basePath="logs">
<IfFileName glob="*.log.gz" />
<IfLastModified age="7d" />
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<Root level="info">
<filters>
<MarkerFilter marker="NETWORK_PACKETS" onMatch="DENY" onMismatch="NEUTRAL" />
</filters>
<AppenderRef ref="SysOut"/>
<AppenderRef ref="File"/>
<AppenderRef ref="ServerGuiConsole"/>
</Root>
</Loggers>
</Configuration>

View File

@@ -1,7 +0,0 @@
.[] |
select(.elements | length > 1) |
select(.elements[].elements[] | select(.class == "version" and .text == $version)) |
.elements[].elements[] |
select(.class|contains("server-jar")) |
.elements[] | select(.name="a") |
.href

18
mcstatus Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
echo "WARNING: mcstatus is deprecated; calling mc-monitor instead"
##### mcstatus shim for mc-monitor
# handles translating calls to
# mcstatus (host:port) (command)
# where the actual command is ignore, but is typically ping or status
addr="$1"
IFS=':'
read -a parts <<< "${addr}"
if [[ ${#parts[*]} -gt 1 ]]; then
exec mc-monitor status --host ${parts[0]} --port ${parts[1]}
else
exec mc-monitor status --host ${parts[0]}
fi

View File

@@ -22,6 +22,7 @@ snooper-enabled=true
texture-pack=
online-mode=true
resource-pack=
resource-pack-sha1=
pvp=true
difficulty=1
enable-command-block=true

41
start
View File

@@ -1,22 +1,51 @@
#!/bin/bash
. /start-utils
umask 0002
chmod g+w /data
if [ $(id -u) = 0 ]; then
if [[ -v UID && $UID != $(id -u) ]]; then
usermod -u $UID minecraft
runAsUser=minecraft
runAsGroup=minecraft
if [[ -v UID ]]; then
if [[ $UID != 0 ]]; then
if [[ $UID != $(id -u minecraft) ]]; then
log "Changing uid of minecraft to $UID"
usermod -u $UID minecraft
fi
else
runAsUser=root
fi
fi
if [[ -v GID ]]; then
groupmod -o -g $GID minecraft
if [[ $GID != 0 ]]; then
if [[ $GID != $(id -g minecraft) ]]; then
log "Changing gid of minecraft to $GID"
groupmod -o -g $GID minecraft
fi
else
runAsGroup=root
fi
fi
if [[ $(stat -c "%u" /data) != $UID ]]; then
echo "Changing ownership of /data to $UID ..."
chown -R minecraft:minecraft /data
log "Changing ownership of /data to $UID ..."
chown -R ${runAsUser}:${runAsGroup} /data
fi
exec su-exec minecraft:minecraft /start-configuration $@
if [[ $(stat -c "%u" /autopause) != $UID ]]; then
log "Changing ownership of /autopause to $UID ..."
chown -R ${runAsUser}:${runAsGroup} /autopause
fi
if [[ ${SKIP_NSSWITCH_CONF^^} != TRUE ]]; then
echo 'hosts: files dns' > /etc/nsswitch.conf
fi
exec su-exec ${runAsUser}:${runAsGroup} /start-configuration $@
else
exec /start-configuration $@
fi

60
start-autopause Executable file
View File

@@ -0,0 +1,60 @@
#!/bin/bash
. /start-utils
log "Autopause functionality enabled"
# update server port to listen to
regseq="^\s*sequence\s*=\s*$SERVER_PORT\s*$"
linenum=$(grep -nm1 sequence /autopause/knockd-config.cfg | cut -d : -f 1 | tail -n1)
if ! [[ $(awk "NR==$linenum" /autopause/knockd-config.cfg) =~ $regseq ]]; then
sed -i "${linenum}s/sequence.*/sequence = $SERVER_PORT/" /autopause/knockd-config.cfg
log "Updated server port in knockd config"
fi
# update rcon port to listen to
regseq="^\s*sequence\s*=\s*$RCON_PORT\s*$"
linenum=$(grep -nm2 sequence /autopause/knockd-config.cfg | cut -d : -f 1 | tail -n1)
if ! [[ $(awk "NR==$linenum" /autopause/knockd-config.cfg) =~ $regseq ]]; then
sed -i "${linenum}s/sequence.*/sequence = $RCON_PORT/" /autopause/knockd-config.cfg
log "Updated rcon port in knockd config"
fi
if ! [[ $AUTOPAUSE_PERIOD =~ ^[0-9]+$ ]]; then
AUTOPAUSE_PERIOD=10
export AUTOPAUSE_PERIOD
log "Warning: AUTOPAUSE_PERIOD is not numeric, set to 10 (seconds)"
fi
if [ "$AUTOPAUSE_PERIOD" -eq "0" ] ; then
AUTOPAUSE_PERIOD=10
export AUTOPAUSE_PERIOD
log "Warning: AUTOPAUSE_PERIOD must not be 0, set to 10 (seconds)"
fi
if ! [[ $AUTOPAUSE_TIMEOUT_KN =~ ^[0-9]+$ ]] ; then
AUTOPAUSE_TIMEOUT_KN=120
export AUTOPAUSE_TIMEOUT_KN
log "Warning: AUTOPAUSE_TIMEOUT_KN is not numeric, set to 120 (seconds)"
fi
if ! [[ $AUTOPAUSE_TIMEOUT_EST =~ ^[0-9]+$ ]] ; then
AUTOPAUSE_TIMEOUT_EST=3600
export AUTOPAUSE_TIMEOUT_EST
log "Warning: AUTOPAUSE_TIMEOUT_EST is not numeric, set to 3600 (seconds)"
fi
if ! [[ $AUTOPAUSE_TIMEOUT_INIT =~ ^[0-9]+$ ]] ; then
AUTOPAUSE_TIMEOUT_INIT=600
export AUTOPAUSE_TIMEOUT_INIT
log "Warning: AUTOPAUSE_TIMEOUT_INIT is not numeric, set to 600 (seconds)"
fi
if [[ -n $MAX_TICK_TIME ]] ; then
log "Warning: MAX_TICK_TIME is non-default, for autopause to work properly, this check should be disabled (-1 for versions >= 1.8.1)"
else
if versionLessThan 1.8.1; then
# 10 years
MAX_TICK_TIME=315360000000
else
MAX_TICK_TIME=-1
fi
export MAX_TICK_TIME
fi
/autopause/autopause-daemon.sh &

View File

@@ -1,33 +1,37 @@
#!/bin/bash
. /start-utils
shopt -s nullglob
#umask 002
export HOME=/data
if [ ! -e /data/eula.txt ]; then
if [ "$EULA" != "" ]; then
echo "# Generated via Docker on $(date)" > eula.txt
echo "eula=$EULA" >> eula.txt
if [ $? != 0 ]; then
echo "ERROR: unable to write eula to /data. Please make sure attached directory is writable by uid=${UID}"
exit 2
fi
else
echo ""
echo "Please accept the Minecraft EULA at"
echo " https://account.mojang.com/documents/minecraft_eula"
echo "by adding the following immediately after 'docker run':"
echo " -e EULA=TRUE"
echo ""
EULA="${EULA,,}"
if [ "$EULA" != "true" ]; then
log ""
log "Please accept the Minecraft EULA at"
log " https://account.mojang.com/documents/minecraft_eula"
log "by adding the following immediately after 'docker run':"
log " -e EULA=TRUE"
log ""
exit 1
fi
echo "# Generated via Docker on $(date)" > /data/eula.txt
if ! echo "eula=$EULA" >> /data/eula.txt; then
log "ERROR: unable to write eula to /data. Please make sure attached directory is writable by uid=${UID}"
exit 2
fi
fi
echo "Running as uid=$(id -u) gid=$(id -g) with /data as '$(ls -lnd /data)'"
log "Running as uid=$(id -u) gid=$(id -g) with /data as '$(ls -lnd /data)'"
if ! touch /data/.verify_access; then
echo "ERROR: /data doesn't seem to be writable. Please make sure attached directory is writable by uid=$(id -u)"
log "ERROR: /data doesn't seem to be writable. Please make sure attached directory is writable by uid=$(id -u)"
exit 2
fi
@@ -36,70 +40,87 @@ rm /data/.verify_access || true
if [[ $PROXY ]]; then
export http_proxy="$PROXY"
export https_proxy="$PROXY"
echo "INFO: Giving proxy time to startup..."
log "INFO: Giving proxy time to startup..."
sleep 5
fi
export SERVER_PROPERTIES=/data/server.properties
export VERSIONS_JSON=https://launchermeta.mojang.com/mc/game/version_manifest.json
echo "Checking version information."
case "X$VERSION" in
X|XLATEST|Xlatest)
export VANILLA_VERSION=`curl -fsSL $VERSIONS_JSON | jq -r '.latest.release'`
VANILLA_VERSION=$(curl -fsSL $VERSIONS_JSON | jq -r '.latest.release')
;;
XSNAPSHOT|Xsnapshot)
export VANILLA_VERSION=`curl -fsSL $VERSIONS_JSON | jq -r '.latest.snapshot'`
VANILLA_VERSION=$(curl -fsSL $VERSIONS_JSON | jq -r '.latest.snapshot')
;;
X[1-9]*)
export VANILLA_VERSION=$VERSION
VANILLA_VERSION=$VERSION
;;
*)
export VANILLA_VERSION=`curl -fsSL $VERSIONS_JSON | jq -r '.latest.release'`
VANILLA_VERSION=$(curl -fsSL $VERSIONS_JSON | jq -r '.latest.release')
;;
esac
export VANILLA_VERSION
log "Resolved version given ${VERSION} into ${VANILLA_VERSION}"
cd /data
cd /data || exit 1
export ORIGINAL_TYPE=${TYPE^^}
echo "Checking type information."
if isTrue "${ENABLE_AUTOPAUSE}"; then
/start-autopause
fi
log "Resolving type given ${TYPE}"
case "${TYPE^^}" in
*BUKKIT|SPIGOT)
exec /start-deployBukkitSpigot $@
exec /start-deployBukkitSpigot "$@"
;;
PAPER)
exec /start-deployPaper $@
exec /start-deployPaper "$@"
;;
TUINITY)
exec /start-deployTuinity "$@"
;;
FORGE)
exec /start-deployForge $@
exec /start-deployForge "$@"
;;
FABRIC)
exec /start-deployFabric $@
exec /start-deployFabric "$@"
;;
FTB|CURSEFORGE)
exec /start-deployFTB $@
exec /start-deployFTB "$@"
;;
VANILLA)
exec /start-deployVanilla $@
exec /start-deployVanilla "$@"
;;
SPONGEVANILLA)
exec /start-deploySpongeVanilla $@
exec /start-deploySpongeVanilla "$@"
;;
CUSTOM)
exec /start-deployCustom $@
exec /start-deployCustom "$@"
;;
CURSE_INSTANCE)
exec /start-validateCurseInstance "$@"
;;
MAGMA)
exec /start-magma "$@"
;;
*)
echo "Invalid type: '$TYPE'"
echo "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTB, CURSEFORGE, SPONGEVANILLA"
log "Invalid type: '$TYPE'"
log "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTB, CURSEFORGE, SPONGEVANILLA"
exit 1
;;

View File

@@ -1,24 +1,44 @@
#!/bin/bash
. /start-utils
set -e
function buildSpigotFromSource {
echo "Building Spigot $VANILLA_VERSION from source, might take a while, get some coffee"
if [[ ${TYPE^^} = *BUKKIT ]] && ! versionLessThan "1.14"; then
log "ERR craftbukkit build is only supported for versions less than 1.14"
exit 1
fi
log "Building Spigot $VANILLA_VERSION from source, might take a while, get some coffee"
rm -rf /data/temp
mkdir /data/temp
cd /data/temp
jvmOpts="-Xms${INIT_MEMORY:-$MEMORY} -Xmx${MAX_MEMORY:-$MEMORY}"
logn ''
curl -sSL -o /data/temp/BuildTools.jar https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar && \
java $jvmOpts -jar /data/temp/BuildTools.jar --rev $VANILLA_VERSION 2>&1 |tee /data/spigot_build.log| while read l; do echo -n .; done; echo "done"
if ! mv spigot-*.jar /data/spigot_server.jar; then
echo "ERR failed to build Spigot"
cat /data/spigot_build.log
exit 1
fi
mv craftbukkit-*.jar /data/craftbukkit_server.jar
echo "Cleaning up"
java $jvmOpts -jar /data/temp/BuildTools.jar --rev $VANILLA_VERSION 2>&1 |tee /data/spigot_build.log| while read l; do echo -n .; done; log "done"
case ${TYPE^^} in
SPIGOT)
if ! mv spigot-*.jar /data/${SERVER}; then
log "ERR failed to build Spigot"
cat /data/spigot_build.log
exit 1
fi
;;
*BUKKIT)
if ! mv craftbukkit-*.jar /data/${SERVER}; then
log "ERR failed to build Spigot"
cat /data/spigot_build.log
exit 1
fi
;;
esac
log "Cleaning up"
rm -rf /data/temp
cd /data
}
@@ -38,18 +58,11 @@ function downloadSpigot {
;;
esac
local downloadVersion
if [[ ${VERSION} == LATEST ]]; then
downloadVersion=${VANILLA_VERSION}
else
downloadVersion=${VERSION}
fi
if [[ -z $downloadUrl ]]; then
downloadUrl="https://cdn.getbukkit.org/${getbukkitFlavor}/${getbukkitFlavor}-${downloadVersion}.jar"
downloadUrl="https://cdn.getbukkit.org/${getbukkitFlavor}/${getbukkitFlavor}-${VANILLA_VERSION}.jar"
fi
echo "Downloading $match from $downloadUrl ..."
log "Downloading $match from $downloadUrl ..."
curl -fsSL -o $SERVER "$downloadUrl"
if [[ $? != 0 || $(grep -c "DOCTYPE html" $SERVER) != 0 ]]; then
cat <<EOF
@@ -61,20 +74,23 @@ ERROR: failed to download from $downloadUrl
EOF
exit 3
fi
JVM_OPTS="${JVM_OPTS} -DIReallyKnowWhatIAmDoingISwear"
export JVM_OPTS
}
case "$TYPE" in
*BUKKIT|*bukkit)
export SERVER=craftbukkit_server.jar
export SERVER=craftbukkit_server-${VANILLA_VERSION}.jar
;;
*)
export SERVER=spigot_server.jar
export SERVER=spigot_server-${VANILLA_VERSION}.jar
;;
esac
if [ ! -f $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
if [[ "$BUILD_SPIGOT_FROM_SOURCE" = TRUE || "$BUILD_SPIGOT_FROM_SOURCE" = true || "$BUILD_FROM_SOURCE" = TRUE || "$BUILD_FROM_SOURCE" = true ]]; then
if isTrue "$BUILD_SPIGOT_FROM_SOURCE" || isTrue "$BUILD_FROM_SOURCE"; then
buildSpigotFromSource
else
downloadSpigot
@@ -83,6 +99,7 @@ fi
# Normalize on Spigot for operations below
export TYPE=SPIGOT
export SKIP_LOG4J_CONFIG=true
# Continue to Final Setup
exec /start-finalSetup01World $@

View File

@@ -7,23 +7,25 @@ if isURL ${CUSTOM_SERVER}; then
export SERVER=/data/${filename}
if [[ -f ${SERVER} ]] || [ -n "$FORCE_REDOWNLOAD" ]; then
echo "Using previously downloaded jar at ${SERVER}"
log "Using previously downloaded jar at ${SERVER}"
else
echo "Downloading custom server jar from ${CUSTOM_SERVER} ..."
log "Downloading custom server jar from ${CUSTOM_SERVER} ..."
if ! curl -sSL -o ${SERVER} ${CUSTOM_SERVER}; then
echo "Failed to download from ${CUSTOM_SERVER}"
log "Failed to download from ${CUSTOM_SERVER}"
exit 2
fi
fi
elif [[ -f ${CUSTOM_SERVER} ]]; then
echo "Using custom server jar at ${CUSTOM_SERVER} ..."
log "Using custom server jar at ${CUSTOM_SERVER} ..."
export SERVER=${CUSTOM_SERVER}
else
echo "CUSTOM_SERVER is not properly set to a URL or existing jar file"
log "CUSTOM_SERVER is not properly set to a URL or existing jar file"
exit 2
fi
export SKIP_LOG4J_CONFIG=true
# Continue to Final Setup
exec /start-finalSetup01World $@

View File

@@ -8,20 +8,25 @@ export TYPE=FEED-THE-BEAST
FTB_SERVER_MOD=${FTB_SERVER_MOD:-$CF_SERVER_MOD}
echo "Looking for Feed-The-Beast / CurseForge server modpack."
log "Looking for Feed-The-Beast / CurseForge server modpack."
if [[ -z $FTB_SERVER_MOD ]]; then
echo "Environment variable FTB_SERVER_MOD not set."
echo "Set FTB_SERVER_MOD to the file name of the FTB server modpack."
echo "(And place the modpack in the /data directory.)"
log "Environment variable FTB_SERVER_MOD not set."
log "Set FTB_SERVER_MOD to the file name of the FTB server modpack."
log "(And place the modpack in the /data directory.)"
exit 2
fi
entryScriptExpr="-name ServerStart.sh -o -name ServerStartLinux.sh -o -name LaunchServer.sh"
entryScriptExpr="
-name ServerStart.sh
-o -name ServerStartLinux.sh
-o -name LaunchServer.sh
-o -name server-start.sh
"
if [[ -d ${FTB_BASE_DIR} ]]; then
startScriptCount=$(find ${FTB_BASE_DIR} $entryScriptExpr |wc -l)
if [[ $startScriptCount > 1 ]]; then
echo "Conflicting FTB/CurseForge packages have been installed. Please cleanup ${FTB_BASE_DIR}"
log "Conflicting FTB/CurseForge packages have been installed. Please cleanup ${FTB_BASE_DIR}"
exit 2
fi
else
@@ -45,7 +50,7 @@ if [[ $startScriptCount = 0 ]]; then
file=$(basename $(dirname $srv_modpack))
downloaded=/data/${file}.zip
if [ ! -e $downloaded ]; then
echo "Downloading FTB modpack...
log "Downloading FTB modpack...
$srv_modpack -> $downloaded"
curl -sSL -o $downloaded $srv_modpack
fi
@@ -60,26 +65,28 @@ if [[ $startScriptCount = 0 ]]; then
srv_modpack=/data/${srv_modpack}
fi
if [[ ! -f ${srv_modpack} ]]; then
echo "FTB server modpack ${srv_modpack} not found."
log "FTB server modpack ${srv_modpack} not found."
exit 2
fi
if [[ ! ${srv_modpack: -4} == ".zip" ]]; then
echo "FTB server modpack ${srv_modpack} is not a zip archive."
echo "Please set FTB_SERVER_MOD to a file with a .zip extension."
log "FTB server modpack ${srv_modpack} is not a zip archive."
log "Please set FTB_SERVER_MOD to a file with a .zip extension."
exit 2
fi
echo "Unpacking FTB server modpack ${srv_modpack} ..."
log "Unpacking FTB server modpack ${srv_modpack} ..."
mkdir -p ${FTB_BASE_DIR}
unzip -o ${srv_modpack} -d ${FTB_BASE_DIR} | awk '{printf "."} END {print ""}'
fi
if [[ $(find ${FTB_BASE_DIR} $entryScriptExpr | wc -l) = 0 ]]; then
forgeJar=$(find ${FTB_BASE_DIR} -name 'forge*.jar' -a -not -name 'forge*installer')
# Allow up to 2 levels since some modpacks have a top-level directory named
# for the modpack
forgeJar=$(find ${FTB_BASE_DIR} -maxdepth 2 -name 'forge*.jar' -a -not -name 'forge*installer')
if [[ "$forgeJar" ]]; then
export FTB_BASE_DIR=$(dirname "${forgeJar}")
echo "No entry script found, so building one for ${forgeJar}"
log "No entry script found, so building one for ${forgeJar}"
cat > "${FTB_BASE_DIR}/ServerStart.sh" <<EOF
#!/bin/sh
. ./settings-local.sh
@@ -87,18 +94,18 @@ java \${JAVA_PARAMETERS} -Xmx\${MAX_RAM} -jar $(basename "${forgeJar}") nogui
EOF
chmod +x "${FTB_BASE_DIR}/ServerStart.sh"
else
echo "Please make sure you are using the server version of the FTB modpack!"
log "Please make sure you are using the server version of the FTB modpack!"
exit 2
fi
fi
scriptCount=$(find "${FTB_BASE_DIR}" $entryScriptExpr | wc -l)
if [[ $scriptCount = 0 ]]; then
echo "Please make sure you are using the server version of the FTB modpack!"
log "Please make sure you are using the server version of the FTB modpack!"
exit 2
elif [[ $scriptCount > 1 ]]; then
echo "Ambigous startup scripts in FTB modpack!"
echo "found:"
log "Ambigous startup scripts in FTB modpack!"
log "found:"
find ${FTB_BASE_DIR} $entryScriptExpr
exit 2
fi
@@ -107,12 +114,13 @@ export FTB_SERVER_START=$(find "${FTB_BASE_DIR}" $entryScriptExpr)
export FTB_DIR=$(dirname "${FTB_SERVER_START}")
chmod a+x "${FTB_SERVER_START}"
sed -i 's/-jar/-Dfml.queryResult=confirm -jar/' "${FTB_SERVER_START}"
grep fml.queryResult=confirm ${FTB_SERVER_START} > /dev/null || \
sed -i 's/-jar/-Dfml.queryResult=confirm -jar/' "${FTB_SERVER_START}"
sed -i 's/.*read.*Restart now/#\0/' "${FTB_SERVER_START}"
legacyJavaFixerPath="${FTB_DIR}/mods/legacyjavafixer.jar"
if isTrue ${FTB_LEGACYJAVAFIXER} && [ ! -e "${legacyJavaFixerPath}" ]; then
echo "Installing legacy java fixer to ${legacyJavaFixerPath}"
log "Installing legacy java fixer to ${legacyJavaFixerPath}"
curl -sSL -o "${legacyJavaFixerPath}" ${legacyJavaFixerUrl}
fi

View File

@@ -1,5 +1,7 @@
#!/bin/bash
set -u
set -eu
. /start-utils
export TYPE=FABRIC
@@ -7,11 +9,10 @@ FABRIC_INSTALLER=${FABRIC_INSTALLER:-}
FABRIC_INSTALLER_URL=${FABRIC_INSTALLER_URL:-}
FABRICVERSION=${FABRICVERSION:-LATEST}
if [[ -z $FABRIC_INSTALLER && -z $FABRIC_INSTALLER_URL ]]; then
echo "Checking Fabric version information."
log "Checking Fabric version information."
case $FABRICVERSION in
LATEST)
curl -fsSL https://maven.fabricmc.net/net/fabricmc/fabric-installer/maven-metadata.xml | xq -c . > /tmp/fabric.json
FABRIC_VERSION=$(< /tmp/fabric.json jq -r ".metadata.versioning.release")
FABRIC_VERSION=$(maven-metadata-release https://maven.fabricmc.net/net/fabricmc/fabric-installer/maven-metadata.xml)
;;
*)
@@ -24,29 +25,34 @@ if [[ -z $FABRIC_INSTALLER && -z $FABRIC_INSTALLER_URL ]]; then
elif [[ -z $FABRIC_INSTALLER ]]; then
FABRIC_INSTALLER="/tmp/fabric-installer.jar"
elif [[ ! -e $FABRIC_INSTALLER ]]; then
echo "ERROR: the given Fabric installer doesn't exist : $FABRIC_INSTALLER"
log "ERROR: the given Fabric installer doesn't exist : $FABRIC_INSTALLER"
exit 2
fi
installMarker=".fabric-installed-${FABRIC_VERSION:-manual}"
installMarker="/data/.fabric-installed-${VANILLA_VERSION}-${FABRIC_VERSION:-manual}"
debug Checking for installMarker ${installMarker}
if [[ ! -e $installMarker ]]; then
if [[ ! -e $FABRIC_INSTALLER ]]; then
if [[ -z $FABRIC_INSTALLER_URL ]]; then
echo "Downloading $FABRIC_VERSION"
log "Downloading $FABRIC_VERSION"
downloadUrl="https://maven.fabricmc.net/net/fabricmc/fabric-installer/$FABRIC_VERSION/fabric-installer-$FABRIC_VERSION.jar"
echo "...trying $downloadUrl"
log "...trying $downloadUrl"
curl -o $FABRIC_INSTALLER -fsSL $downloadUrl
else
echo "Downloading $FABRIC_INSTALLER_URL ..."
log "Downloading $FABRIC_INSTALLER_URL ..."
if ! curl -o $FABRIC_INSTALLER -fsSL $FABRIC_INSTALLER_URL; then
echo "Failed to download from given location $FABRIC_INSTALLER_URL"
log "Failed to download from given location $FABRIC_INSTALLER_URL"
exit 2
fi
fi
fi
echo "Installing Fabric $FABRIC_VERSION using $FABRIC_INSTALLER"
if isDebugging; then
debug "Installing Fabric $FABRIC_VERSION using $FABRIC_INSTALLER with mcversion ${VANILLA_VERSION}"
else
log "Installing Fabric $FABRIC_VERSION using $FABRIC_INSTALLER"
fi
tries=3
set +e
while ((--tries >= 0)); do
@@ -57,11 +63,11 @@ if [[ ! -e $installMarker ]]; then
done
set -e
if (($tries < 0)); then
echo "Fabric failed to install after several tries." >&2
log "Fabric failed to install after several tries." >&2
exit 10
fi
export SERVER=fabric-server-launch.jar
echo "Using server $SERVER"
log "Using server $SERVER"
echo $SERVER > $installMarker
else

View File

@@ -1,5 +1,7 @@
#!/bin/bash
. /start-utils
export TYPE=FORGE
if [[ -z $FORGE_INSTALLER && -z $FORGE_INSTALLER_URL ]]; then
@@ -14,7 +16,7 @@ if [[ -z $FORGE_INSTALLER && -z $FORGE_INSTALLER_URL ]]; then
#################################################################################
echo "Checking Forge version information."
log "Checking Forge version information."
case $FORGEVERSION in
RECOMMENDED)
curl -fsSL -o /tmp/forge.json http://files.minecraftforge.net/maven/net/minecraftforge/forge/promotions_slim.json
@@ -22,8 +24,8 @@ if [[ -z $FORGE_INSTALLER && -z $FORGE_INSTALLER_URL ]]; then
if [ $FORGE_VERSION = null ]; then
FORGE_VERSION=$(cat /tmp/forge.json | jq -r ".promos[\"$VANILLA_VERSION-latest\"]")
if [ $FORGE_VERSION = null ]; then
echo "ERROR: Version $VANILLA_VERSION is not supported by Forge"
echo " Refer to http://files.minecraftforge.net/ for supported versions"
log "ERROR: Version $VANILLA_VERSION is not supported by Forge"
log " Refer to http://files.minecraftforge.net/ for supported versions"
exit 2
fi
fi
@@ -41,17 +43,17 @@ if [[ -z $FORGE_INSTALLER && -z $FORGE_INSTALLER_URL ]]; then
elif [[ -z $FORGE_INSTALLER ]]; then
FORGE_INSTALLER="/tmp/forge-installer.jar"
elif [[ ! -e $FORGE_INSTALLER ]]; then
echo "ERROR: the given Forge installer doesn't exist : $FORGE_INSTALLER"
log "ERROR: the given Forge installer doesn't exist : $FORGE_INSTALLER"
exit 2
fi
installMarker=".forge-installed-$shortForgeVersion"
installMarker="/data/.forge-installed-$shortForgeVersion"
if [ ! -e $installMarker ]; then
if [ ! -e $FORGE_INSTALLER ]; then
if [[ -z $FORGE_INSTALLER_URL ]]; then
echo "Downloading $normForgeVersion"
log "Downloading $normForgeVersion"
forgeFileNames="
$normForgeVersion/forge-$normForgeVersion-installer.jar
@@ -60,25 +62,25 @@ if [ ! -e $installMarker ]; then
"
for fn in $forgeFileNames; do
if [ $fn == END ]; then
echo "Unable to compute URL for $normForgeVersion"
log "Unable to compute URL for $normForgeVersion"
exit 2
fi
downloadUrl=http://files.minecraftforge.net/maven/net/minecraftforge/forge/$fn
echo "...trying $downloadUrl"
log "...trying $downloadUrl"
if curl -o $FORGE_INSTALLER -fsSL $downloadUrl; then
break
fi
done
else
echo "Downloading $FORGE_INSTALLER_URL ..."
log "Downloading $FORGE_INSTALLER_URL ..."
if ! curl -o $FORGE_INSTALLER -fsSL $FORGE_INSTALLER_URL; then
echo "Failed to download from given location $FORGE_INSTALLER_URL"
log "Failed to download from given location $FORGE_INSTALLER_URL"
exit 2
fi
fi
fi
echo "Installing Forge $shortForgeVersion using $FORGE_INSTALLER"
log "Installing Forge $shortForgeVersion using $FORGE_INSTALLER"
mkdir -p mods
tries=3
while ((--tries >= 0)); do
@@ -88,22 +90,22 @@ if [ ! -e $installMarker ]; then
fi
done
if (($tries < 0)); then
echo "Forge failed to install after several tries." >&2
log "Forge failed to install after several tries." >&2
exit 10
fi
# NOTE $shortForgeVersion will be empty if installer location was given to us
echo "Finding installed server jar..."
log "Finding installed server jar..."
unset -v latest
for file in *forge*.jar; do
[[ $file =~ installer ]] || [[ $file -nt $latest ]] && latest=$file
done
if [[ -z $latest ]]; then
echo "Unable to derive server jar for Forge"
log "Unable to derive server jar for Forge"
exit 2
fi
export SERVER=$latest
echo "Using server $SERVER"
log "Using server $SERVER"
echo $SERVER > $installMarker
else

View File

@@ -1,18 +1,23 @@
#!/bin/bash
export SERVER=paper_server.jar
if [ ! -f $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
downloadUrl=${PAPER_DOWNLOAD_URL:-https://papermc.io/api/v1/paper/${VANILLA_VERSION}/latest/download}
echo "Downloading Paper $VANILLA_VERSION from $downloadUrl ..."
curl -fsSL -o $SERVER "$downloadUrl"
if [ ! -f $SERVER ]; then
echo "ERROR: failed to download from $downloadUrl (status=$?)"
. /start-utils
: ${PAPERBUILD:=latest}
export SERVER=paper_server-${VANILLA_VERSION}-${PAPERBUILD}.jar
if [ ! -f "$SERVER" ] || [ -n "$FORCE_REDOWNLOAD" ]; then
downloadUrl=${PAPER_DOWNLOAD_URL:-https://papermc.io/api/v1/paper/${VANILLA_VERSION}/${PAPERBUILD}/download}
log "Downloading Paper $VANILLA_VERSION (build $PAPERBUILD) from $downloadUrl ..."
curl -fsSL -o "$SERVER" "$downloadUrl"
if [ ! -f "$SERVER" ]; then
log "ERROR: failed to download from $downloadUrl (status=$?)"
exit 3
fi
fi
# Normalize on Spigot for operations below
export TYPE=SPIGOT
export SKIP_LOG4J_CONFIG=true
# Continue to Final Setup
exec /start-finalSetup01World $@

View File

@@ -1,9 +1,11 @@
#!/bin/bash
. /start-utils
export TYPE=spongevanilla
# Parse branch
echo "Choosing branch for Sponge"
log "Choosing branch for Sponge"
case "$SPONGEBRANCH" in
EXPERIMENTAL|experimental|BLEEDING|bleeding)
@@ -18,7 +20,7 @@ esac
# If not SPONGEVERSION selected, detect last version on selected branch
if [ -z $SPONGEVERSION ]; then
echo "Choosing Version for Sponge"
log "Choosing Version for Sponge"
if [ "$SPONGEBRANCH" == "stable" ]; then
export SPONGEVERSION=`curl -fsSL https://dl-api.spongepowered.org/v1/org.spongepowered/$TYPE | jq -r '.buildTypes.stable.latest.version'`
else
@@ -29,7 +31,7 @@ fi
export SERVER="spongevanilla-$SPONGEVERSION.jar"
if [ ! -e $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
echo "Downloading $SERVER ..."
log "Downloading $SERVER ..."
curl -sSL -o $SERVER https://repo.spongepowered.org/maven/org/spongepowered/$TYPE/$SPONGEVERSION/$SERVER
fi

27
start-deployTuinity Normal file
View File

@@ -0,0 +1,27 @@
#!/bin/bash
. /start-utils
if [ "${VERSION}" != "LATEST" ]; then
log "ERROR: Tunity server type only supports VERSION=LATEST"
exit 1
fi
: ${TUNITY_BUILD:=lastSuccessfulBuild}
export SERVER=tunity-${VANILLA_VERSION}-${TUNITY_BUILD}.jar
if [ ! -f "$SERVER" ] || [ -n "$FORCE_REDOWNLOAD" ]; then
downloadUrl="https://ci.codemc.io/job/Spottedleaf/job/Tuinity/${TUNITY_BUILD}/artifact/tuinity-paperclip.jar"
log "Downloading Tunity (build $TUNITY_BUILD) from $downloadUrl ..."
curl -fsSL -o "$SERVER" "$downloadUrl"
if [ ! -f "$SERVER" ]; then
log "ERROR: failed to download from $downloadUrl (status=$?)"
exit 3
fi
fi
# Normalize on Spigot for operations below
export TYPE=SPIGOT
# Continue to Final Setup
exec /start-finalSetup01World $@

View File

@@ -1,21 +1,22 @@
#!/bin/bash
. /start-utils
isDebugging && set -x
set -o pipefail
export SERVER="minecraft_server.${VANILLA_VERSION// /_}.jar"
if [ ! -e $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
echo "Downloading $SERVER ..."
log "Downloading $SERVER ..."
debug "Finding version manifest for $VANILLA_VERSION"
versionManifestUrl=$(curl -fsSL 'https://launchermeta.mojang.com/mc/game/version_manifest.json' | jq --arg VANILLA_VERSION "$VANILLA_VERSION" --raw-output '[.versions[]|select(.id == $VANILLA_VERSION)][0].url')
result=$?
if [ $result != 0 ]; then
echo "ERROR failed to obtain version manifest URL ($result)"
log "ERROR failed to obtain version manifest URL ($result)"
exit 1
fi
if [ $versionManifestUrl = "null" ]; then
echo "ERROR couldn't find a matching manifest entry for $VANILLA_VERSION"
log "ERROR couldn't find a matching manifest entry for $VANILLA_VERSION"
exit 1
fi
debug "Found version manifest at $versionManifestUrl"
@@ -23,7 +24,7 @@ if [ ! -e $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
serverDownloadUrl=$(curl -fsSL ${versionManifestUrl} | jq --raw-output '.downloads.server.url')
result=$?
if [ $result != 0 ]; then
echo "ERROR failed to obtain version manifest from $versionManifestUrl ($result)"
log "ERROR failed to obtain version manifest from $versionManifestUrl ($result)"
exit 1
fi
@@ -34,10 +35,12 @@ if [ ! -e $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
curl $verbose -fsSL -o $SERVER $serverDownloadUrl
result=$?
if [ $result != 0 ]; then
echo "ERROR failed to download server from $serverDownloadUrl ($result)"
log "ERROR failed to download server from $serverDownloadUrl ($result)"
exit 1
fi
fi
isDebugging && ls -l
# Continue to Final Setup
exec /start-finalSetup01World $@

View File

@@ -1,50 +1,54 @@
#!/bin/bash
. /start-utils
set -e
isDebugging && set -x
if [ $TYPE = "FEED-THE-BEAST" ]; then
worldDest=$FTB_BASE_DIR/$LEVEL
else
worldDest=/data/$LEVEL
fi
# If no world exists and a URL for a world is supplied, download it and unpack
if [[ "$WORLD" ]] && [ ! -d "$worldDest" ]; then
case "X$WORLD" in
X[Hh][Tt][Tt][Pp]*)
echo "Downloading world from $WORLD"
curl -sSL -o - "$WORLD" > /data/world.zip
echo "Unzipping world"
unzip -o -q /data/world.zip
rm -f /data/world.zip
if [ ! -d $worldDest ]; then
echo World directory not found
for i in /data/*/level.dat; do
if [ -f "$i" ]; then
d=`dirname "$i"`
echo Renaming world directory from $d
mv -f "$d" $worldDest
fi
done
fi
if [ "$TYPE" = "SPIGOT" ]; then
# Reorganise if a Spigot server
echo "Moving End and Nether maps to Spigot location"
[ -d "$worldDest/DIM1" ] && mv -f "$worldDest/DIM1" "/data/${LEVEL}_the_end"
[ -d "$worldDest/DIM-1" ] && mv -f "$worldDest/DIM-1" "/data/${LEVEL}_nether"
fi
;;
*)
if [[ -d $WORLD ]]; then
if [[ ! -d $worldDest ]]; then
echo "Cloning world directory from $WORLD ..."
cp -r $WORLD $worldDest
else
echo "Skipping clone from $WORLD since $worldDest exists"
fi
if isURL $WORLD; then
curl -fsSL "$WORLD" -o /tmp/world.zip
zipSrc=/tmp/world.zip
elif [[ "$WORLD" =~ .*\.zip ]]; then
zipSrc="$WORLD"
fi
if [[ "$zipSrc" ]]; then
log "Unzipping world"
# Stage contents so that the correct subdirectory can be picked off
mkdir -p /tmp/world-data
(cd /tmp/world-data && unzip -o -q "$zipSrc")
baseDirs=$(find /tmp/world-data -name "level.dat" -exec dirname "{}" \;)
count=$(echo "$baseDirs" | wc -l)
if [[ $count -gt 1 ]]; then
baseDir="$(echo "$baseDirs" | sed -n ${WORLD_INDEX:-1}p)"
baseName=$(basename "$baseDir")
log "WARN multiple levels found, picking: $baseName"
elif [[ $count -gt 0 ]]; then
baseDir="$baseDirs"
else
echo "Invalid URL given for world: Must be HTTP or HTTPS and a ZIP file"
log "ERROR invalid world content"
exit 1
fi
;;
esac
mv "$baseDir" "$worldDest"
else
log "Cloning world directory from $WORLD ..."
cp -r "$WORLD" "$worldDest"
fi
if [ "$TYPE" = "SPIGOT" ]; then
# Reorganise if a Spigot server
log "Moving End and Nether maps to Spigot location"
[ -d "$worldDest/DIM1" ] && mv -f "$worldDest/DIM1" "/data/${LEVEL}_the_end"
[ -d "$worldDest/DIM-1" ] && mv -f "$worldDest/DIM-1" "/data/${LEVEL}_nether"
fi
fi
exec /start-finalSetup02Modpack $@

View File

@@ -1,5 +1,9 @@
#!/bin/bash
set -e
. /start-utils
# CURSE_URL_BASE used in manifest downloads below
CURSE_URL_BASE=${CURSE_URL_BASE:-https://minecraft.curseforge.com/projects}
@@ -17,28 +21,28 @@ if [[ "$MODPACK" ]]; then
EFFECTIVE_MODPACK_URL=$(curl -Ls -o /dev/null -w %{url_effective} $MODPACK)
case "X$EFFECTIVE_MODPACK_URL" in
X[Hh][Tt][Tt][Pp]*.zip)
echo "Downloading mod/plugin pack via HTTP"
echo " from $EFFECTIVE_MODPACK_URL ..."
log "Downloading mod/plugin pack via HTTP"
log " from $EFFECTIVE_MODPACK_URL ..."
if ! curl -sSL -o /tmp/modpack.zip "$EFFECTIVE_MODPACK_URL"; then
echo "ERROR: failed to download from $EFFECTIVE_MODPACK_URL"
log "ERROR: failed to download from $EFFECTIVE_MODPACK_URL"
exit 2
fi
if [ "$TYPE" = "SPIGOT" ]; then
mkdir -p /data/plugins
if ! unzip -o -d /data/plugins /tmp/modpack.zip; then
echo "ERROR: failed to unzip the modpack from $EFFECTIVE_MODPACK_URL"
log "ERROR: failed to unzip the modpack from $EFFECTIVE_MODPACK_URL"
fi
else
mkdir -p /data/mods
if ! unzip -o -d /data/mods /tmp/modpack.zip; then
echo "ERROR: failed to unzip the modpack from $EFFECTIVE_MODPACK_URL"
log "ERROR: failed to unzip the modpack from $EFFECTIVE_MODPACK_URL"
fi
fi
rm -f /tmp/modpack.zip
;;
*)
echo "Invalid URL given for modpack: Must be HTTP or HTTPS and a ZIP file"
log "Invalid URL given for modpack: Must be HTTP or HTTPS and a ZIP file"
;;
esac
fi
@@ -50,10 +54,10 @@ do
EFFECTIVE_MOD_URL=$(curl -Ls -o /dev/null -w %{url_effective} $i)
case "X$EFFECTIVE_MOD_URL" in
X[Hh][Tt][Tt][Pp]*.jar)
echo "Downloading mod/plugin via HTTP"
echo " from $EFFECTIVE_MOD_URL ..."
log "Downloading mod/plugin via HTTP"
log " from $EFFECTIVE_MOD_URL ..."
if ! curl -sSL -o /tmp/${EFFECTIVE_MOD_URL##*/} $EFFECTIVE_MOD_URL; then
echo "ERROR: failed to download from $EFFECTIVE_MOD_URL to /tmp/${EFFECTIVE_MOD_URL##*/}"
log "ERROR: failed to download from $EFFECTIVE_MOD_URL to /tmp/${EFFECTIVE_MOD_URL##*/}"
exit 2
fi
@@ -67,43 +71,87 @@ do
rm -f /tmp/${EFFECTIVE_MOD_URL##*/}
;;
*)
echo "Invalid URL given for modpack: Must be HTTP or HTTPS and a JAR file"
log "Invalid URL given for modpack: Must be HTTP or HTTPS and a JAR file"
;;
esac
done
fi
if [[ "$MANIFEST" ]]; then
EFFECTIVE_MANIFEST_URL=$(curl -Ls -o /dev/null -w %{url_effective} $MANIFEST)
case "X$EFFECTIVE_MANIFEST_URL" in
if [[ -e "$MANIFEST" ]]; then
EFFECTIVE_MANIFEST_FILE=$MANIFEST
elif isURL "$MANIFEST"; then
EFFECTIVE_MANIFEST_FILE=/tmp/manifest.json
EFFECTIVE_MANIFEST_URL=$(curl -Ls -o /dev/null -w %{url_effective} $MANIFEST)
curl -Ls -o $EFFECTIVE_MANIFEST_FILE "$EFFECTIVE_MANIFEST_URL"
else
log "MANIFEST='$MANIFEST' is not a valid manifest url or location"
exit 2
fi
case "X$EFFECTIVE_MANIFEST_FILE" in
X*.json)
if [ -f "${EFFECTIVE_MANIFEST_URL}" ]; then
if [ -f "${EFFECTIVE_MANIFEST_FILE}" ]; then
MOD_DIR=${FTB_BASE_DIR:-/data}/mods
if [ ! -d "$MOD_DIR" ]
then
echo "Creating mods dir $MOD_DIR"
log "Creating mods dir $MOD_DIR"
mkdir -p "$MOD_DIR"
fi
echo "Starting manifest download..."
cat "${EFFECTIVE_MANIFEST_URL}" | jq -r '.files[] | (.projectID|tostring) + " " + (.fileID|tostring)'| while read -r p f
log "Starting manifest download..."
cat "${EFFECTIVE_MANIFEST_FILE}" | jq -r '.files[] | (.projectID|tostring) + " " + (.fileID|tostring)'| while read -r p f
do
if [ ! -f $MOD_DIR/${p}_${f}.jar ]
then
redirect_url="$(curl -Ls -o /dev/null -w %{url_effective} ${CURSE_URL_BASE}/${p})"
url="$redirect_url/download/${f}/file"
echo Downloading curseforge mod $url
log Downloading curseforge mod $url
# Manifest usually doesn't have mod names. Using id should be fine, tho
curl -sSL "${url}" -o $MOD_DIR/${p}_${f}.jar
fi
done
else
echo "Could not find manifest file, unsufficient privs, or malformed path."
log "Could not find manifest file, unsufficient privs, or malformed path."
fi
;;
*)
echo "Invalid manifest file for modpack. Please make sure it is a .json file."
log "Invalid manifest file for modpack. Please make sure it is a .json file."
;;
esac
fi
if [[ "${GENERIC_PACK}" ]]; then
if isURL "${GENERIC_PACK}"; then
generic_pack_url=${GENERIC_PACK}
GENERIC_PACK=/tmp/$(basename ${generic_pack_url})
log "Downloading generic pack from ${generic_pack_url} ..."
curl -fsSL -o ${GENERIC_PACK} ${generic_pack_url}
fi
sum_file=/data/.generic_pack.sum
if ! sha256sum -c ${sum_file} -s 2> /dev/null; then
base_dir=/tmp/generic_pack_base
mkdir -p ${base_dir}
unzip -q -d ${base_dir} ${GENERIC_PACK}
if [ -f /data/manifest.txt ]; then
log "Manifest exists from older generic pack, cleaning up ..."
while read f; do
rm -rf "/data/${f}"
done < /data/manifest.txt
find /data/* -type d -exec rmdir --ignore-fail-on-non-empty {} +
rm -f /data/manifest.txt
fi
log "Writing generic pack manifest ... "
find ${base_dir} -type f -print0 | xargs -0 -I {} echo "{}" | sed "s#${base_dir}/##" > /data/manifest.txt
log "Applying generic pack ..."
IFS='
'
set -f
for d in $(find ${base_dir} -type d); do mkdir -p "$(sed "s#${base_dir}#/data#" <<< $d)"; done
for f in $(find ${base_dir} -type f); do cp -f "$f" "$(sed "s#${base_dir}#/data#" <<< $f)"; done
rm -rf ${base_dir}
sha256sum ${GENERIC_PACK} > ${sum_file}
fi
fi
exec /start-finalSetup03Modconfig $@

View File

@@ -1,11 +1,13 @@
#!/bin/bash
. /start-utils
# If supplied with a URL for a config (simple zip of configurations), download it and unpack
if [[ "$MODCONFIG" ]]; then
case "X$MODCONFIG" in
X[Hh][Tt][Tt][Pp]*[Zz][iI][pP])
echo "Downloading mod/plugin configs via HTTP"
echo " from $MODCONFIG ..."
log "Downloading mod/plugin configs via HTTP"
log " from $MODCONFIG ..."
curl -sSL -o /tmp/modconfig.zip "$MODCONFIG"
if [ "$TYPE" = "SPIGOT" ]; then
mkdir -p /data/plugins
@@ -17,7 +19,7 @@ case "X$MODCONFIG" in
rm -f /tmp/modconfig.zip
;;
*)
echo "Invalid URL given for modconfig: Must be HTTP or HTTPS and a ZIP file"
log "Invalid URL given for modconfig: Must be HTTP or HTTPS and a ZIP file"
;;
esac
fi

View File

@@ -1,5 +1,7 @@
#!/bin/bash
. /start-utils
# FUNCTIONS
function setServerProp {
local prop=$1
@@ -10,16 +12,16 @@ function setServerProp {
TRUE|FALSE)
var=${var,,} ;;
esac
echo "Setting ${prop} to '${var}' in ${SERVER_PROPERTIES}"
log "Setting ${prop} to '${var}' in ${SERVER_PROPERTIES}"
sed -i "/^${prop}\s*=/ c ${prop}=${var}" "$SERVER_PROPERTIES"
else
echo "Skip setting ${prop}"
log "Skip setting ${prop}"
fi
}
function customizeServerProps {
if [ -n "$WHITELIST" ]; then
echo "Creating whitelist"
log "Creating whitelist"
setServerProp "whitelist" "true"
setServerProp "white-list" "true"
fi
@@ -41,6 +43,7 @@ function customizeServerProps {
fi
setServerProp "server-name" "$SERVER_NAME"
setServerProp "server-ip" "$SERVER_IP"
setServerProp "server-port" "$SERVER_PORT"
setServerProp "motd" "$MOTD"
setServerProp "allow-nether" "$ALLOW_NETHER"
@@ -49,6 +52,7 @@ function customizeServerProps {
setServerProp "spawn-animals" "$SPAWN_ANIMALS"
setServerProp "spawn-monsters" "$SPAWN_MONSTERS"
setServerProp "spawn-npcs" "$SPAWN_NPCS"
setServerProp "spawn-protection" "$SPAWN_PROTECTION"
setServerProp "generate-structures" "$GENERATE_STRUCTURES"
setServerProp "view-distance" "$VIEW_DISTANCE"
setServerProp "hardcore" "$HARDCORE"
@@ -70,23 +74,42 @@ function customizeServerProps {
setServerProp "online-mode" "$ONLINE_MODE"
setServerProp "allow-flight" "$ALLOW_FLIGHT"
setServerProp "level-type" "${LEVEL_TYPE^^}"
setServerProp "resource-pack" "$RESOURCE_PACK"
setServerProp "resource-pack-sha1" "$RESOURCE_PACK_SHA1"
setServerProp "player-idle-timeout" "$PLAYER_IDLE_TIMEOUT"
if [ -n "$DIFFICULTY" ]; then
case $DIFFICULTY in
peaceful|0)
DIFFICULTY=0
if versionLessThan 1.13; then
DIFFICULTY=0
else
DIFFICULTY=peaceful
fi
;;
easy|1)
DIFFICULTY=1
if versionLessThan 1.13; then
DIFFICULTY=1
else
DIFFICULTY=easy
fi
;;
normal|2)
DIFFICULTY=2
if versionLessThan 1.13; then
DIFFICULTY=2
else
DIFFICULTY=normal
fi
;;
hard|3)
DIFFICULTY=3
if versionLessThan 1.13; then
DIFFICULTY=3
else
DIFFICULTY=hard
fi
;;
*)
echo "DIFFICULTY must be peaceful, easy, normal, or hard."
log "DIFFICULTY must be peaceful, easy, normal, or hard."
exit 1
;;
esac
@@ -94,25 +117,39 @@ function customizeServerProps {
fi
if [ -n "$MODE" ]; then
echo "Setting mode"
log "Setting mode"
MODE_LC=$( echo $MODE | tr '[:upper:]' '[:lower:]' )
case $MODE_LC in
0|1|2|3)
su*|0)
if versionLessThan 1.13; then
MODE=0
else
MODE=survival
fi
;;
su*)
MODE=0
c*|1)
if versionLessThan 1.13; then
MODE=1
else
MODE=creative
fi
;;
c*)
MODE=1
a*|2)
if versionLessThan 1.13; then
MODE=2
else
MODE=adventure
fi
;;
a*)
MODE=2
;;
sp*)
MODE=3
sp*|3)
if versionLessThan 1.13; then
MODE=3
else
MODE=spectator
fi
;;
*)
echo "ERROR: Invalid game mode: $MODE"
log "ERROR: Invalid game mode: $MODE"
exit 1
;;
esac
@@ -123,11 +160,11 @@ function customizeServerProps {
# Deploy server.properties file
if [[ ${TYPE} == "FEED-THE-BEAST" ]]; then
export SERVER_PROPERTIES=${FTB_DIR}/server.properties
echo "detected FTB, changing properties path to ${SERVER_PROPERTIES}"
log "detected FTB, changing properties path to ${SERVER_PROPERTIES}"
fi
if [ ! -e "$SERVER_PROPERTIES" ]; then
echo "Creating server.properties in ${SERVER_PROPERTIES}"
log "Creating server.properties in ${SERVER_PROPERTIES}"
cp /tmp/server.properties "$SERVER_PROPERTIES"
customizeServerProps
elif [ -n "${OVERRIDE_SERVER_PROPERTIES}" ]; then
@@ -136,11 +173,25 @@ elif [ -n "${OVERRIDE_SERVER_PROPERTIES}" ]; then
customizeServerProps
;;
*)
echo "server.properties already created, skipping"
log "server.properties already created, skipping"
;;
esac
else
echo "server.properties already created, skipping"
log "server.properties already created, skipping"
fi
if isTrue "${ENABLE_AUTOPAUSE}"; then
current_max_tick=$( grep 'max-tick-time' "$SERVER_PROPERTIES" | sed -r 's/( )+//g' | awk -F= '{print $2}' )
if (( $current_max_tick > 0 && $current_max_tick < 86400000 )); then
log "Warning: The server.properties for the server doesn't have the Server Watchdog (effectively) disabled."
log "Warning (cont): Autopause functionality resuming the process might trigger the Watchdog and restart the server completely."
log "Warning (cont): Set the max-tick-time property to a high value (or disable the Watchdog with value -1 for versions 1.8.1+)."
fi
fi
if isDebugging; then
log "DEBUG Dumping server.properties"
cat /data/server.properties
fi
exec /start-finalSetup05EnvVariables $@

View File

@@ -1,15 +1,28 @@
#!/bin/bash
if [ "$REPLACE_ENV_VARIABLES" = "TRUE" ]; then
echo "Replacing env variables in configs that match the prefix $ENV_VARIABLE_PREFIX..."
. /start-utils
if [ "${REPLACE_ENV_VARIABLES^^}" = "TRUE" ]; then
log "Replacing env variables in configs that match the prefix $ENV_VARIABLE_PREFIX..."
while IFS='=' read -r name value ; do
# check if name of env variable matches the prefix
# sanity check environment variables to avoid code injections
if [[ "$name" = $ENV_VARIABLE_PREFIX* ]] && [[ $value =~ ^[0-9a-zA-Z_:/=?.+\-]*$ ]] && [[ $name =~ ^[0-9a-zA-Z_\-]*$ ]]; then
echo "Replacing $name with $value ..."
find /data/ -type f \( -name "*.yml" -or -name "*.yaml" -or -name "*.txt" -or -name "*.cfg" -or -name "*.properties" \) -exec sed -i 's#${'"$name"'}#'"$value"'#g' {} \;
if [[ "$name" = $ENV_VARIABLE_PREFIX* ]] \
&& [[ $value =~ ^[0-9a-zA-Z_:/=?.+\-]*$ ]] \
&& [[ $name =~ ^[0-9a-zA-Z_\-]*$ ]]; then
# Read content from file environment
if [[ $name = *"_FILE" ]] && [[ -f $value ]]; then
name="${name/_FILE/}"
value=$(<$value)
fi
log "Replacing $name with $value ..."
find /data/ -type f \
\( -name "*.yml" -or -name "*.yaml" -or -name "*.txt" -or -name "*.cfg" \
-or -name "*.conf" -or -name "*.properties" \) \
-exec sed -i 's#${'"$name"'}#'"$value"'#g' {} \;
fi
done < <(env)
fi
exec /start-minecraftFinalSetup $@
exec /start-minecraftFinalSetup $@

18
start-magma Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
. /start-utils
export SERVER="/data/magma-server-${VANILLA_VERSION}.jar"
# Always download since new updates of each base version are published frequently
if ! curl -o /data/magma-server-${VANILLA_VERSION}.jar -fsSL \
https://api.magmafoundation.org/api/resources/Magma/${VANILLA_VERSION}/stable/latest/download; then
log "ERROR unable to download version ${VANILLA_VERSION} of Magma"
log " Check https://magmafoundation.org/ for available versions"
exit 1
fi
export SKIP_LOG4J_CONFIG=true
# Continue to Final Setup
exec /start-finalSetup01World $@

View File

@@ -2,44 +2,58 @@
. /start-utils
if [ -n "$OPS" -a ! -e ops.txt.converted ]; then
echo "Setting ops"
echo $OPS | awk -v RS=, '{print}' >> ops.txt
if [ -n "$OPS" ]; then
log "Setting/adding ops"
rm -rf /data/ops.txt.converted
echo $OPS | awk -v RS=, '{print}' > /data/ops.txt
fi
if [ -n "$WHITELIST" -a ! -e white-list.txt.converted ]; then
echo "Setting whitelist"
echo $WHITELIST | awk -v RS=, '{print}' >> white-list.txt
if [ -n "$WHITELIST" ]; then
log "Setting whitelist"
rm -rf /data/white-list.txt.converted
echo $WHITELIST | awk -v RS=, '{print}' > /data/white-list.txt
fi
if [ -n "$ICON" -a ! -e server-icon.png ]; then
echo "Using server icon from $ICON..."
log "Using server icon from $ICON..."
# Not sure what it is yet...call it "img"
curl -sSL -o /tmp/icon.img $ICON
specs=$(identify /tmp/icon.img | awk '{print $2,$3}')
if [ "$specs" = "PNG 64x64" ]; then
mv /tmp/icon.img /data/server-icon.png
else
echo "Converting image to 64x64 PNG..."
log "Converting image to 64x64 PNG..."
convert /tmp/icon.img -resize 64x64! /data/server-icon.png
fi
fi
if ! isTrue ${SKIP_LOG4J_CONFIG}; then
# Set up log configuration
LOGFILE="/data/log4j2.xml"
if [ ! -e "$LOGFILE" ]; then
log "Creating log4j2.xml in ${LOGFILE}"
cp /tmp/log4j2.xml "$LOGFILE"
else
log "log4j2.xml already created, skipping"
fi
JVM_OPTS="-Dlog4j.configurationFile=/data/log4j2.xml ${JVM_OPTS}"
fi
# Make sure files exist and are valid JSON (for pre-1.12 to 1.12 upgrades)
echo "Checking for JSON files."
JSON_FILES=$(find . -maxdepth 1 -name '*.json')
log "Checking for JSON files."
JSON_FILES=$(find /data -maxdepth 1 -name '*.json')
for j in $JSON_FILES; do
if [[ $(python -c "print open('$j').read().strip()==''") = True ]]; then
echo "Fixing JSON $j"
if [[ $(cat "$j" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') == "" ]]; then
log "Fixing JSON $j"
echo '[]' > $j
fi
done
# If any modules have been provided, copy them over
mkdir -p /data/mods
if [ -d /mods ]; then
echo "Copying any mods over..."
log "Copying any mods over..."
mkdir -p /data/mods
rsync -a --out-format="update:%f:Last Modified %M" --prune-empty-dirs --update /mods /data
fi
@@ -47,24 +61,26 @@ fi
for c in /config/*
do
if [ -f "$c" ]; then
echo Copying configuration `basename "$c"`
log Copying configuration $(basename "$c")
cp -rf "$c" /data/config
fi
done
mkdir -p /data/plugins
if [ "$TYPE" = "SPIGOT" ]; then
if [ -d /plugins ]; then
echo "Copying any Bukkit plugins over..."
# Copy plugins over using rsync to allow deeply nested updates of plugins
# only updates files if the source file is newer and print updated files
rsync -a --out-format="update:%f:Last Modified %M" --prune-empty-dirs --update /plugins /data
fi
fi
case ${TYPE} in
SPIGOT|BUKKIT|PAPER)
mkdir -p /data/plugins
if [ -d /plugins ]; then
log "Copying plugins over..."
# Copy plugins over using rsync to allow deeply nested updates of plugins
# only updates files if the source file is newer and print updated files
rsync -a --out-format="update:%f:Last Modified %M" --prune-empty-dirs --update /plugins /data
fi
;;
esac
EXTRA_ARGS=""
# Optional disable console
if [[ ${CONSOLE} = false || ${CONSOLE} = FALSE ]]; then
if versionLessThan 1.14 && [[ ${CONSOLE,,} = false ]]; then
EXTRA_ARGS+="--noconsole"
fi
@@ -74,7 +90,7 @@ if [[ ${GUI} = false || ${GUI} = FALSE ]]; then
fi
# put these prior JVM_OPTS at the end to give any memory settings there higher precedence
echo "Setting initial memory to ${INIT_MEMORY:=${MEMORY}} and max to ${MAX_MEMORY:=${MEMORY}}"
log "Setting initial memory to ${INIT_MEMORY:=${MEMORY}} and max to ${MAX_MEMORY:=${MEMORY}}"
expandedDOpts=
if [ -n "$JVM_DD_OPTS" ]; then
@@ -84,9 +100,88 @@ if [ -n "$JVM_DD_OPTS" ]; then
done
fi
mcServerRunnerArgs="--stop-duration 60s"
if isTrue ${ENABLE_JMX}; then
: ${JMX_HOST:=0.0.0.0}
: ${JMX_PORT:=7091}
JVM_OPTS="${JVM_OPTS}
-Dcom.sun.management.jmxremote.local.only=false
-Dcom.sun.management.jmxremote.port=${JMX_PORT}
-Dcom.sun.management.jmxremote.rmi.port=${JMX_PORT}
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.host=${JMX_HOST}
-Djava.rmi.server.hostname=${JMX_HOST}"
log "JMX is enabled. Make sure you have port forwarding for ${JMX_PORT}"
fi
if isTrue "${USE_AIKAR_FLAGS}"; then
# From https://mcflags.emc.gs/
if (( $(normalizeMemSize "${MAX_MEMORY}") >= $(normalizeMemSize 12g) )); then
log "Using Aikar's >12GB flags"
G1NewSizePercent=40
G1MaxNewSizePercent=50
G1HeapRegionSize=16M
G1ReservePercent=15
InitiatingHeapOccupancyPercent=20
else
log "Using Aikar's flags"
G1NewSizePercent=30
G1MaxNewSizePercent=40
G1HeapRegionSize=8M
G1ReservePercent=20
InitiatingHeapOccupancyPercent=15
fi
JVM_XX_OPTS="${JVM_XX_OPTS}
-XX:+UseG1GC
-XX:+ParallelRefProcEnabled
-XX:MaxGCPauseMillis=200
-XX:+UnlockExperimentalVMOptions
-XX:+DisableExplicitGC
-XX:+AlwaysPreTouch
-XX:G1NewSizePercent=${G1NewSizePercent}
-XX:G1MaxNewSizePercent=${G1MaxNewSizePercent}
-XX:G1HeapRegionSize=${G1HeapRegionSize}
-XX:G1ReservePercent=${G1ReservePercent}
-XX:G1HeapWastePercent=5
-XX:G1MixedGCCountTarget=4
-XX:InitiatingHeapOccupancyPercent=${InitiatingHeapOccupancyPercent}
-XX:G1MixedGCLiveThresholdPercent=90
-XX:G1RSetUpdatingPauseTimePercent=5
-XX:SurvivorRatio=32
-XX:+PerfDisableSharedMem
-XX:MaxTenuringThreshold=1
-Dusing.aikars.flags=https://mcflags.emc.gs
-Daikars.new.flags=true
"
fi
if isTrue "${USE_LARGE_PAGES}"; then
JVM_XX_OPTS="${JVM_XX_OPTS}
-XX:+UseLargePagesInMetaspace
"
fi
if isTrue "${DEBUG_MEMORY}"; then
log "Memory usage and availability (in MB)"
uname -a
free -m
fi
mcServerRunnerArgs="--stop-duration 60s"
if [[ ${TYPE} == "CURSE_INSTANCE" ]]; then
JVM_OPTS="-Xms${INIT_MEMORY} -Xmx${MAX_MEMORY} ${JVM_OPTS}"
if isTrue ${DEBUG_EXEC}; then
set -x
fi
exec mc-server-runner ${mcServerRunnerArgs} \
--cf-instance-file "${CURSE_INSTANCE_JSON}" \
java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar _SERVERJAR_ "$@" $EXTRA_ARGS
elif [[ ${TYPE} == "FEED-THE-BEAST" ]]; then
mcServerRunnerArgs="${mcServerRunnerArgs} --shell bash"
if [[ ${TYPE} == "FEED-THE-BEAST" ]]; then
if [ ! -e "${FTB_DIR}/ops.json" -a -e /data/ops.txt ]; then
cp -f /data/ops.txt ${FTB_DIR}/
fi
@@ -100,7 +195,7 @@ if [[ ${TYPE} == "FEED-THE-BEAST" ]]; then
cat > "${FTB_DIR}/settings-local.sh" <<EOF
export MIN_RAM="${INIT_MEMORY}"
export MAX_RAM="${MAX_MEMORY}"
export JAVA_PARAMETERS="-Xms${INIT_MEMORY} $expandedDOpts"
export JAVA_PARAMETERS="${JVM_XX_OPTS} -Xms${INIT_MEMORY} ${JVM_OPTS} $expandedDOpts"
EOF
# patch CurseForge cfg file, if present
@@ -109,7 +204,7 @@ EOF
fi
cd "${FTB_DIR}"
echo "Running FTB ${FTB_SERVER_START} in ${FTB_DIR} ..."
log "Running FTB ${FTB_SERVER_START} in ${FTB_DIR} ..."
if isTrue ${DEBUG_EXEC}; then
set -x
fi
@@ -120,7 +215,7 @@ else
bootstrapArgs="--bootstrap /data/bootstrap.txt"
fi
echo "Starting the Minecraft server..."
log "Starting the Minecraft server..."
JVM_OPTS="-Xms${INIT_MEMORY} -Xmx${MAX_MEMORY} ${JVM_OPTS}"
if isTrue ${DEBUG_EXEC}; then
set -x

View File

@@ -3,7 +3,7 @@
function isURL {
local value=$1
if [[ ${value:0:8} == "https://" || ${value:0:7} = "http://" ]]; then
if [[ ${value:0:8} == "https://" || ${value:0:7} == "http://" ]]; then
return 0
else
return 1
@@ -28,7 +28,7 @@ function isTrue {
}
function isDebugging {
if [[ ${DEBUG^^} = TRUE ]]; then
if [[ -v DEBUG ]] && [[ ${DEBUG^^} = TRUE ]]; then
return 0
else
return 1
@@ -37,6 +37,66 @@ function isDebugging {
function debug {
if isDebugging; then
echo "DEBUG: $*"
log "DEBUG: $*"
fi
}
function logn {
echo -n "[init] $*"
}
function log {
echo "[init] $*"
}
function logAutopause {
echo "[Autopause loop] $*"
}
function logAutopauseAction {
echo "[$(date -Iseconds)] [Autopause] $*"
}
function normalizeMemSize {
local scale=1
case ${1,,} in
*k)
scale=1024;;
*m)
scale=1048576;;
*g)
scale=1073741824;;
esac
val=${1:0: -1}
echo $(( val * scale ))
}
function versionLessThan {
local activeParts
IFS=. read -ra activeParts <<< "${VANILLA_VERSION}"
local givenParts
IFS=. read -ra givenParts <<< "$1"
if (( ${#activeParts[@]} < 2 )); then
return 1
fi
if (( ${#activeParts[@]} == 2 )); then
if (( activeParts[0] < givenParts[0] )) || \
(( activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1] )); then
return 0
else
return 1
fi
else
if (( activeParts[0] < givenParts[0] )) || \
(( activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1] )) || \
(( activeParts[0] == givenParts[0] && activeParts[1] == givenParts[1] && activeParts[2] < givenParts[2] )); then
return 0
else
return 1
fi
fi
}

18
start-validateCurseInstance Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
. /start-utils
if ! [[ -v CURSE_INSTANCE_JSON ]]; then
log "ERROR: CURSE_INSTANCE_JSON needs to be set"
exit 2
elif ! [ -f "${CURSE_INSTANCE_JSON}" ] && [ -f "${CURSE_INSTANCE_JSON}/minecraftinstance.json" ]; then
CURSE_INSTANCE_JSON="${CURSE_INSTANCE_JSON}/minecraftinstance.json"
elif ! [ -f "${CURSE_INSTANCE_JSON}" ]; then
log "ERROR: CURSE_INSTANCE_JSON file does not exist: ${CURSE_INSTANCE_JSON}"
exit 2
fi
log "Resolved CURSE_INSTANCE_JSON as ${CURSE_INSTANCE_JSON}"
# Continue to Final Setup
exec /start-finalSetup01World "$@"