Compare commits

...

156 Commits

Author SHA1 Message Date
Geoff Bourne
ceee9eddc9 ci: restored base image to ubuntu and install openjdk-8 2021-02-06 15:53:59 -06:00
Geoff Bourne
60ba668743 Merge branch 'master' into java8-multiarch
# Conflicts:
#	Dockerfile
2021-02-06 15:49:16 -06:00
Geoff Bourne
beeaf1a996 ci: Added java8-multiarch to build and docs 2021-02-06 15:48:27 -06:00
Geoff Bourne
fd1b15e01f ci: Added java8 variant of multiarch 2021-02-06 15:44:02 -06:00
Geoff Bourne
f856276d71 Upgraded multiarch to Java 11 2021-02-06 15:22:15 -06:00
Geoff Bourne
0300854c46 Merge branch 'master' into multiarch 2021-02-06 15:21:53 -06:00
Geoff Bourne
96aa1054dc Upgraded mainline/latest to Java 11 2021-02-06 15:21:20 -06:00
Geoff Bourne
e7937206af ci: Added java15 to multiarch build 2021-02-06 15:12:34 -06:00
Geoff Bourne
081b2c11e4 ci: Introduced java15 branch
ci: Deprecated adopt13, adopt14, openj9-nightly
2021-02-06 15:11:03 -06:00
Geoff Bourne
f342f4aa98 ci: Introduced java15 branch
ci: Deprecated adopt13, adopt14, openj9-nightly
2021-02-06 15:07:42 -06:00
Geoff Bourne
f06e9f5ede Merge branch 'master' into multiarch 2021-02-06 14:52:35 -06:00
Geoff Bourne
4e73e69342 ci: Added build-multiarch.yml to align merges 2021-02-06 14:52:20 -06:00
Geoff Bourne
c6ff80b71c docs: Clarify MEMORY limits vs overall container memory
Related to #691
2021-02-01 21:15:33 -06:00
M*C*O
37cad3f255 docs: Document LEVEL_TYPE: BIOMESOP (#741) 2021-02-01 12:39:55 -06:00
Geoff Bourne
5700f36a6f Renamed forge branch to java8 2021-01-30 18:49:46 -06:00
Geoff Bourne
34f800d815 ci: Added forge branch to builds 2021-01-30 16:02:15 -06:00
Geoff Bourne
8d3ca813ed Auto-merging via docker-versions-create 2021-01-29 21:07:00 -06:00
Geoff Bourne
ffec50141a Fixed MODS provides from github release URLs
For #731
2021-01-28 20:55:08 -06:00
Geoff Bourne
54027049d3 docs: Added compose example to data attaching section 2021-01-24 12:31:56 -06:00
Geoff Bourne
4c2829e3d2 docs: Added a simple docker compose example 2021-01-21 13:36:41 -06:00
Geoff Bourne
69e308d420 Split eula header into two lines of comments
#728
- Found that https://github.com/Yoosk/ServerStarter hard coded expectation that eula property was on third line
2021-01-19 21:36:21 -06:00
Geoff Bourne
ad46f10b55 Added option to override whitelist and ops files
#726
2021-01-17 10:09:41 -06:00
Eugene
cd0fdfc95b Add an option to override the icon which already has been set. (#723) 2021-01-13 16:47:15 -06:00
Geoff Bourne
d95abfce82 ci: Added openj9-11 tags pattern 2021-01-12 17:33:03 -06:00
Geoff Bourne
942a125e04 ci: Added non-versioned cache as restore-key fallback 2021-01-12 17:30:58 -06:00
Geoff Bourne
e97a00e61d Auto-merging via docker-versions-create 2021-01-12 17:28:11 -06:00
Geoff Bourne
a3677d5aa8 ci: Enabled pull in build step 2021-01-12 17:20:57 -06:00
Geoff Bourne
f927933c46 Added openj9 JDK11 variant
For #721
2021-01-12 17:18:08 -06:00
Michael Kirsch
b519c43e16 fix multiarch autopause daemon (#722) 2021-01-12 16:05:12 -06:00
Geoff Bourne
5ab83bcb21 ci: Switched build to docker/build-push-action@v2 2021-01-09 14:13:18 -06:00
Geoff Bourne
02c8393bc6 ci: Added opencontainers labels 2021-01-09 14:07:05 -06:00
Geoff Bourne
9469291731 ci: Switched multiarch build caching to github actions 2021-01-09 12:28:27 -06:00
Geoff Bourne
c29baf446d Auto-merging via docker-versions-create 2021-01-09 11:24:53 -06:00
Dubhar
fdf5fb46bc fix/681 (#719)
* [shellcheck] prevent globbing

* fix/681 remove old PaperMC before downloading new

Fixes #681 

Co-authored-by: Dubhar <thorsten.jerosch@gmail.com>
2021-01-09 11:03:21 -06:00
Geoff Bourne
8c6ca5e999 Restored the ability for PAPERBUILD to be used with TYPE=PAPER
For #715
2021-01-07 20:03:42 -06:00
Geoff Bourne
bb2b9eeea9 docs: Changed FORGEVERSION example to use a valid combination
For #716
2021-01-07 11:02:19 -06:00
Geoff Bourne
d1cbce3f89 docs: Clarified usage of VERSION with FORGE type
For #716
2021-01-06 22:49:22 -06:00
Geoff Bourne
55b5f6821f Fixed ops and white-list setup for CurseForge modpacks named with spaces
For #717
2021-01-06 22:38:18 -06:00
Geoff Bourne
f9b8db0715 Merged master 2021-01-06 22:14:46 -06:00
Michael Kirsch
2fb01b4adf Autopause update: allow network interface selection (#711)
* Cherry-pick: Fixing AUTOPAUSE on Raspberry Pi 4s (#708)

* implement autopause interface selection

* concentrate ps calls in function file

* wording and add note about PAPER's etc watchdogs
2021-01-02 11:27:03 -06:00
Geoff Bourne
02bce8c3a8 docs: Documented adopt15 and multiarch-latest tags 2021-01-02 11:12:07 -06:00
Nathanial L. McConnell
468671a3fa Update README.md (#712)
Change "Please" to "Place"
2021-01-01 15:23:04 -06:00
ErstBlack
ffb50cfe28 Fixing AUTOPAUSE on Raspberry Pi 4s (#708)
* Replacing killall with pkill and ps -a to ps -ax

* Adding net-tools and removing -q from pkill

* Missed the resume.sh

* Christ there's a lot of ps calls

* Adding -x to health.sh, replacing killall with pkill in sudoers-mv, and replacing su-exec with gosu in knockd-config.cfg

Co-authored-by: sean.sullivan.ctr@progeny.net <sean.sullivan.ctr@progeny.net>
2020-12-31 13:15:44 -06:00
Geoff Bourne
8ee650f38d Allowed CF_BASE_DIR/FTB_BASE_DIR to be configured
For #518
2020-12-31 13:11:37 -06:00
Geoff Bourne
3de2bf88df Escaped backslashes when setting server property value (#706)
* Escaped backslashes when setting server property value
For #446

* Fixed pattern substitution to "replace all"
2020-12-30 09:42:29 -06:00
Geoff Bourne
1fcbd8410f Allow CUSTOM_SERVER to reference not-yet-existing file from GENERIC_PACK
For #703
2020-12-29 10:56:05 -06:00
Geoff Bourne
51e6d5dfbd Added install of sudo
For #699
2020-12-28 11:42:54 -06:00
Geoff Bourne
842c69fd80 Auto-merging via docker-versions-create 2020-12-27 22:08:02 -06:00
Gabriel Fontes
d40bbdc3a5 Envvars in files from /config and /mods now replaced as expected (#701)
Envvars in files from `/config` and `/mods` now replaced as expected (#701)
2020-12-27 22:01:03 -06:00
Andrew Lambeth
c458823014 ignore duplicate entries in the targets array of version.json (#698) 2020-12-26 14:44:37 -06:00
aspro-at
61c291ae4e Fixed REMOVE_OLD_MODS with missing /data/mods or /data/plugins #667 (#697) 2020-12-23 13:25:14 -06:00
Geoff Bourne
32abf1614f Auto-merging via docker-versions-create 2020-12-19 08:26:24 -06:00
Geoff Bourne
f613228619 Restored support for PAPER_DOWNLOAD_URL
Fixes #687
2020-12-15 20:40:00 -06:00
Geoff Bourne
a916cc8320 Auto-merging via docker-versions-create 2020-12-15 14:00:27 -06:00
Silthus
ca9f883352 feat: add COPY_CONFIG_DEST option (#689) 2020-12-15 13:31:51 -06:00
Silthus
9d68fa3b88 feat: improvde REMOVE_OLD_MODS option (#688) 2020-12-13 20:00:06 -06:00
Geoff Bourne
d3a5885d95 Fixed handling of query parameters in MODS url
For #684
2020-12-12 15:22:07 -06:00
Geoff Bourne
c1db13c1f6 Fixed dirname handling in find for SPIGOT WORLD handling
For #685
2020-12-12 11:10:13 -06:00
Mike Wilson
31b0f711b8 Fixing some spigot world import issues (#683)
* Fixing adding an existing spigot world and removing incorrectly identifying spigot worlds as multiple worlds

* Update start-finalSetupWorld

Co-authored-by: Geoff Bourne <itzgeoff@gmail.com>

Co-authored-by: Geoff Bourne <itzgeoff@gmail.com>
2020-12-12 08:26:32 -06:00
Geoff Bourne
59ca1ce3a6 Improved URL handling for GENERIC_PACK
For #684
2020-12-11 21:12:44 -06:00
Geoff Bourne
0f7bd5f4fd ci: Added adopt15 branch releases 2020-12-07 10:54:36 -06:00
Geoff Bourne
01130757d6 Reverting FTBA debug change 2020-11-26 08:45:51 -06:00
Geoff Bourne
f97b3bf82e Added error handling of FTB installer download
For #645
2020-11-25 21:36:22 -06:00
Geoff Bourne
b7bcd252d3 ci: Fixed tag extraction 2020-11-25 16:06:01 -06:00
Geoff Bourne
aa43926da2 Merged from master 2020-11-25 15:59:43 -06:00
Geoff Bourne
a368f4cf57 misc: Added multiarch-latest to versions to release 2020-11-25 15:52:07 -06:00
Geoff Bourne
08a4bde6c1 Switched to PaperMC v2 API
Fixes #670
2020-11-25 15:42:27 -06:00
Geoff Bourne
f68e979229 docs: Improved appearance of Discord badge
For #481
2020-11-06 14:47:04 -06:00
Geoff Bourne
544b1f243d Removed invalid spigot/bukkit download along with debug of content
For #655
2020-11-04 17:04:57 -06:00
Geoff Bourne
391e807c78 Added debug logging of bukkit/spigot curl download
For #655
2020-11-03 16:49:38 -06:00
Geoff Bourne
4099cde737 Revert "Improved handling of bad spigot/bukkit downloads via temp file For #655"
This reverts commit e56a74dc
2020-11-03 16:47:46 -06:00
Geoff Bourne
e56a74dc81 Improved handling of bad spigot/bukkit downloads via temp file
For #655
2020-11-02 20:31:01 -06:00
Geoff Bourne
34c45ec883 Switched to latest Docker buildx github action 2020-10-31 14:59:28 -05:00
Geoff Bourne
31b8535854 Added debug output for bukkit/sigot type
For #655
2020-10-30 17:03:13 -05:00
stevoh6
ed1bb73c22 Update deprecated LegacyJavaFixer path. (#648) 2020-10-14 21:21:40 -05:00
Paul1365972
b7ac28e902 IPv6 support for autopause (#646) 2020-10-11 13:27:59 -05:00
vatertime
3cb72797b6 Added AWS blurb to readme (#644)
* Added AWS blurb to readme

* moved section in readme

Co-authored-by: Chris Vater <chris.vater@johnsonfit.com>
2020-10-07 13:35:07 -05:00
Geoff Bourne
6f1f8d7806 Added use of REMOVE_OLD_MODS to /mods processing 2020-10-03 14:34:02 -05:00
Geoff Bourne
b06f1115d4 Added pruning of 'config' to CF modpack upgrade
Fixes #626
2020-09-27 10:27:46 -05:00
Geoff Bourne
777ad31de0 Resolve latest bukkit/spigot directly from getbukkit
Fixes #629 #631
2020-09-27 10:21:49 -05:00
Geoff Bourne
8b977f8786 Added adopt14 variant 2020-09-27 10:21:49 -05:00
Geoff Bourne
7c3139226c Changed Paper update process to check FORCE_REDOWNLOAD first
For #634
2020-09-16 17:09:16 -05:00
Geoff Bourne
0ddabf3089 Corrected Fabric installer variables in README 2020-09-10 16:25:29 -05:00
Geoff Bourne
6cfc7e45ef ci: prepared for adopt14 variant 2020-08-27 18:49:24 -05:00
Geoff Bourne
9ea675bc89 Improved handling of latest PaperMC version
Fixes #563
2020-08-25 21:44:36 -05:00
Geoff Bourne
42f90c8806 Added variable to configure stop duration
Fixes #617
2020-08-25 19:10:55 -05:00
Geoff Bourne
c8b6eac8fe Updated FTBA modpack ID instructions
Fixes #612
2020-08-23 20:40:47 -05:00
Bartosz Stefańczyk
d78272c1fa PaperSpigot is now known as Paper (#614) 2020-08-23 09:16:04 -05:00
Geoff Bourne
48ccdf128f Fixed CF_SERVER_MOD to handle spaces in the given filename
Updated USE_MODPACK_START_SCRIPT=false to support forge provided by pack
For #608
2020-08-18 20:44:11 -05:00
Geoff Bourne
2322dffd49 misc: Improved error log for missing Paper versions 2020-08-15 10:06:49 -05:00
Geoff Bourne
8a5e5bf01e Improved handling of missing Paper server version downloads
Fixes #607
2020-08-15 10:02:45 -05:00
Geoff Bourne
99ed83022e misc: added EOL config to .editorconfig 2020-08-12 20:47:52 -05:00
Geoff Bourne
07185534fb Upgraded to mc-server-runner 1.5.0 2020-08-09 13:28:36 -05:00
Geoff Bourne
9bacaa11d8 Auto-merging via docker-versions-create 2020-08-09 13:07:53 -05:00
Stephen Owen
4fe55b5a28 Added note on tweaking settings and using own map (#602) 2020-08-07 17:15:13 -05:00
Stephen Owen
bd503f224d Adds EULA to the 'quickstart' command in readme (#600)
* Adds EULA to the 'quickstart' command in readme

most people will start with the quickstart command, which won't work anymore now that EULA is required.  Modified the sample quickstart to include the new minimum params.

* Update README.md

Co-authored-by: Geoff Bourne <itzgeoff@gmail.com>

* Update README.md

Co-authored-by: Geoff Bourne <itzgeoff@gmail.com>

Co-authored-by: Geoff Bourne <itzgeoff@gmail.com>
2020-08-04 20:06:00 -05:00
Geoff Bourne
b5c91647ca Added testdata to dockerignore 2020-08-02 19:57:47 -05:00
Geoff Bourne
c359a0f2ac Changed MODPACK and MODS to only resolve effective URL when needed
For #592
2020-08-02 19:57:12 -05:00
Geoff Bourne
c7c4c7497a docs: Added test multiarch build instruction 2020-07-26 13:51:16 -05:00
Geoff Bourne
e442baab31 Added writing of eula file after FTBA modpack is installed (#550) 2020-07-26 13:50:57 -05:00
Geoff Bourne
8101c8b51c Merge branch 'master' into multiarch
Renamed to start-deployFTBA

# Conflicts:
#	start-configuration
#	start-deployCF
2020-07-26 13:47:17 -05:00
Geoff Bourne
49d9f4a89d Separated autopause config file location to keep scripts read-only 2020-07-26 13:22:07 -05:00
Geoff Bourne
aebe35c9d4 misc: Refactor writeEula 2020-07-26 13:19:45 -05:00
Geoff Bourne
a26361c79f misc: Renamed start-deployCF to align with multiarch branch 2020-07-26 13:07:30 -05:00
Geoff Bourne
eba1ef6ab9 Auto-merging via docker-versions-create
# Conflicts:
#	start-deployFTB
#	start-minecraftFinalSetup
2020-07-26 08:35:13 -05:00
Paul Zühlcke
a486458a08 Fixed "REPLACE_ENV_VARIABLES_EXCLUDE_PATHS" breaking cfg replacer when set. (#598) 2020-07-26 08:20:11 -05:00
nrgbistro
82b8401414 More filenames for modpack start scripts (#596) 2020-07-23 14:29:39 -05:00
Geoff Bourne
8b6ee91ec1 Added support for upgrading with USE_MODPACK_START_SCRIPT=false 2020-07-19 18:10:16 -05:00
Geoff Bourne
06cffd9e15 Ensured eula and other files brought over when not using CF start script (#591) 2020-07-19 16:29:41 -05:00
Geoff Bourne
beaccbcf3b Added option to set USE_MODPACK_START_SCRIPT=false for CF modpacks (#591) 2020-07-19 15:01:19 -05:00
Geoff Bourne
21ee5e2401 Changed handling of unrecognized VERSION and detect absent server in meta json
For #590
2020-07-19 12:22:15 -05:00
Geoff Bourne
6462e1580c Removed improperly merged apk call 2020-07-18 19:29:49 -05:00
Geoff Bourne
8b5552bb62 Auto-merging via docker-versions-create 2020-07-18 18:41:10 -05:00
Paul Zühlcke
747c188824 Use -prune for "REPLACE_ENV_VARIABLES_EXCLUDE_PATHS" feature. (#588) 2020-07-18 18:31:29 -05:00
Geoff Bourne
692087dd25 Ensured ops.txt and white-list.txt are always provided for CURSEFORGE/FTB type (#584) 2020-07-18 13:49:40 -05:00
Geoff Bourne
6fe13e8654 Clarified "invalid type" message for FTBA on multiarch 2020-07-18 13:09:58 -05:00
Geoff Bourne
3b2b98b9fe Upgrade base image packages
For #586
2020-07-14 21:07:57 -05:00
Code Monad
796f2fe14a Add support for rcon password from file (#585) 2020-07-13 21:00:46 -05:00
Geoff Bourne
4fef391b64 misc: Switched maintainer label to opencontainers schema 2020-07-12 11:36:31 -05:00
Geoff Bourne
83f6cebd0b Merge pull request #581 from itzg/dev/add-ci-tests
Added CI tests
2020-07-11 14:29:59 -05:00
Geoff Bourne
90183ae823 ci: Don't restart failed container during test 2020-07-11 14:26:47 -05:00
Geoff Bourne
3c9df03584 ci: Only output server logs when failed 2020-07-11 14:13:51 -05:00
Geoff Bourne
367c6cfd92 ci: Added testing step to github actions 2020-07-11 14:09:08 -05:00
Geoff Bourne
5e75410e7c Confirm latest Paper jar is always downloaded 2020-07-11 13:30:39 -05:00
Geoff Bourne
38028f7d0c Confirm latest Spigot jar is always downloaded 2020-07-11 13:17:28 -05:00
Geoff Bourne
3ca514f2b2 Auto-merging via docker-versions-create 2020-07-11 13:14:10 -05:00
Geoff Bourne
a07ae685e2 Fixed attempted rsync when WORLD not set 2020-07-11 13:09:48 -05:00
Geoff Bourne
c07f899870 Auto-merging via docker-versions-create
# Conflicts:
#	start-deployFTB
2020-07-10 17:13:05 -05:00
Geoff Bourne
e527fd9551 Auto-merging via docker-versions-create 2020-07-04 14:58:40 -05:00
Geoff Bourne
047a477f7b Auto-merging via docker-versions-create 2020-06-20 15:45:29 -05:00
Geoff Bourne
78cb05adda ci: added multiarch tags to triggers 2020-06-19 15:03:29 -05:00
Geoff Bourne
8493252645 Auto-merging via docker-versions-create
# Conflicts:
#	Dockerfile
#	README.md
#	start
#	start-configuration
#	start-deployFTB
2020-06-19 15:01:28 -05:00
Geoff Bourne
aa42633ab2 Added support for FTB application modpacks via modpacks.ch
For #524
2020-05-31 18:18:54 -05:00
Geoff Bourne
9ec336283f Updated to support multiarch/BuiltKit builds 2020-05-21 20:48:54 -05:00
Geoff Bourne
bbdb2c9b36 Auto-merging via docker-versions-create 2020-05-20 08:15:50 -05:00
Geoff Bourne
48e09f42fc Changed base ubuntu to 18.04 2020-05-14 20:09:12 -05:00
Geoff Bourne
ec7d182d38 Avoid touch since rpi mounts default to noatime 2020-05-14 15:21:51 -05:00
Geoff Bourne
9c7c95cf4f Pinned Java version at 11 2020-05-03 11:51:56 -05:00
Geoff Bourne
e32ffd1819 Auto-merging via docker-versions-create 2020-05-02 09:34:58 -05:00
Geoff Bourne
095c6ad099 Auto-merging via docker-versions-create 2020-04-25 12:11:39 -05:00
Geoff Bourne
14342c9632 Auto-merging via docker-versions-create
# Conflicts:
#	Dockerfile
2020-04-17 21:32:03 -05:00
Geoff Bourne
f6df4d6694 Auto-merging via docker-versions-create
# Conflicts:
#	.circleci/config.yml
2020-04-11 08:56:29 -05:00
Geoff Bourne
0406e89c2a Auto-merging via docker-versions-create 2020-04-10 11:09:12 -05:00
Geoff Bourne
5ef21e1ddf Auto-merging via docker-versions-create 2020-04-03 13:31:53 -05:00
Geoff Bourne
414d5bd8ac Auto-merging via docker-versions-create 2020-04-03 13:29:03 -05:00
Geoff Bourne
15ccf03b28 Auto-merging via docker-versions-create 2020-04-02 17:47:52 -05:00
Geoff Bourne
828a48998f Auto-merging via docker-versions-create 2020-03-30 08:32:11 -05:00
Geoff Bourne
4b590e03ff Auto-merging via docker-versions-create 2020-03-26 20:54:25 -05:00
Geoff Bourne
0db8780ad9 Changed base image to arm32v7/adoptopenjdk 2020-03-25 21:05:16 -05:00
Geoff Bourne
5b744176df Merge remote-tracking branch 'origin/master' into multiarch 2020-03-25 20:08:47 -05:00
Geoff Bourne
20b15e0330 Merge remote-tracking branch 'origin/master' into multiarch
# Conflicts:
#	Dockerfile
2020-02-06 16:59:59 -06:00
Geoff Bourne
818539e3de Switched base image to adoptopenjdk (debian) 2020-02-05 21:33:08 -06:00
Geoff Bourne
f48741f65c Try BuildKit via regular setup_remote_docker 2020-02-05 08:21:52 -06:00
Geoff Bourne
e9e5af849f Use docker executor 2020-02-04 20:14:32 -06:00
Geoff Bourne
22d68f5c7c Enable use-remote-docker 2020-02-04 20:13:02 -06:00
Geoff Bourne
690598da60 Try BuildKit/multiarch support on CircleCI 2020-02-04 20:10:45 -06:00
41 changed files with 1056 additions and 408 deletions

View File

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

View File

@@ -1,2 +1,4 @@
[start-*]
indent_size = 2
indent_size = 2
indent_style = space
end_of_line = lf

80
.github/workflows/build-multiarch.yml vendored Normal file
View File

@@ -0,0 +1,80 @@
name: Build and publish multiarch
on:
push:
branches:
- multiarch
- java8-multiarch
- multiarch-latest
- java15
- test/multiarch/*
tags:
- "[0-9]+.[0-9]+.[0-9]+-multiarch"
- "[0-9]+.[0-9]+.[0-9]+-multiarch-latest"
- "[0-9]+.[0-9]+.[0-9]+-java15"
jobs:
docker-buildx:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v2.2.0
- name: Prepare
id: prep
run: |
DOCKER_IMAGE=itzg/minecraft-server
VERSION=edge
if [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
fi
if [[ $GITHUB_REF == refs/heads/* ]]; then
VERSION=${GITHUB_REF#refs/heads/}
if [[ $VERSION == master ]]; then
VERSION=latest
fi
fi
TAGS="${DOCKER_IMAGE}:${VERSION//\//-}"
echo ::set-output name=tags::${TAGS}
echo ::set-output name=cache_from::${TAGS}
echo ::set-output name=version::${VERSION//\//-}
echo ::set-output name=cache_version::${VERSION//\//-}
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ steps.prep.outputs.cache_version }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-${{ steps.prep.outputs.cache_version }}-
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm/v7,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.prep.outputs.tags }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
labels: |
org.opencontainers.image.documentation=https://github.com/itzg/docker-minecraft-server
org.opencontainers.image.source=https://github.com/itzg/docker-minecraft-server
org.opencontainers.image.version=${{ steps.prep.outputs.version }}
org.opencontainers.image.revision=${{ github.sha }}
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}

View File

@@ -4,32 +4,94 @@ on:
push:
branches:
- master
- java8
- openj9
- openj9-nightly
- openj9-11
- adopt11
- adopt13
- test/*
tags:
- "[0-9]+.[0-9]+.[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+-java8"
- "[0-9]+.[0-9]+.[0-9]+-openj9"
- "[0-9]+.[0-9]+.[0-9]+-openj9-11"
- "[0-9]+.[0-9]+.[0-9]+-openj9-nightly"
- "[0-9]+.[0-9]+.[0-9]+-adopt11"
- "[0-9]+.[0-9]+.[0-9]+-adopt13"
jobs:
test:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Run tests
run: |
tests/test.sh
build:
runs-on: ubuntu-latest
needs:
- test
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Build and push Docker images
uses: docker/build-push-action@v1.1.0
- name: Prepare
id: prep
run: |
DOCKER_IMAGE=itzg/minecraft-server
VERSION=edge
if [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
fi
if [[ $GITHUB_REF == refs/heads/* ]]; then
VERSION=${GITHUB_REF#refs/heads/}
if [[ $VERSION == master ]]; then
VERSION=latest
fi
fi
TAGS="${DOCKER_IMAGE}:${VERSION//\//-}"
echo ::set-output name=tags::${TAGS}
echo ::set-output name=cache_from::${TAGS}
echo ::set-output name=version::${VERSION//\//-}
echo ::set-output name=cache_version::${VERSION//\//-}
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ steps.prep.outputs.cache_version }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-${{ steps.prep.outputs.cache_version }}-
${{ runner.os }}-buildx-
- name: Login to DockerHub
uses: docker/login-action@v1
with:
repository: itzg/minecraft-server
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }}
tag_with_ref: true
tag_with_sha: false
cache_froms: itzg/minecraft-server:latest
add_git_labels: true
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
# ensure latest base image is used
pull: true
# publish
push: true
# tags determined by prep step
tags: ${{ steps.prep.outputs.tags }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
labels: |
org.opencontainers.image.documentation=https://github.com/itzg/docker-minecraft-server
org.opencontainers.image.version=${{ steps.prep.outputs.version }}
org.opencontainers.image.source=https://github.com/itzg/docker-minecraft-server
org.opencontainers.image.revision=${{ github.sha }}
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}

View File

@@ -5,15 +5,12 @@ on:
branches: [ master ]
jobs:
build:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build Docker image
uses: docker/build-push-action@v1.1.0
with:
tag_with_sha: true
cache_froms: itzg/minecraft-server:latest
push: false
- name: Run tests
run: |
tests/test.sh

11
BUILDING.md Normal file
View File

@@ -0,0 +1,11 @@
Ensure buildx/BuildKit support is enabled and run:
```shell script
docker buildx build --platform=linux/arm64 --platform=linux/arm/v7 --platform=linux/amd64 --tag itzg/minecraft-server:multiarch --push .
```
To build for local testing, use:
```shell script
docker buildx build --platform=linux/amd64 --tag mc-multiarch --load .
```

View File

@@ -1,29 +1,29 @@
FROM openjdk:8u212-jre-alpine
FROM ubuntu:18.04
LABEL maintainer "itzg"
LABEL org.opencontainers.image.authors="Geoff Bourne <itzgeoff@gmail.com>"
RUN apk add --no-cache -U \
openssl \
imagemagick \
lsof \
su-exec \
shadow \
bash \
curl iputils wget \
git \
jq \
mysql-client \
tzdata \
rsync \
nano \
sudo \
knock \
ttf-dejavu
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive \
apt-get install -y \
openjdk-8-jre-headless \
imagemagick \
gosu \
sudo \
net-tools \
curl wget \
jq \
dos2unix \
mysql-client \
tzdata \
rsync \
nano \
unzip \
knockd \
ttf-dejavu \
&& apt-get clean
RUN addgroup -g 1000 minecraft \
&& adduser -Ss /bin/false -u 1000 -G minecraft -h /home/minecraft minecraft \
&& mkdir -m 777 /data \
&& chown minecraft:minecraft /data /home/minecraft
RUN addgroup --gid 1000 minecraft \
&& adduser --system --shell /bin/false --uid 1000 --ingroup minecraft --home /data minecraft
COPY files/sudoers* /etc/sudoers.d
@@ -31,9 +31,9 @@ EXPOSE 25565 25575
# 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 TARGETOS
ARG TARGETARCH
ARG TARGETVARIANT
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
@@ -52,7 +52,7 @@ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=1.4.3 --var app=mc-server-runner --file {{.app}} \
--var version=1.5.0 --var app=mc-server-runner --file {{.app}} \
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
@@ -67,11 +67,12 @@ COPY log4j2.xml /tmp/log4j2.xml
WORKDIR /data
ENV UID=1000 GID=1000 \
JVM_XX_OPTS="-XX:+UseG1GC" MEMORY="1G" \
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 SERVER_PORT=25565 ONLINE_MODE=TRUE SERVER_NAME="Dedicated Server" \
ENABLE_AUTOPAUSE=false AUTOPAUSE_TIMEOUT_EST=3600 AUTOPAUSE_TIMEOUT_KN=120 AUTOPAUSE_TIMEOUT_INIT=600 AUTOPAUSE_PERIOD=10
ENABLE_AUTOPAUSE=false AUTOPAUSE_TIMEOUT_EST=3600 AUTOPAUSE_TIMEOUT_KN=120 AUTOPAUSE_TIMEOUT_INIT=600 \
AUTOPAUSE_PERIOD=10 AUTOPAUSE_KNOCK_INTERFACE=eth0
COPY start* /
COPY health.sh /

200
README.md
View File

@@ -1,7 +1,7 @@
[![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)
[![Discord](https://img.shields.io/discord/660567679458869252)](https://discord.gg/DXfKpjB)
[![Discord](https://img.shields.io/discord/660567679458869252?label=Discord&logo=discord)](https://discord.gg/DXfKpjB)
[![Build and Publish](https://github.com/itzg/docker-minecraft-server/workflows/Build%20and%20Publish/badge.svg)](https://github.com/itzg/docker-minecraft-server/actions)
[![](https://img.shields.io/badge/Donate-Buy%20me%20a%20coffee-orange.svg)](https://www.buymeacoffee.com/itzg)
@@ -11,7 +11,7 @@ latest snapshot. See the _Versions_ section below for more information.
To simply use the latest stable version, run
docker run -d -p 25565:25565 --name mc itzg/minecraft-server
docker run -d -p 25565:25565 --name mc -e EULA=TRUE itzg/minecraft-server
where the standard server port, 25565, will be exposed on your host machine.
@@ -35,6 +35,7 @@ With that you can easily view the logs, stop, or re-start the container:
docker stop mc
docker start mc
*Be sure to always include `-e EULA=TRUE` in your commands, as Mojang/Microsoft requires EULA acceptance.*
## Looking for a Bedrock Dedicated Server
@@ -115,8 +116,24 @@ to map a directory on your host machine to the container's `/data` directory, su
docker run -d -v /path/on/host:/data ...
When attached in this way you can stop the server, edit the configuration under your attached `/path/on/host`
and start the server again with `docker start CONTAINERID` to pick up the new configuration.
When attached in this way you can stop the server, edit the configuration under your attached `/path/on/host` and start the server again with `docker start CONTAINER_ID` to pick up the new configuration.
As example, using Docker compose, create the following `docker-compose.yml` in its own directory and the container will automatically create/attach the relative directory `data` to the container:
```yaml
version: "3"
services:
mc:
image: itzg/minecraft-server
ports:
- 25565:25565
environment:
EULA: "TRUE"
volumes:
# attach the relative directory 'data' to the container's /data path
./data:/data
```
## Versions
@@ -143,20 +160,31 @@ the server jar remain in the `/data` directory. It is safe to remove those._
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 |
| Tag name | Java version | Linux | JVM Type | Architecture |
| -------------- | -------------|--------|----------|-------------------|
| latest | 11 | Alpine | Hotspot | amd64 |
| java8 | 8 | Alpine | Hotspot | amd64 |
| java8-multiarch | 8 | Debian | Hotspot | amd64,arm64,armv7 |
| java15 | 15 | Debian | Hotspot | amd64,arm64,armv7 |
| adopt11 | 11 | Alpine | Hotspot | amd64 |
| openj9 | 8 | Alpine | OpenJ9 | amd64 |
| openj9-11 | 11 | Alpine | OpenJ9 | amd64 |
| multiarch | 11 | Debian | Hotspot | amd64,arm64,armv7 |
| multiarch-latest | 15+ | Debian | Hotspot | amd64,arm64,armv7 |
For example, to use a Java version 13:
For example, to use Java version 15 on any supported architecture:
docker run --name mc itzg/minecraft-server:adopt13
docker run --name mc itzg/minecraft-server:java15
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.
> 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.
### Deprecated Image Tags
The following image tags have been deprecated and are no longer receiving updates:
- adopt13
- adopt14
- adopt15
- openj9-nightly
## Healthcheck
@@ -178,22 +206,22 @@ healthy
Some orchestration systems, such as Portainer, don't allow for disabling the default `HEALTHCHECK` declared by this image. In those cases you can approximate the disabling of healthchecks by setting the environment variable `DISABLE_HEALTHCHECK` to `true`.
## Autopause (experimental)
## Autopause
### Description
> EXPERIMENTAL: this feature only works with default bridge networking using official Docker distributions. Host networking and container management software, such as Portainer, and NAS solutions do not seem to provide compatible networking.
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.
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. Non-vanilla versions might have their own configuration file, you might have to disable their watchdogs separately (e.g. PAPER Servers).
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 utility used to wake the server (`knock(d)`) works at network interface level. So the correct interface has to be set using the `AUTOPAUSE_KNOCK_INTERFACE` variable when using non-default networking environments (e.g. host-networking, Portainer oder NAS solutions). See the description of the variable below.
A starting, example compose file has been provided in [examples/docker-compose-autopause.yml](examples/docker-compose-autopause.yml).
### Enabling Autopause
@@ -204,7 +232,7 @@ Enable the Autopause functionality by setting:
-e ENABLE_AUTOPAUSE=TRUE
```
There are 4 more environment variables that define the behaviour:
The following environment variables define the behaviour of auto-pausing:
* `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)
@@ -213,6 +241,8 @@ describes the time between server start and the pausing of the process, when no
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)
* `AUTOPAUSE_KNOCK_INTERFACE`, default `eth0`
<br>Describes the interface passed to the `knockd` daemon. If the default interface does not work, run the `ifconfig` command inside the container and derive the interface receiving the incoming connection from its output. The passed interface must exist inside the container. Using the loopback interface (`lo`) does likely not yield the desired results.
## Deployment Templates and Examples
@@ -225,14 +255,19 @@ describes period of the daemonized state machine, that handles the pausing of th
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.
### Amazon Web Services (AWS) Deployment
If you're looking for a simple way to deploy this to the Amazon Web Services Cloud, check out the [Minecraft Server Deployment (CloudFormation) repository](https://github.com/vatertime/minecraft-spot-pricing). This repository contains a CloudFormation template that will get you up and running in AWS in a matter of minutes. Optionally it uses Spot Pricing so the server is very cheap, and you can easily turn it off when not in use.
## 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`.
Enable [Forge server](http://www.minecraftforge.net/wiki/) mode by adding a `-e TYPE=FORGE` to your command-line.
The overall version is specified by `VERSION`, [as described in the section above](#versions) and will run the recommended Forge version by default. You can also choose to run a specific Forge version with `FORGEVERSION`, such as `-e FORGEVERSION=14.23.5.2854`.
$ docker run -d -v /path/on/host:/data \
-e TYPE=FORGE -e FORGEVERSION=10.13.4.1448 \
-e TYPE=FORGE \
-e VERSION=1.12.2 -e FORGEVERSION=14.23.5.2854 \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
To use a pre-downloaded Forge installer, place it in the attached `/data` directory and
@@ -269,10 +304,20 @@ the `/path/on/host` folder contents look like:
├── ops.json
├── server.properties
├── whitelist.json
├── worlds
│   └── ... PLACE MAPS IN THEIR OWN FOLDERS HERE ...
└── ...
```
If you add mods while the container is running, you'll need to restart it to pick those
Providing a presistent `/data` mount is a good idea, both to persist the game world and to allow for the manual configuration which is sometimes needed.
For instance, imagine a scenario when the initial launch has completed, but you now want to change the worldmap for your server.
Assuming you have a shared directory to your container, you can then (after first launch) drag and drop your premade maps or worlds into the `\worlds\` directory. **Note:** each world should be placed in its own folder under the `\worlds\` directory.
Once your maps are in the proper path, you can then specify which map the server uses by changing the `level-name` value in `server.properties` to match the name of your map.
If you add mods or make changes to `server.properties` while the container is running, you'll need to restart it to pick those
up:
docker stop mc
@@ -285,12 +330,18 @@ or downloading a world with the `WORLD` option.
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.
`/data` filesystem before starting Minecraft. If you want old mods to be removed as the `/mods` content is updated, then add `-e REMOVE_OLD_MODS=TRUE`. If you are running a `BUKKIT` distribution this will affect all files inside the `plugins/` directory. You can fine tune the removal process by specifing the `REMOVE_OLD_MODS_INCLUDE` and `REMOVE_OLD_MODS_EXCLUDE` variables. By default everything will be removed. You can also specify the `REMOVE_OLD_MODS_DEPTH` (default 16) variable to only delete files up to a certain level.
> For example: `-e REMOVE_OLD_MODS=TRUE -e REMOVE_OLD_MODS_INCLUDE="*.jar" -e REMOVE_OLD_MODS_DEPTH=1` will remove all old jar files that are directly inside the `plugins/` or `mods/` directory.
This works well if you want to have a common set of modules in a separate
location, but still have multiple worlds with different server requirements
in either persistent volumes or a downloadable archive.
You can specify the destination of the configs that are located inside the `/config` mount by setting the `COPY_CONFIG_DEST` variable. The configs are copied recursivly to the `/data/config` directory by default. If a file was updated directly inside the `/data/*` directoy and is newer than the file in the `/config/*` mount it will not be overriden.
> For example: `-v ./config:/config -e COPY_CONFIG_DEST=/data` will allow you to copy over your `bukkit.yml` and so on directly into the server directory.
### Replacing variables inside configs
Sometimes you have mods or plugins that require configuration information that is only available at runtime.
@@ -324,7 +375,13 @@ There are some limitations to what characters you can use.
Variables will be replaced in files with the following extensions:
`.yml`, `.yaml`, `.txt`, `.cfg`, `.conf`, `.properties`.
Specific files can be excluded by listing their name (without path) in the variable `REPLACE_ENV_VARIABLES_EXCLUDES`. Paths can be excluded by listing them in the variable `REPLACE_ENV_VARIABLES_EXCLUDE_PATHS`.
Specific files can be excluded by listing their name (without path) in the variable `REPLACE_ENV_VARIABLES_EXCLUDES`.
Paths can be excluded by listing them in the variable `REPLACE_ENV_VARIABLES_EXCLUDE_PATHS`. Path
excludes are recursive. Here is an example:
```
REPLACE_ENV_VARIABLES_EXCLUDE_PATHS="/data/plugins/Essentials/userdata /data/plugins/MyPlugin"
```
Here is a full example where we want to replace values inside a `database.yml`.
@@ -384,7 +441,7 @@ secrets:
The content of `db_password`:
ug23u3bg39o-ogADSs
## Running a Bukkit/Spigot server
Enable Bukkit/Spigot server mode by adding a `-e TYPE=BUKKIT` or `-e TYPE=SPIGOT` to your command-line.
@@ -402,9 +459,9 @@ You can build spigot from source by adding `-e BUILD_FROM_SOURCE=true`
If you have attached a host directory to the `/data` volume, then you can install plugins within the `plugins` subdirectory. You can also [attach a `/plugins` volume](#deploying-plugins-from-attached-volume). If you add plugins while the container is running, you'll need to restart it to pick those up.
## Running a PaperSpigot server
## Running a Paper server
Enable PaperSpigot server mode by adding a `-e TYPE=PAPER` to your command-line.
Enable Paper 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`.
@@ -413,7 +470,7 @@ but you can also choose to run a specific build with `-e PAPERBUILD=205`.
-e TYPE=PAPER \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
If you are hosting your own copy of PaperSpigot you can override the download URL with:
If you are hosting your own copy of Paper you can override the download URL with:
- -e PAPER_DOWNLOAD_URL=<url>
@@ -458,12 +515,12 @@ A [Catserver](http://catserver.moe/) type server can be used with
## Running a server with a Feed the Beast modpack
> **NOTE** requires `itzg/minecraft-server:multiarch` image
> **NOTE** requires one of the Debian based images listed in [the Java versions section](#running-minecraft-server-on-different-java-version).
[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_ID`: **required**, the numerical ID of the modpack to install. The ID can be located by [finding the modpack](https://www.feed-the-beast.com/modpack) and using the "ID" displayed next to the name
- `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
@@ -507,6 +564,16 @@ The following example uses `/modpacks` as the container path as the pre-download
-e CF_SERVER_MOD=/modpacks/SkyFactory_4_Server_4.1.0.zip \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
#### Modpack data directory
By default, CurseForge modpacks are expanded into the sub-directory `/data/FeedTheBeast` and executed from there. (The default location was chosen for legacy reasons, when Curse and FTB were maintained together.)
The directory can be changed by setting `CF_BASE_DIR`, such as `-e CF_BASE_DIR=/data`.
#### Buggy start scripts
Some modpacks have buggy or overly complex start scripts. You can avoid using the bundled start script and use this image's standard server-starting logic by adding `-e USE_MODPACK_START_SCRIPT=false`.
### Fixing "unable to launch forgemodloader"
If your server's modpack fails to load with an error [like this](https://support.feed-the-beast.com/t/cant-start-crashlanding-server-unable-to-launch-forgemodloader/6028/2):
@@ -534,29 +601,31 @@ Just change it with `SPONGEBRANCH`, such as:
## Running a Fabric Server
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`.
Enable [Fabric server](http://fabricmc.net/use/) mode by adding a `-e TYPE=FABRIC` to your command-line. By default, the container will run the latest version, but you can also choose to run a specific version with `VERSION`.
$ 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
```
docker run -d -v /path/on/host:/data \
-e TYPE=FABRIC \
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
```
To use a pre-downloaded Fabric installer, place it in the attached `/data` directory and
specify the name of the installer file with `FABRIC_INSTALLER`, such as:
A specific installer version can be requested using `FABRIC_INSTALLER_VERSION`.
$ docker run -d -v /path/on/host:/data ... \
-e FABRIC_INSTALLER=fabric-installer-0.5.0.32.jar ...
To use a pre-downloaded Fabric installer, place it in a directory attached into the container, such as the `/data` volume and specify the name of the installer file with `FABRIC_INSTALLER`, such as:
To download a Fabric installer from a custom location, such as your own file repository, specify
the URL with `FABRIC_INSTALLER_URL`, such as:
```
docker run -d -v /path/on/host:/data ... \
-e FABRIC_INSTALLER=fabric-installer-0.5.0.32.jar ...
```
$ docker run -d -v /path/on/host:/data ... \
-e FORGE_INSTALLER_URL=http://HOST/fabric-installer-0.5.0.32.jar ...
To download a Fabric installer from a custom location, such as your own file repository, specify the URL with `FABRIC_INSTALLER_URL`, such as:
In both of the cases above, there is no need for the `VERSION` or `FABRICVERSION` variables.
```
docker run -d -v /path/on/host:/data ... \
-e FABRIC_INSTALLER_URL=http://HOST/fabric-installer-0.5.0.32.jar ...
```
In order to add mods, you have two options.
In order to add mods, you have two options:
### Using the /data volume
@@ -707,12 +776,18 @@ To whitelist players for your Minecraft server, pass the Minecraft usernames sep
If the `WHITELIST` environment variable is not used, any user can join your Minecraft server if it's publicly accessible.
> NOTE: When `WHITELIST` is used the server property `white-list` will automatically get set to `true`.
> By default, the players in `WHITELIST` are **added** to the final `whitelist.json` file by the Minecraft server. If you set `OVERRIDE_WHITELIST` to "true" then the `whitelist.json` file will be recreated on each server startup.
### Op/Administrator Players
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 ...
> By default, the players in `OPS` are **added** to the final `ops.json` file by the Minecraft server. If you set `OVERRIDE_OPS` to "true" then the `ops.json` file will be recreated on each server startup.
### Server icon
A server icon can be configured using the `ICON` variable. The image will be automatically
@@ -720,6 +795,10 @@ downloaded, scaled, and converted from any other image format:
docker run -d -e ICON=http://..../some/image.png ...
The server icon which has been set doesn't get overridden by default. It can be changed and overridden by setting `OVERRIDE_ICON` to `TRUE`.
docker run -d -e ICON=http://..../some/other/image.png -e OVERRIDE_ICON=TRUE...
### Rcon
To use rcon use the `ENABLE_RCON` and `RCON_PASSORD` variables.
@@ -886,7 +965,7 @@ environment variable set to `false`, such as
### Level Type and Generator Settings
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
be configured by setting `LEVEL_TYPE` to an expected type, for example
- DEFAULT
- FLAT
@@ -894,6 +973,8 @@ be configured by setting `LEVEL_TYPE` to an expected type, such as
- AMPLIFIED
- CUSTOMIZED
- BUFFET
- BIOMESOP (Biomes O' Plenty for 1.12 and older)
- BIOMESOPLENTY (Biomes O' Plenty for 1.15 and above)
Descriptions are available at the [gamepedia](http://minecraft.gamepedia.com/Server.properties).
@@ -1024,19 +1105,18 @@ is passed to `docker run`.
### Memory Limit
By default, the image declares a Java initial and maximum memory limit of 1 GB. There are several
ways to adjust the memory settings:
By default, the image declares an initial and maximum Java memory-heap 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 settings of the JVM
- `INIT_MEMORY`, independently sets the initial heap size
- `MAX_MEMORY`, independently sets the max heap size
- `MEMORY`: "1G" by default, can be used to adjust both initial (`Xms`) and max (`Xmx`) memory heap settings of the JVM
- `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:
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:
-e MEMORY=2G
> NOTE: the settings above only set the Java **heap** limits. Memory resource requests and limits on the overall container should also account for non-heap memory usage. An extra 25% is [a general best practice](https://dzone.com/articles/best-practices-java-memory-arguments-for-container).
### JVM Options
General JVM options can be passed to the Minecraft Server invocation by passing a `JVM_OPTS`
@@ -1081,6 +1161,10 @@ Some older versions (pre-1.14) of Spigot required `--noconsole` to be passed whe
Some older servers get confused and think that the GUI interface is enabled. You can explicitly
disable that by passing `-e GUI=FALSE`.
### Stop Duration
When the container is signalled to stop, the Minecraft process wrapper will attempt to send a "stop" command via RCON or console and waits for the process to gracefully finish. By defaul it waits 60 seconds, but that duration can be configured by setting the environment variable `STOP_DURATION` to the number of seconds.
## Running on RaspberryPi
To run this image on a RaspberryPi 3 B+, 4, or newer, use the image tag

View File

@@ -1,7 +1,7 @@
#!/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')
branches_list=('java8' 'java8-multiarch' 'openj9' 'openj9-11' 'adopt11' 'java15' 'multiarch' 'multiarch-latest')
function TrapExit {
echo "Checking out back in master"

0
docs/.gitkeep Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -0,0 +1,12 @@
version: "3"
services:
mc:
image: itzg/minecraft-server
ports:
- 25565:25565
environment:
EULA: "TRUE"
volumes:
# attach the relative directory 'data' to the container's /data path
./data:/data

View File

@@ -1,3 +1,3 @@
Please server [modpacks downloaded from CurseForge](https://www.curseforge.com/minecraft/modpacks) in this directory.
Place 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

@@ -2,23 +2,48 @@
. /autopause/autopause-fcns.sh
. /start-utils
. ${SCRIPTS:-/}start-utils
sudo /usr/sbin/knockd -c /autopause/knockd-config.cfg -d
if [ $? -ne 0 ] ; then
autopause_error_loop() {
logAutopause "Available interfaces within the docker container:"
INTERFACES=$(echo /sys/class/net/*)
INTERFACES=${INTERFACES//\/sys\/class\/net\//}
logAutopause " $INTERFACES"
logAutopause "Please set the environment variable AUTOPAUSE_KNOCK_INTERFACE to the interface that handles incoming connections."
logAutopause "If unsure which interface to choose, run the ifconfig command in the container."
logAutopause "Autopause failed to initialize. This log entry will be printed every 30 minutes."
while :
do
if [[ -n $(ps -o comm | grep java) ]] ; then
break
fi
sleep 0.1
sleep 1800
logAutopause "Autopause failed to initialize."
done
}
# wait for java process to be started
while :
do
if java_process_exists ; then
break
fi
sleep 0.1
done
# check for interface existence
if [[ -z "$AUTOPAUSE_KNOCK_INTERFACE" ]] ; then
logAutopause "AUTOPAUSE_KNOCK_INTERFACE variable must not be empty!"
autopause_error_loop
fi
if ! [[ -d "/sys/class/net/$AUTOPAUSE_KNOCK_INTERFACE" ]] ; then
logAutopause "Selected interface \"$AUTOPAUSE_KNOCK_INTERFACE\" does not exist!"
autopause_error_loop
fi
sudo /usr/sbin/knockd -c /tmp/knockd-config.cfg -d -i "$AUTOPAUSE_KNOCK_INTERFACE"
if [ $? -ne 0 ] ; then
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
logAutopause "Probable cause: Unable to attach to interface \"$AUTOPAUSE_KNOCK_INTERFACE\"."
autopause_error_loop
fi
STATE=INIT

View File

@@ -5,15 +5,19 @@ current_uptime() {
}
java_running() {
[[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]]
[[ $( ps -ax -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]]
}
java_process_exists() {
[[ -n "$(ps -ax -o comm | grep 'java')" ]]
}
rcon_client_exists() {
[[ -n "$(ps -a -o comm | grep 'rcon-cli')" ]]
[[ -n "$(ps -ax -o comm | grep 'rcon-cli')" ]]
}
mc_server_listening() {
[[ -n $(netstat -tln | grep "0.0.0.0:$SERVER_PORT" | grep LISTEN) ]]
[[ -n $(netstat -tln | grep -e "0.0.0.0:$SERVER_PORT" -e ":::$SERVER_PORT" | grep LISTEN) ]]
}
java_clients_connected() {
@@ -29,7 +33,7 @@ java_clients_connected() {
# 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
if [[ ! $(echo "${connections[$i]}" | awk '{print $5}') =~ ^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$ ]] ; then
# not localhost
return 0
fi

View File

@@ -3,10 +3,10 @@
[unpauseMCServer-server]
sequence = 25565
seq_timeout = 1
command = /sbin/su-exec minecraft:minecraft /autopause/resume.sh
command = /usr/sbin/gosu minecraft:minecraft /autopause/resume.sh
tcpflags = syn
[unpauseMCServer-rcon]
sequence = 25575
seq_timeout = 1
command = /sbin/su-exec minecraft:minecraft /autopause/resume.sh
command = /usr/sbin/gosu minecraft:minecraft /autopause/resume.sh
tcpflags = syn

View File

@@ -2,7 +2,7 @@
. /start-utils
if [[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]] ; then
if [[ $( ps -ax -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]] ; then
# save world
rcon-cli save-all >/dev/null
@@ -17,5 +17,5 @@ if [[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]] ; th
# finally pause the process
logAutopauseAction "Pausing Java process"
killall -q -STOP java
pkill -STOP java
fi

View File

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

View File

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

View File

@@ -5,7 +5,7 @@
if isTrue "${DISABLE_HEALTHCHECK}"; then
echo "Healthcheck disabled"
exit 0
elif isTrue "${ENABLE_AUTOPAUSE}" && [[ "$( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }')" =~ ^T.*$ ]]; then
elif isTrue "${ENABLE_AUTOPAUSE}" && [[ "$( ps -ax -o stat,comm | grep 'java' | awk '{ print $1 }')" =~ ^T.*$ ]]; then
echo "Java process suspended by Autopause function"
exit 0
else

7
start
View File

@@ -36,16 +36,11 @@ if [ $(id -u) = 0 ]; then
chown -R ${runAsUser}:${runAsGroup} /data
fi
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} ${SCRIPTS:-/}start-configuration $@
exec gosu ${runAsUser}:${runAsGroup} ${SCRIPTS:-/}start-configuration $@
else
exec ${SCRIPTS:-/}start-configuration $@
fi

View File

@@ -4,18 +4,20 @@
log "Autopause functionality enabled"
cp /autopause/knockd-config.cfg /tmp/knockd-config.cfg
# 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
linenum=$(grep -nm1 sequence /tmp/knockd-config.cfg | cut -d : -f 1 | tail -n1)
if ! [[ $(awk "NR==$linenum" /tmp/knockd-config.cfg) =~ $regseq ]]; then
sed -i "${linenum}s/sequence.*/sequence = $SERVER_PORT/" /tmp/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
linenum=$(grep -nm2 sequence /tmp/knockd-config.cfg | cut -d : -f 1 | tail -n1)
if ! [[ $(awk "NR==$linenum" /tmp/knockd-config.cfg) =~ $regseq ]]; then
sed -i "${linenum}s/sequence.*/sequence = $RCON_PORT/" /tmp/knockd-config.cfg
log "Updated rcon port in knockd config"
fi
@@ -44,10 +46,15 @@ if ! [[ $AUTOPAUSE_TIMEOUT_INIT =~ ^[0-9]+$ ]] ; then
export AUTOPAUSE_TIMEOUT_INIT
log "Warning: AUTOPAUSE_TIMEOUT_INIT is not numeric, set to 600 (seconds)"
fi
if [[ "$AUTOPAUSE_KNOCK_INTERFACE" == "lo" ]] ; then
log "Warning: AUTOPAUSE_KNOCK_INTERFACE is set to the local loopback interface."
log " This is not advisable, as incoming connections are likely not picked up there."
log " Continuing with this setting."
fi
if [[ -n $MAX_TICK_TIME ]] ; then
if [[ -n "$MAX_TICK_TIME" && "$MAX_TICK_TIME" != "-1" ]] ; 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
elif [[ -z "$MAX_TICK_TIME" ]] ; then
if versionLessThan 1.8.1; then
# 10 years
MAX_TICK_TIME=315360000000

View File

@@ -7,9 +7,10 @@ shopt -s nullglob
#umask 002
export HOME=/data
log "Running as uid=$(id -u) gid=$(id -g) with /data as '$(ls -lnd /data)'"
if [ ! -e /data/eula.txt ]; then
EULA="${EULA,,}"
if [ "$EULA" != "true" ]; then
if ! isTrue "$EULA"; then
log ""
log "Please accept the Minecraft EULA at"
log " https://account.mojang.com/documents/minecraft_eula"
@@ -19,24 +20,10 @@ if [ ! -e /data/eula.txt ]; then
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
writeEula
fi
log "Running as uid=$(id -u) gid=$(id -g) with /data as '$(ls -lnd /data)'"
if ! touch /data/.verify_access; then
log "ERROR: /data doesn't seem to be writable. Please make sure attached directory is writable by uid=$(id -u)"
exit 2
fi
rm /data/.verify_access || true
if [[ $PROXY ]]; then
export http_proxy="$PROXY"
export https_proxy="$PROXY"
@@ -45,6 +32,22 @@ if [[ $PROXY ]]; then
sleep 5
fi
if [[ $RCON_PASSWORD_FILE ]]; then
log ""
if [ ! -e ${RCON_PASSWORD_FILE} ]; then
log "Initial RCON password file ${RCON_PASSWORD_FILE} does not seems to exist."
log "Please ensure your configuration."
log "If you are using Docker Secrets feature, please check this for further information: "
log " https://docs.docker.com/engine/swarm/secrets"
log ""
exit 1
else
RCON_PASSWORD=$(cat ${RCON_PASSWORD_FILE})
export RCON_PASSWORD
fi
log ""
fi
export SERVER_PROPERTIES=/data/server.properties
export VERSIONS_JSON=https://launchermeta.mojang.com/mc/game/version_manifest.json
@@ -55,11 +58,8 @@ case "X$VERSION" in
XSNAPSHOT|Xsnapshot)
VANILLA_VERSION=$(curl -fsSL $VERSIONS_JSON | jq -r '.latest.snapshot')
;;
X[1-9]*)
VANILLA_VERSION=$VERSION
;;
*)
VANILLA_VERSION=$(curl -fsSL $VERSIONS_JSON | jq -r '.latest.release')
VANILLA_VERSION=$VERSION
;;
esac
export VANILLA_VERSION
@@ -88,6 +88,10 @@ case "${TYPE^^}" in
;;
FORGE)
log "**********************************************************************"
log "WARNING: The image tag itzg/minecraft-server:java8 is recommended"
log " since some mods require Java 8"
log "**********************************************************************"
exec ${SCRIPTS:-/}start-deployForge "$@"
;;
@@ -95,8 +99,12 @@ case "${TYPE^^}" in
exec ${SCRIPTS:-/}start-deployFabric "$@"
;;
FTB|CURSEFORGE)
exec ${SCRIPTS:-/}start-deployFTB "$@"
FTBA)
exec ${SCRIPTS:-/}start-deployFTBA "$@"
;;
CURSEFORGE|FTB)
exec ${SCRIPTS:-/}start-deployCF "$@"
;;
VANILLA)
@@ -129,8 +137,9 @@ case "${TYPE^^}" in
*)
log "Invalid type: '$TYPE'"
log "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTBA, CURSEFORGE, SPONGEVANILLA,"
log " CUSTOM, CURSE_INSTANCE, MAGMA, MOHIST, CATSERVER"
log "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTBA (multiarch-only),"
log " CURSE_INSTANCE, CURSEFORGE, SPONGEVANILLA,"
log " CUSTOM, MAGMA, MOHIST, CATSERVER"
exit 1
;;

View File

@@ -1,6 +1,7 @@
#!/bin/bash
. ${SCRIPTS:-/}start-utils
isDebugging && set -x
set -e
@@ -58,12 +59,24 @@ function downloadSpigot {
;;
esac
if [[ ${VERSION^^} = LATEST ]]; then
VANILLA_VERSION=$(restify https://getbukkit.org/download/spigot --attribute='property=og:title' | jq -r '.[0] | .attributes | select(.property == "og:title") | .content | split(" ") | .[-1]')
fi
if [[ -z $downloadUrl ]]; then
downloadUrl="https://cdn.getbukkit.org/${getbukkitFlavor}/${getbukkitFlavor}-${VANILLA_VERSION}.jar"
fi
setServerVar
if [ -f $SERVER ]; then
# tell curl to only download when newer
curlArgs="-z $SERVER"
fi
if isDebugging; then
curlArgs="$curlArgs -v"
fi
log "Downloading $match from $downloadUrl ..."
curl -fsSL -o $SERVER "$downloadUrl"
curl -fsSL -o $SERVER $curlArgs "$downloadUrl"
if [[ $? != 0 || $(grep -c "DOCTYPE html" $SERVER) != 0 ]]; then
cat <<EOF
@@ -72,6 +85,13 @@ ERROR: failed to download from $downloadUrl
exact version, such as 1.4.6-R0.4-SNAPSHOT or 1.8-R0.1-SNAPSHOT-LATEST
EOF
if isDebugging && [[ $(grep -c "DOCTYPE html" $SERVER) != 0 ]]; then
cat $SERVER
fi
# remove invalid download
rm $SERVER
exit 3
fi
@@ -79,22 +99,24 @@ EOF
export JVM_OPTS
}
function setServerVar {
case "$TYPE" in
*BUKKIT|*bukkit)
export SERVER=craftbukkit_server-${VANILLA_VERSION}.jar
;;
*)
export SERVER=spigot_server-${VANILLA_VERSION}.jar
;;
esac
}
case "$TYPE" in
*BUKKIT|*bukkit)
export SERVER=craftbukkit_server-${VANILLA_VERSION}.jar
;;
*)
export SERVER=spigot_server-${VANILLA_VERSION}.jar
;;
esac
if [ ! -f $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
if isTrue "$BUILD_SPIGOT_FROM_SOURCE" || isTrue "$BUILD_FROM_SOURCE"; then
buildSpigotFromSource
else
downloadSpigot
fi
if isTrue "$BUILD_SPIGOT_FROM_SOURCE" || isTrue "$BUILD_FROM_SOURCE"; then
setServerVar
if [ ! -f $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
buildSpigotFromSource
fi
else
downloadSpigot
fi
# Normalize on Spigot for operations below

View File

@@ -1,26 +1,83 @@
#!/bin/bash
. ${SCRIPTS:-/}start-utils
set -e
export FTB_BASE_DIR=/data/FeedTheBeast
legacyJavaFixerUrl=http://ftb.cursecdn.com/FTB2/maven/net/minecraftforge/lex/legacyjavafixer/1.0/legacyjavafixer-1.0.jar
export TYPE=FEED-THE-BEAST
. ${SCRIPTS:-/}start-utils
isDebugging && set -x
: ${FTB_BASE_DIR:=${CF_BASE_DIR:-/data/FeedTheBeast}}
export FTB_BASE_DIR
legacyJavaFixerUrl=https://ftb.forgecdn.net/FTB2/maven/net/minecraftforge/lex/legacyjavafixer/1.0/legacyjavafixer-1.0.jar
export TYPE=CURSEFORGE
FTB_SERVER_MOD=${FTB_SERVER_MOD:-$CF_SERVER_MOD}
log "Looking for Feed-The-Beast / CurseForge server modpack."
if [[ -z $FTB_SERVER_MOD ]]; then
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.)"
requireVar FTB_SERVER_MOD
if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then
if ! [ -f "${FTB_SERVER_MOD}" ]; then
log "ERROR unable to find requested modpack file ${FTB_SERVER_MOD}"
exit 2
fi
needsInstall=true
installMarker=/data/.curseforge-installed
if [ -f $installMarker ]; then
if [ "$(cat $installMarker)" != "${FTB_SERVER_MOD}" ]; then
log "Upgrading modpack"
serverJar=$(find ${FTB_BASE_DIR} -not -name "forge*installer.jar" -name "forge*.jar")
if [[ "${serverJar}" ]]; then
rm -rf $(dirname "${serverJar}")/{mods,*.jar,libraries,resources,scripts,config}
fi
else
needsInstall=false
fi
fi
if $needsInstall; then
log "Unpacking FTB server modpack ${FTB_SERVER_MOD} ..."
mkdir -p ${FTB_BASE_DIR}
unzip -o "${FTB_SERVER_MOD}" -d ${FTB_BASE_DIR} | awk '{printf "."} END {print ""}'
serverJar=$(find ${FTB_BASE_DIR} -path "*/libraries/*" -prune -type f -o -not -name "forge*installer.jar" -name "forge*.jar")
if [[ -z "$serverJar" ]]; then
forgeInstallerJar=$(find ${FTB_BASE_DIR} -name "forge*installer.jar")
if [[ -z "${forgeInstallerJar}" ]]; then
log "ERROR Unable to find forge installer in modpack."
log " Make sure you downloaded the server files."
exit 2
fi
log "Installing forge server"
(cd $(dirname "${forgeInstallerJar}"); java -jar $(basename "${forgeInstallerJar}") --installServer) | awk '{printf "."} END {print ""}'
fi
echo "${FTB_SERVER_MOD}" > $installMarker
fi
export SERVER=$(find ${FTB_BASE_DIR} -path "*/libraries/*" -prune -type f -o -not -name "forge*installer.jar" -name "forge*.jar")
if [[ -z "${SERVER}" || ! -f "${SERVER}" ]]; then
log "ERROR unable to locate installed forge server jar"
isDebugging && find ${FTB_BASE_DIR} -name "forge*.jar"
exit 2
fi
export FTB_DIR=$(dirname "${SERVER}")
exec ${SCRIPTS:-/}start-finalSetupWorld $@
fi
entryScriptExpr="
-name ServerStart.sh
-o -name serverstart.sh
-o -name ServerStartLinux.sh
-o -name LaunchServer.sh
-o -name server-start.sh
-o -name startserver.sh
-o -name StartServer.sh
"
if [[ -d ${FTB_BASE_DIR} ]]; then
@@ -38,7 +95,7 @@ fi
# this allows saving just the world separate from the rest of the data directory
if [[ $startScriptCount = 0 ]]; then
srv_modpack=${FTB_SERVER_MOD}
if isURL ${srv_modpack}; then
if isURL "${srv_modpack}"; then
case $srv_modpack in
https://www.feed-the-beast.com/*/download|https://www.curseforge.com/minecraft/modpacks/*/download/*/file)
;;
@@ -56,19 +113,19 @@ if [[ $startScriptCount = 0 ]]; then
fi
srv_modpack=$downloaded
fi
if [[ ${srv_modpack:0:5} == "data/" ]]; then
if [[ "${srv_modpack:0:5}" == "data/" ]]; then
# Prepend with "/"
srv_modpack=/${srv_modpack}
srv_modpack="/${srv_modpack}"
fi
if [[ ! ${srv_modpack:0:1} == "/" ]]; then
if [[ ! "${srv_modpack:0:1}" == "/" ]]; then
# If not an absolute path, assume file is in "/data"
srv_modpack=/data/${srv_modpack}
fi
if [[ ! -f ${srv_modpack} ]]; then
if [[ ! -f "${srv_modpack}" ]]; then
log "FTB server modpack ${srv_modpack} not found."
exit 2
fi
if [[ ! ${srv_modpack: -4} == ".zip" ]]; then
if [[ ! "${srv_modpack: -4}" == ".zip" ]]; then
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
@@ -76,7 +133,7 @@ if [[ $startScriptCount = 0 ]]; then
log "Unpacking FTB server modpack ${srv_modpack} ..."
mkdir -p ${FTB_BASE_DIR}
unzip -o ${srv_modpack} -d ${FTB_BASE_DIR} | awk '{printf "."} END {print ""}'
unzip -o "${srv_modpack}" -d ${FTB_BASE_DIR} | awk '{printf "."} END {print ""}'
fi
if [[ $(find ${FTB_BASE_DIR} $entryScriptExpr | wc -l) = 0 ]]; then
@@ -114,7 +171,7 @@ export FTB_SERVER_START=$(find "${FTB_BASE_DIR}" $entryScriptExpr)
export FTB_DIR=$(dirname "${FTB_SERVER_START}")
chmod a+x "${FTB_SERVER_START}"
grep fml.queryResult=confirm ${FTB_SERVER_START} > /dev/null || \
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"

View File

@@ -17,12 +17,16 @@ if isURL ${CUSTOM_SERVER}; then
fi
elif [[ -f ${CUSTOM_SERVER} ]]; then
log "Using custom server jar at ${CUSTOM_SERVER} ..."
export SERVER=${CUSTOM_SERVER}
elif [[ ${GENERIC_PACK} ]]; then
log "Using custom server jar from generic pack at ${CUSTOM_SERVER} ..."
export SERVER=${CUSTOM_SERVER}
else
log "CUSTOM_SERVER is not properly set to a URL or existing jar file"
exit 2
fi
export SKIP_LOG4J_CONFIG=true

72
start-deployFTBA Normal file
View File

@@ -0,0 +1,72 @@
#!/bin/bash
ftbInstallMarker=".ftb-installed"
. ${SCRIPTS:-/}start-utils
isDebugging && set -x
set -e
if ! [[ -v FTB_MODPACK_ID ]]; then
log "ERROR FTB_MODPACK_ID is required with TYPE=FTB"
exit 1
fi
if ! [[ ${FTB_MODPACK_ID} =~ [0-9]+ ]]; then
log "ERROR FTB_MODPACK_ID needs to be numeric"
exit 1
fi
if ! [[ -v FTB_MODPACK_VERSION_ID ]]; then
if ! FTB_MODPACK_VERSION_ID=$(curl -fsSL https://api.modpacks.ch/public/modpack/${FTB_MODPACK_ID} | jq -r '.versions | sort_by(.updated)[-1].id'); then
log "ERROR unable to resolve latest modpack version ID for modpack ${FTB_MODPACK_ID}"
exit 1
fi
elif ! [[ ${FTB_MODPACK_VERSION_ID} =~ [0-9]+ ]]; then
log "ERROR FTB_MODPACK_VERSION_ID needs to be numeric"
exit 1
fi
if ! [ -f "${ftbInstallMarker}" ] || [ $(cat "${ftbInstallMarker}") != "${FTB_MODPACK_ID}=${FTB_MODPACK_VERSION_ID}" ]; then
ftbInstaller=/data/ftb-installer
if ! [[ -f "${ftbInstaller}" ]]; then
log "Downloading FTB installer"
curl -fsSL https://api.modpacks.ch/public/modpack/1/1/server/linux -o "${ftbInstaller}"
chmod +x "${ftbInstaller}"
fi
rm -rf forge*jar mods config libraries defaultconfigs changelogs
log "Installing modpack ID ${FTB_MODPACK_ID}, version ID ${FTB_MODPACK_VERSION_ID}"
${ftbInstaller} ${FTB_MODPACK_ID} ${FTB_MODPACK_VERSION_ID} --noscript --auto
rm -f forge*installer.jar
echo "${FTB_MODPACK_ID}=${FTB_MODPACK_VERSION_ID}" > ${ftbInstallMarker}
writeEula
else
log "FTB modpack ID ${FTB_MODPACK_ID}, version ID ${FTB_MODPACK_VERSION_ID} is ready to go"
fi
isDebugging && cat version.json
forgeVersion=$(jq -r '.targets|unique[] | select(.name == "forge") | .version' version.json)
mcVersion=$(jq -r '.targets|unique[] | select(.name == "minecraft") | .version' version.json)
variants=(
forge-${mcVersion}-${forgeVersion}.jar
forge-${mcVersion}-${forgeVersion}-universal.jar
forge-${mcVersion}-${forgeVersion}-${mcVersion}-universal.jar
)
for f in ${variants[@]}; do
if [ -f $f ]; then
export SERVER=$f
break
fi
done
if ! [ -v SERVER ]; then
log "ERROR unable to locate the installed forge server jar"
ls *.jar
exit 2
fi
# Continue to Final Setup
exec ${SCRIPTS:-/}start-finalSetupWorld $@

View File

@@ -7,36 +7,34 @@ export TYPE=FABRIC
FABRIC_INSTALLER=${FABRIC_INSTALLER:-}
FABRIC_INSTALLER_URL=${FABRIC_INSTALLER_URL:-}
FABRICVERSION=${FABRICVERSION:-LATEST}
FABRIC_INSTALLER_VERSION=${FABRIC_INSTALLER_VERSION:-${FABRICVERSION:-LATEST}}
if [[ -z $FABRIC_INSTALLER && -z $FABRIC_INSTALLER_URL ]]; then
log "Checking Fabric version information."
case $FABRICVERSION in
case $FABRIC_INSTALLER_VERSION in
LATEST)
FABRIC_VERSION=$(maven-metadata-release https://maven.fabricmc.net/net/fabricmc/fabric-installer/maven-metadata.xml)
;;
*)
FABRIC_VERSION=$FABRICVERSION
FABRIC_INSTALLER_VERSION=$(maven-metadata-release https://maven.fabricmc.net/net/fabricmc/fabric-installer/maven-metadata.xml)
;;
esac
FABRIC_INSTALLER="/tmp/fabric-installer-$FABRIC_VERSION.jar"
FABRIC_INSTALLER="/tmp/fabric-installer-${FABRIC_INSTALLER_VERSION}.jar"
markerVersion=$FABRIC_INSTALLER_VERSION
elif [[ -z $FABRIC_INSTALLER ]]; then
FABRIC_INSTALLER="/tmp/fabric-installer.jar"
markerVersion=custom
elif [[ ! -e $FABRIC_INSTALLER ]]; then
log "ERROR: the given Fabric installer doesn't exist : $FABRIC_INSTALLER"
exit 2
fi
installMarker="/data/.fabric-installed-${VANILLA_VERSION}-${FABRIC_VERSION:-manual}"
installMarker="/data/.fabric-installed-${VANILLA_VERSION}-${markerVersion}"
debug Checking for installMarker ${installMarker}
if [[ ! -e $installMarker ]]; then
if [[ ! -e $FABRIC_INSTALLER ]]; then
if [[ -z $FABRIC_INSTALLER_URL ]]; then
log "Downloading $FABRIC_VERSION"
downloadUrl="https://maven.fabricmc.net/net/fabricmc/fabric-installer/$FABRIC_VERSION/fabric-installer-$FABRIC_VERSION.jar"
log "Downloading installer version $FABRIC_INSTALLER_VERSION"
downloadUrl="https://maven.fabricmc.net/net/fabricmc/fabric-installer/${FABRIC_INSTALLER_VERSION}/fabric-installer-${FABRIC_INSTALLER_VERSION}.jar"
log "...trying $downloadUrl"
curl -o $FABRIC_INSTALLER -fsSL $downloadUrl
else
@@ -49,9 +47,9 @@ if [[ ! -e $installMarker ]]; then
fi
if isDebugging; then
debug "Installing Fabric $FABRIC_VERSION using $FABRIC_INSTALLER with mcversion ${VANILLA_VERSION}"
debug "Installing Fabric ${VANILLA_VERSION} using $FABRIC_INSTALLER"
else
log "Installing Fabric $FABRIC_VERSION using $FABRIC_INSTALLER"
log "Installing Fabric using $FABRIC_INSTALLER"
fi
tries=3
set +e

View File

@@ -1,23 +1,78 @@
#!/bin/bash
. ${SCRIPTS:-/}start-utils
set -o pipefail
isDebugging && set -x
: ${PAPERBUILD:=latest}
export SERVER=paper_server-${VANILLA_VERSION}-${PAPERBUILD}.jar
if [[ $PAPER_DOWNLOAD_URL ]]; then
export SERVER=$(getFilenameFromUrl "${PAPER_DOWNLOAD_URL}")
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
if [ -f "$SERVER" ]; then
zarg=(-z "$SERVER")
fi
echo "Preparing custom PaperMC jar from $PAPER_DOWNLOAD_URL"
curl -fsSL -o "$SERVER" "${zarg[@]}" "${PAPER_DOWNLOAD_URL}"
else
# PaperMC API v2 docs : https://papermc.io/api/docs/swagger-ui/index.html?configUrl=/api/openapi/swagger-config
build=${PAPERBUILD:=$(curl -fsSL "https://papermc.io/api/v2/projects/paper/versions/${VANILLA_VERSION}" -H "accept: application/json" \
| jq '.builds[-1]')}
case $? in
0)
;;
22)
versions=$(curl -fsSL "https://papermc.io/api/v2/projects/paper" -H "accept: application/json")
if [[ $VERSION = LATEST ]]; then
VANILLA_VERSION=$(echo "$versions" | jq -r '.versions[-1]')
log "WARN: using ${VANILLA_VERSION} since that's the latest provided by PaperMC"
# re-execute the current script with the newly computed version
exec "$0" "$@"
fi
log "ERROR: ${VANILLA_VERSION} is not published by PaperMC"
log " Set VERSION to one of the following: "
log " $(echo "$versions" | jq -r '.versions | join(", ")')"
exit 1
;;
*)
echo "ERROR: unknown error while looking up PaperMC version=${VANILLA_VERSION}"
exit 1
;;
esac
if [ $? != 0 ]; then
echo "ERROR: failed to lookup PaperMC build from version ${VANILLA_VERSION}"
exit 1
fi
export SERVER=$(curl -fsSL "https://papermc.io/api/v2/projects/paper/versions/${VANILLA_VERSION}/builds/${build}" -H "accept: application/json" \
| jq -r '.downloads.application.name')
if [ $? != 0 ]; then
echo "ERROR: failed to lookup PaperMC download file from version=${VANILLA_VERSION} build=${build}"
exit 1
fi
if [ -f "$SERVER" ]; then
zarg=(-z "$SERVER")
fi
log "Removing old PaperMC versions ..."
paperJarSearchString=${SERVER/$build/[0-9]*}
find . -name "$paperJarSearchString" ! -name "$SERVER" -delete -print
log "Downloading PaperMC $VANILLA_VERSION (build $build) ..."
curl -fsSL -o "$SERVER" "${zarg[@]}" \
"https://papermc.io/api/v2/projects/paper/versions/${VANILLA_VERSION}/builds/${build}/downloads/${SERVER}" \
-H "accept: application/java-archive"
if [ $? != 0 ]; then
echo "ERROR: failed to download PaperMC from version=${VANILLA_VERSION} build=${build} download=${SERVER}"
exit 1
fi
fi
# Normalize on Spigot for operations below
# Normalize on Spigot for downstream operations
export TYPE=SPIGOT
export SKIP_LOG4J_CONFIG=true
# Continue to Final Setup
exec ${SCRIPTS:-/}start-finalSetupWorld $@
exec ${SCRIPTS:-/}start-finalSetupWorld "$@"

View File

@@ -26,6 +26,9 @@ if [ ! -e $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
if [ $result != 0 ]; then
log "ERROR failed to obtain version manifest from $versionManifestUrl ($result)"
exit 1
elif [ $serverDownloadUrl = null ]; then
log "ERROR version $VANILLA_VERSION does not provide a server download"
exit 1
fi
debug "Downloading server from $serverDownloadUrl"

View File

@@ -7,14 +7,20 @@
if isTrue "${REPLACE_ENV_VARIABLES}"; then
log "Replacing env variables in configs that match the prefix $ENV_VARIABLE_PREFIX..."
findExcludes=
# File excludes
fileExcludes=
for f in ${REPLACE_ENV_VARIABLES_EXCLUDES}; do
findExcludes="${findExcludes} -not -name $f"
fileExcludes="${fileExcludes} -not -name $f"
done
for p in ${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS}; do
findExcludes="${findExcludes} -not -path \"*$p*\""
done
isDebugging && echo "Using find exclusion: $findExcludes"
# Directory excludes (recursive)
dirExcludes=$(join_by " -o -path " ${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS})
if [[ $dirExcludes ]]; then
dirExcludes=" -type d ( -path ${dirExcludes} ) -prune -o"
fi
isDebugging && echo "Using find file exclusions: $fileExcludes"
isDebugging && echo "Using find directory exclusions: $dirExcludes"
while IFS='=' read -r name value ; do
# check if name of env variable matches the prefix
@@ -29,10 +35,12 @@ if isTrue "${REPLACE_ENV_VARIABLES}"; then
fi
log "Replacing $name with $value ..."
find /data/ -type f \
find /data/ \
$dirExcludes \
-type f \
\( -name "*.yml" -or -name "*.yaml" -or -name "*.txt" -or -name "*.cfg" \
-or -name "*.conf" -or -name "*.properties" \) \
$findExcludes \
$fileExcludes \
-exec sed -i 's#${'"$name"'}#'"$value"'#g' {} \;
fi
done < <(env)

View File

@@ -24,4 +24,4 @@ case "X$MODCONFIG" in
esac
fi
exec ${SCRIPTS:-/}start-finalSetupPlugins $@
exec ${SCRIPTS:-/}start-finalSetupMounts $@

View File

@@ -1,80 +1,109 @@
#!/bin/bash
set -e
set -e -o pipefail
. ${SCRIPTS:-/}start-utils
if isDebugging; then
set -x
fi
# CURSE_URL_BASE used in manifest downloads below
CURSE_URL_BASE=${CURSE_URL_BASE:-https://minecraft.curseforge.com/projects}
# Remove old mods/plugins
if [ "$REMOVE_OLD_MODS" = "TRUE" ]; then
if [ "$TYPE" = "SPIGOT" ]; then
rm -rf /data/plugins/*
if isTrue ${REMOVE_OLD_MODS}; then
remove_mods_dest="/data/mods"
case ${TYPE} in
SPIGOT|BUKKIT|PAPER)
remove_mods_dest="/data/plugins"
;;
esac
# only try to remove existing mods dir
if [ -d "$remove_mods_dest" ]; then
log "Removing old mods in $remove_mods_dest..."
find $remove_mods_dest -mindepth 1 -maxdepth ${REMOVE_OLD_MODS_DEPTH:-16} -wholename "${REMOVE_OLD_MODS_INCLUDE:-*}" -not -wholename "${REMOVE_OLD_MODS_EXCLUDE}" -delete
else
rm -rf /data/mods/*
log "Directory $remove_mods_dest does not exist; removing nothing."
fi
fi
# If supplied with a URL for a modpack (simple zip of jars), download it and unpack
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)
if isURL "${MODPACK}"; then
if [[ "${MODPACK}" == *.zip ]]; then
downloadUrl="${MODPACK}"
else
downloadUrl=$(curl -Ls -o /dev/null -w %{effective_url} $MODPACK)
if ! [[ $downloadUrl == *.zip ]]; then
log "ERROR Invalid URL given for MODPACK: $downloadUrl resolved from $MODPACK"
log " Must be HTTP or HTTPS and a ZIP file"
exit 1
fi
fi
log "Downloading mod/plugin pack via HTTP"
log " from $EFFECTIVE_MODPACK_URL ..."
if ! curl -sSL -o /tmp/modpack.zip "$EFFECTIVE_MODPACK_URL"; then
log "ERROR: failed to download from $EFFECTIVE_MODPACK_URL"
log " from $downloadUrl ..."
if ! curl -sSL -o /tmp/modpack.zip "$downloadUrl"; then
log "ERROR: failed to download from $downloadUrl"
exit 2
fi
if [ "$TYPE" = "SPIGOT" ]; then
mkdir -p /data/plugins
if ! unzip -o -d /data/plugins /tmp/modpack.zip; then
log "ERROR: failed to unzip the modpack from $EFFECTIVE_MODPACK_URL"
log "ERROR: failed to unzip the modpack from $downloadUrl"
fi
else
mkdir -p /data/mods
if ! unzip -o -d /data/mods /tmp/modpack.zip; then
log "ERROR: failed to unzip the modpack from $EFFECTIVE_MODPACK_URL"
log "ERROR: failed to unzip the modpack from $downloadUrl"
fi
fi
rm -f /tmp/modpack.zip
;;
*)
log "Invalid URL given for modpack: Must be HTTP or HTTPS and a ZIP file"
;;
esac
else
log "ERROR Invalid URL given for MODPACK: $MODPACK"
exit 1
fi
fi
# If supplied with a URL for a plugin download it.
if [[ "$MODS" ]]; then
for i in ${MODS//,/ }
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)
log "Downloading mod/plugin via HTTP"
log " from $EFFECTIVE_MOD_URL ..."
if ! curl -sSL -o /tmp/${EFFECTIVE_MOD_URL##*/} $EFFECTIVE_MOD_URL; then
log "ERROR: failed to download from $EFFECTIVE_MOD_URL to /tmp/${EFFECTIVE_MOD_URL##*/}"
exit 2
fi
if [ "$TYPE" = "SPIGOT" ]; then
out_dir=/data/plugins
else
out_dir=/data/mods
fi
mkdir -p "$out_dir"
if [ "$TYPE" = "SPIGOT" ]; then
mkdir -p /data/plugins
mv /tmp/${EFFECTIVE_MOD_URL##*/} /data/plugins/${EFFECTIVE_MOD_URL##*/}
for i in ${MODS//,/ }
do
if isURL $i; then
log "Downloading mod/plugin $i ..."
if isValidFileURL jar "$i"; then
if ! curl -fsSL -o "${out_dir}/$(getFilenameFromUrl "${i}")" "${i}"; then
log "ERROR: failed to download from $i into $out_dir"
exit 2
fi
else
mkdir -p /data/mods
mv /tmp/${EFFECTIVE_MOD_URL##*/} /data/mods/${EFFECTIVE_MOD_URL##*/}
effective_url=$(resolveEffectiveUrl "$i")
if isValidFileURL jar "${effective_url}"; then
out_file=$(getFilenameFromUrl "${effective_url}")
if ! curl -fsSL -o "${out_dir}/$out_file" "${effective_url}"; then
log "ERROR: failed to download from $i into $out_dir"
exit 2
fi
else
log "ERROR: $effective_url resolved from $i is not a valid jar URL"
exit 2
fi
fi
rm -f /tmp/${EFFECTIVE_MOD_URL##*/}
;;
*)
log "Invalid URL given for modpack: Must be HTTP or HTTPS and a JAR file"
;;
esac
done
else
log "ERROR Invalid URL given in MODS: $i"
exit 2
fi
done
fi
if [[ "$MANIFEST" ]]; then
@@ -82,7 +111,7 @@ if [[ "$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)
EFFECTIVE_MANIFEST_URL=$(curl -Ls -o /dev/null -w %{effective_url} $MANIFEST)
curl -Ls -o $EFFECTIVE_MANIFEST_FILE "$EFFECTIVE_MANIFEST_URL"
else
log "MANIFEST='$MANIFEST' is not a valid manifest url or location"
@@ -103,7 +132,7 @@ case "X$EFFECTIVE_MANIFEST_FILE" in
do
if [ ! -f $MOD_DIR/${p}_${f}.jar ]
then
redirect_url="$(curl -Ls -o /dev/null -w %{url_effective} ${CURSE_URL_BASE}/${p})"
redirect_url="$(curl -Ls -o /dev/null -w %{effective_url} ${CURSE_URL_BASE}/${p})"
url="$redirect_url/download/${f}/file"
log Downloading curseforge mod $url
# Manifest usually doesn't have mod names. Using id should be fine, tho
@@ -122,17 +151,17 @@ 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}
log "Downloading generic pack ..."
curl -fsSL -o /tmp/generic_pack.zip "${GENERIC_PACK}"
GENERIC_PACK=/tmp/generic_pack.zip
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}
isDebugging && ls -l "${GENERIC_PACK}"
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
@@ -150,7 +179,7 @@ if [[ "${GENERIC_PACK}" ]]; then
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}
sha256sum "${GENERIC_PACK}" > ${sum_file}
fi
fi

38
start-finalSetupMounts Executable file
View File

@@ -0,0 +1,38 @@
#!/bin/bash
. ${SCRIPTS:-/}start-utils
: ${PLUGINS_SYNC_UPDATE:=true}
isDebugging && set -x
if [ -d /plugins ]; then
case ${TYPE} in
SPIGOT|BUKKIT|PAPER|MAGMA)
mkdir -p /data/plugins
log "Copying plugins over..."
if isTrue ${PLUGINS_SYNC_UPDATE}; then
updateArg="--update"
fi
# Copy plugins over using rsync to allow deeply nested updates of plugins
rsync -a --out-format="update:%f:Last Modified %M" --prune-empty-dirs $updateArg /plugins /data
;;
esac
fi
# If any modules have been provided, copy them over
if [ -d /mods ]; then
log "Copying any mods over..."
mkdir -p /data/mods
rsync -a --out-format="update:%f:Last Modified %M" "${rsyncArgs[@]}" --prune-empty-dirs --update /mods /data
fi
: ${COPY_CONFIG_DEST:="/data/config"}
if [ -d /config ]; then
log "Copying any configs from /config to $COPY_CONFIG_DEST"
mkdir -p $COPY_CONFIG_DEST
rsync -a --out-format="update:%f:Last Modified %M" "${rsyncArgs[@]}" --prune-empty-dirs --update /config/ $COPY_CONFIG_DEST
fi
exec ${SCRIPTS:-/}start-finalSetupServerProperties $@

View File

@@ -1,23 +0,0 @@
#!/bin/bash
. ${SCRIPTS:-/}start-utils
: ${PLUGINS_SYNC_UPDATE:=true}
isDebugging && set -x
if [ -d /plugins ]; then
case ${TYPE} in
SPIGOT|BUKKIT|PAPER)
mkdir -p /data/plugins
log "Copying plugins over..."
if isTrue ${PLUGINS_SYNC_UPDATE}; then
updateArg="--update"
fi
# Copy plugins over using rsync to allow deeply nested updates of plugins
rsync -a --out-format="update:%f:Last Modified %M" --prune-empty-dirs $updateArg /plugins /data
;;
esac
fi
exec ${SCRIPTS:-/}start-finalSetupServerProperties $@

View File

@@ -13,7 +13,7 @@ function setServerProp {
var=${var,,} ;;
esac
log "Setting ${prop} to '${var}' in ${SERVER_PROPERTIES}"
sed -i "/^${prop}\s*=/ c ${prop}=${var}" "$SERVER_PROPERTIES"
sed -i "/^${prop}\s*=/ c ${prop}=${var//\\/\\\\}" "$SERVER_PROPERTIES"
else
log "Skip setting ${prop}"
fi

View File

@@ -10,7 +10,7 @@ else
worldDest=/data/$LEVEL
fi
if [[ "$WORLD" ]] && isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ]; then
if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] ); then
if isURL $WORLD; then
curl -fsSL "$WORLD" -o /tmp/world.zip
zipSrc=/tmp/world.zip
@@ -25,7 +25,12 @@ if [[ "$WORLD" ]] && isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ]; the
mkdir -p /tmp/world-data
(cd /tmp/world-data && unzip -o -q "$zipSrc")
baseDirs=$(find /tmp/world-data -name "level.dat" -exec dirname "{}" \;)
if [ "$TYPE" = "SPIGOT" ]; then
baseDirs=$(find /tmp/world-data -name "level.dat" -not -path "*_nether*" -not -path "*_the_end*" -exec dirname "{}" \;)
else
baseDirs=$(find /tmp/world-data -name "level.dat" -exec dirname "{}" \;)
fi
count=$(echo "$baseDirs" | wc -l)
if [[ $count -gt 1 ]]; then
baseDir="$(echo "$baseDirs" | sed -n ${WORLD_INDEX:-1}p)"
@@ -38,6 +43,11 @@ if [[ "$WORLD" ]] && isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ]; the
exit 1
fi
rsync --remove-source-files --recursive --delete "$baseDir/" "$worldDest"
if [ "$TYPE" = "SPIGOT" ]; then
log "Copying end and nether ..."
[ -d "${baseDir}_nether" ] && rsync --remove-source-files --recursive --delete "${baseDir}_nether/" "${worldDest}_nether"
[ -d "${baseDir}_the_end" ] && rsync --remove-source-files --recursive --delete "${baseDir}_the_end/" "${worldDest}_the_end"
fi
else
log "Cloning world directory from $WORLD ..."
rsync --recursive --delete "${WORLD%/}"/ "$worldDest"

View File

@@ -3,28 +3,40 @@
. ${SCRIPTS:-/}start-utils
if [ -n "$OPS" ]; then
log "Setting/adding ops"
rm -rf /data/ops.txt.converted
log "Updating ops"
rm -f /data/ops.txt.converted
echo $OPS | awk -v RS=, '{print}' > /data/ops.txt
if isTrue "${OVERRIDE_OPS}"; then
log "Recreating ops.json file at server startup"
rm -f /data/ops.json
fi
fi
if [ -n "$WHITELIST" ]; then
log "Setting whitelist"
rm -rf /data/white-list.txt.converted
log "Updating whitelist"
rm -f /data/white-list.txt.converted
echo $WHITELIST | awk -v RS=, '{print}' > /data/white-list.txt
if isTrue "${OVERRIDE_WHITELIST}"; then
log "Recreating whitelist.json file at server startup"
rm -f /data/whitelist.json
fi
fi
if [ -n "$ICON" -a ! -e server-icon.png ]; then
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
log "Converting image to 64x64 PNG..."
convert /tmp/icon.img -resize 64x64! /data/server-icon.png
fi
if [ -n "$ICON" ]; then
if [ ! -e server-icon.png ] || [ "${OVERRIDE_ICON}" == "TRUE" ]; then
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
log "Converting image to 64x64 PNG..."
convert /tmp/icon.img -resize 64x64! /data/server-icon.png
fi
fi
fi
if ! isTrue ${SKIP_LOG4J_CONFIG}; then
@@ -49,23 +61,6 @@ for j in $JSON_FILES; do
fi
done
# If any modules have been provided, copy them over
if [ -d /mods ]; then
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
[ -d /data/config ] || mkdir /data/config
for c in /config/*
do
if [ -f "$c" ]; then
log Copying configuration $(basename "$c")
cp -rf "$c" /data/config
fi
done
EXTRA_ARGS=""
# Optional disable console
if versionLessThan 1.14 && [[ ${CONSOLE,,} = false ]]; then
@@ -158,49 +153,60 @@ if isTrue "${DEBUG_MEMORY}"; then
free -m
fi
mcServerRunnerArgs="--stop-duration 60s"
JVM_OPTS="-Xms${INIT_MEMORY} -Xmx${MAX_MEMORY} ${JVM_OPTS}"
function copyFilesForCurseForge() {
# copy player modification files unconditionally since their
# processing into json is additive anyway
[ -f /data/ops.txt ] && cp -f /data/ops.txt "${FTB_DIR}/"
[ -f /data/white-list.txt ] && cp -f /data/white-list.txt "${FTB_DIR}/"
if [ ! -e "${FTB_DIR}/server-icon.png" -a -e /data/server-icon.png ]; then
cp -f /data/server-icon.png "${FTB_DIR}/"
fi
cp -f /data/eula.txt "${FTB_DIR}/"
}
mcServerRunnerArgs="--stop-duration ${STOP_DURATION:-60}s"
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"
elif [[ ${TYPE} == "CURSEFORGE" && "${SERVER}" ]]; then
copyFilesForCurseForge
if [ ! -e "${FTB_DIR}/ops.json" -a -e /data/ops.txt ]; then
cp -f /data/ops.txt ${FTB_DIR}/
fi
cd "${FTB_DIR}"
log "Starting CurseForge server in ${FTB_DIR}..."
if isTrue ${DEBUG_EXEC}; then
set -x
fi
exec mc-server-runner ${bootstrapArgs} ${mcServerRunnerArgs} java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar $(basename "${SERVER}") "$@" $EXTRA_ARGS
elif [[ ${TYPE} == "CURSEFORGE" ]]; then
mcServerRunnerArgs="${mcServerRunnerArgs} --shell bash"
if [ ! -e "${FTB_DIR}/whitelist.json" -a -e /data/white-list.txt ]; then
cp -f /data/white-list.txt ${FTB_DIR}/
fi
copyFilesForCurseForge
if [ ! -e "${FTB_DIR}/server-icon.png" -a -e /data/server-icon.png ]; then
cp -f /data/server-icon.png ${FTB_DIR}/
fi
cp -f /data/eula.txt "${FTB_DIR}/"
cat > "${FTB_DIR}/settings-local.sh" <<EOF
cat > "${FTB_DIR}/settings-local.sh" <<EOF
export MIN_RAM="${INIT_MEMORY}"
export MAX_RAM="${MAX_MEMORY}"
export JAVA_PARAMETERS="${JVM_XX_OPTS} -Xms${INIT_MEMORY} ${JVM_OPTS} $expandedDOpts"
EOF
# patch CurseForge cfg file, if present
if [ -f "${FTB_DIR}/settings.cfg" ]; then
sed -i "s/MAX_RAM=[^;]*/MAX_RAM=${MAX_MEMORY}/" "${FTB_DIR}/settings.cfg"
fi
# patch CurseForge cfg file, if present
if [ -f "${FTB_DIR}/settings.cfg" ]; then
sed -i "s/MAX_RAM=[^;]*/MAX_RAM=${MAX_MEMORY}/" "${FTB_DIR}/settings.cfg"
fi
cd "${FTB_DIR}"
log "Running FTB ${FTB_SERVER_START} in ${FTB_DIR} ..."
if isTrue ${DEBUG_EXEC}; then
set -x
fi
exec mc-server-runner ${mcServerRunnerArgs} "${FTB_SERVER_START}"
cd "${FTB_DIR}"
log "Running FTB ${FTB_SERVER_START} in ${FTB_DIR} ..."
if isTrue ${DEBUG_EXEC}; then
set -x
fi
exec mc-server-runner ${mcServerRunnerArgs} "${FTB_SERVER_START}"
else
# If we have a bootstrap.txt file... feed that in to the server stdin
if [ -f /data/bootstrap.txt ]; then
@@ -208,7 +214,6 @@ else
fi
log "Starting the Minecraft server..."
JVM_OPTS="-Xms${INIT_MEMORY} -Xmx${MAX_MEMORY} ${JVM_OPTS}"
if isTrue ${DEBUG_EXEC}; then
set -x
fi

View File

@@ -1,6 +1,14 @@
#!/bin/bash
function isURL {
function join_by() {
local d=$1
shift
echo -n "$1"
shift
printf "%s" "${@/#/$d}"
}
function isURL() {
local value=$1
if [[ ${value:0:8} == "https://" || ${value:0:7} == "http://" ]]; then
@@ -10,90 +18,114 @@ function isURL {
fi
}
function isTrue {
function isValidFileURL() {
suffix=${1:?Missing required suffix arg}
url=${2:?Missing required url arg}
[[ "$url" == http*://*.${suffix} || "$url" == http*://*.${suffix}\?* ]]
}
function resolveEffectiveUrl() {
url="${1:?Missing required url argument}"
if ! curl -Ls -o /dev/null -w %{url_effective} "$url"; then
log "ERROR failed to resolve effective URL from $url"
exit 2
fi
}
function getFilenameFromUrl() {
url="${1:?Missing required url argument}"
strippedOfQuery="${url%\?*}"
basename "$strippedOfQuery"
}
function isTrue() {
local value=${1,,}
result=
case ${value} in
true|on)
result=0
;;
*)
result=1
;;
true | on)
result=0
;;
*)
result=1
;;
esac
return ${result}
}
function isDebugging {
if [[ -v DEBUG ]] && [[ ${DEBUG^^} = TRUE ]]; then
function isDebugging() {
if [[ -v DEBUG ]] && [[ ${DEBUG^^} == TRUE ]]; then
return 0
else
return 1
fi
}
function debug {
function debug() {
if isDebugging; then
log "DEBUG: $*"
fi
}
function logn {
function logn() {
echo -n "[init] $*"
}
function log {
function log() {
echo "[init] $*"
}
function logAutopause {
function logAutopause() {
echo "[Autopause loop] $*"
}
function logAutopauseAction {
function logAutopauseAction() {
echo "[$(date -Iseconds)] [Autopause] $*"
}
function normalizeMemSize {
function normalizeMemSize() {
local scale=1
case ${1,,} in
*k)
scale=1024;;
*m)
scale=1048576;;
*g)
scale=1073741824;;
*k)
scale=1024
;;
*m)
scale=1048576
;;
*g)
scale=1073741824
;;
esac
val=${1:0: -1}
echo $(( val * scale ))
val=${1:0:-1}
echo $((val * scale))
}
function versionLessThan {
function versionLessThan() {
local activeParts
IFS=. read -ra activeParts <<< "${VANILLA_VERSION}"
IFS=. read -ra activeParts <<<"${VANILLA_VERSION}"
local givenParts
IFS=. read -ra givenParts <<< "$1"
IFS=. read -ra givenParts <<<"$1"
if (( ${#activeParts[@]} < 2 )); then
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
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
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
@@ -106,4 +138,18 @@ requireVar() {
log "ERROR: $1 is required to be set"
exit 1
fi
if [ -z "${!1}" ]; then
log "ERROR: $1 is required to be set"
exit 1
fi
}
function writeEula() {
if ! echo "# Generated via Docker
# $(date)
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
}

View File

@@ -0,0 +1,17 @@
version: "3.8"
services:
sut:
depends_on:
- mc
image: itzg/mc-monitor:0.6.0
command: status --host mc --retry-interval 1s --retry-limit 120
mc:
restart: "no"
build:
context: ..
cache_from:
- itzg/minecraft-server:latest
environment:
EULA: "TRUE"

17
tests/test.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/bash
cd $(dirname $0)
failed=false
args="-f docker-compose.test.yml"
docker-compose $args run sut || failed=true
echo "
Result: failed=$failed"
$failed && docker-compose $args logs mc
docker-compose $args down -v
if $failed; then
exit 1
fi