diff --git a/.github/workflows/build-multiarch.yml b/.github/workflows/build-multiarch.yml index 971b5e99..af52b673 100644 --- a/.github/workflows/build-multiarch.yml +++ b/.github/workflows/build-multiarch.yml @@ -8,6 +8,7 @@ on: - java8-openj9 - java11* - java16* + - java17* - test/* tags: - "[0-9]+.[0-9]+.[0-9]+" diff --git a/README.md b/README.md index c24b8353..00a008c3 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ By default, the container will download the latest version of the "vanilla" [Min * [Running a SpongeVanilla server](#running-a-spongevanilla-server) * [Running a Fabric Server](#running-a-fabric-server) * [Running a Limbo server](#running-a-limbo-server) + * [Running a Crucible server](#running-a-crucible-server) * [Running a server with a Feed the Beast modpack](#running-a-server-with-a-feed-the-beast-modpack) * [Environment Variables:](#environment-variables) * [Upgrading](#upgrading) @@ -64,6 +65,7 @@ By default, the container will download the latest version of the "vanilla" [Min * [Optional plugins, mods, and config attach points](#optional-plugins-mods-and-config-attach-points) * [Auto-downloading SpigotMC/Bukkit/PaperMC plugins](#auto-downloading-spigotmcbukkitpapermc-plugins) * [Downloadable mod/plugin pack for Forge, Bukkit, and Spigot Servers](#downloadable-modplugin-pack-for-forge-bukkit-and-spigot-servers) + * [Generic pack file](#generic-pack-file) * [Mod/Plugin URL Listing File](#modplugin-url-listing-file) * [Remove old mods/plugins](#remove-old-modsplugins) * [Working with world data](#working-with-world-data) @@ -130,7 +132,7 @@ By default, the container will download the latest version of the "vanilla" [Min * [Enabling Autopause](#enabling-autopause) * [Running on RaspberryPi](#running-on-raspberrypi) - + @@ -277,6 +279,7 @@ To use a different version of Java, please use a docker tag to run your Minecraf | java11-openj9 | 11 | Debian | OpenJ9 | amd64 | | java16 | 16 | Debian | Hotspot | amd64,arm64,armv7 | | java16-openj9 | 16 | Debian | OpenJ9 | amd64 | +| java17 | 17 | Ubuntu | Hotspot | amd64 | | multiarch-latest | 15+ | Debian | Hotspot | amd64,arm64,armv7 | For example, to use Java version 16 on any supported architecture: @@ -712,6 +715,10 @@ You may also download or copy over individual mods using the `MODS` environment docker run -d -e MODS=https://www.example.com/mods/mod1.jar,/plugins/common,/plugins/special/mod2.jar ... +### Generic pack file + +To install all of the server content (jars, mods, plugins, configs, etc) from a zip file, such as a CurseForge modpack that is missing a server start script, then set `GENERIC_PACK` to the container path of the zip file. That, combined with `TYPE`, allows for custom content along with container managed server download and install. + ### Mod/Plugin URL Listing File As an alternative to `MODS`, the variable `MODS_FILE` can be set with the path to a text file listing a mod/plugin URL on each line. For example, the following diff --git a/docker-versions-create.sh b/docker-versions-create.sh index 6f8b7d0c..847efe8d 100755 --- a/docker-versions-create.sh +++ b/docker-versions-create.sh @@ -9,6 +9,7 @@ branches_list=( 'java11-openj9' 'java16' 'java16-openj9' + 'java17' 'multiarch-latest' ) diff --git a/examples/docker-compose-curseforge.yml b/examples/docker-compose-curseforge.yml index a3b885d5..b0b54986 100644 --- a/examples/docker-compose-curseforge.yml +++ b/examples/docker-compose-curseforge.yml @@ -2,12 +2,17 @@ version: '3.8' services: mc: - image: itzg/minecraft-server:java8 + image: itzg/minecraft-server:${IMAGE_TAG:-java8} volumes: - ./modpacks:/modpacks:ro + - data:/data environment: EULA: "true" TYPE: CURSEFORGE - CF_SERVER_MOD: /modpacks/SkyFactory_4_Server_4.1.0.zip + CF_SERVER_MOD: https://media.forgecdn.net/files/3012/800/SkyFactory-4_Server_4.2.2.zip +# CF_SERVER_MOD: /modpacks/${MODPACK:-SkyFactory_4_Server_4.1.0.zip} ports: - - 25565:25565 + - "25565:25565" + +volumes: + data: {} \ No newline at end of file diff --git a/examples/docker-compose-generic-pack.yml b/examples/docker-compose-generic-pack.yml new file mode 100644 index 00000000..314a8083 --- /dev/null +++ b/examples/docker-compose-generic-pack.yml @@ -0,0 +1,20 @@ +version: '3.8' + +services: + mc: + image: itzg/minecraft-server:${IMAGE_TAG:-latest} + volumes: + - data:/data + - ./modpacks:/modpacks:ro + environment: + EULA: "true" + TYPE: FORGE + DEBUG: "${DEBUG:-false}" + VERSION: ${VERSION:-1.17.1} + FORGEVERSION: ${FORGEVERSION:-37.0.90} + GENERIC_PACK: /modpacks/${MODPACK:-Server-Files-0.0.21.zip} + ports: + - "25565:25565" + +volumes: + data: {} \ No newline at end of file diff --git a/start-deployCF b/start-deployCF index d821636a..cdbafb30 100755 --- a/start-deployCF +++ b/start-deployCF @@ -2,7 +2,8 @@ set -e -. ${SCRIPTS:-/}start-utils +# shellcheck source=start-utils +. "${SCRIPTS:-/}start-utils" loadForgeVars() { cfgFile=${1?} @@ -23,7 +24,7 @@ loadForgeVars() { isDebugging && set -x -: ${FTB_BASE_DIR:=${CF_BASE_DIR:-/data/FeedTheBeast}} +: "${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 @@ -34,7 +35,7 @@ FTB_SERVER_MOD=${FTB_SERVER_MOD:-$CF_SERVER_MOD} log "Looking for Feed-The-Beast / CurseForge server modpack." requireVar FTB_SERVER_MOD -if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then +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 @@ -46,9 +47,9 @@ if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then if [ "$(cat $installMarker)" != "${FTB_SERVER_MOD}" ]; then log "Upgrading modpack" - serverJar=$(find ${FTB_BASE_DIR} -not -name "forge*installer.jar" -name "forge*.jar") + 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} + rm -rf "$(dirname "${serverJar}")"/{mods,*.jar,libraries,resources,scripts,config} fi else needsInstall=false @@ -57,10 +58,10 @@ if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then 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 ""}' + mkdir -p "${FTB_BASE_DIR}" + unzip -o "${FTB_SERVER_MOD}" -d "${FTB_BASE_DIR}" | awk '{printf "."} END {print ""}' - serverJar=$(find ${FTB_BASE_DIR} -type f \( -path "*/libraries/*" -o -path "*/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -print) + serverJar=$(find "${FTB_BASE_DIR}" -type f \( -path "*/libraries/*" -o -path "*/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -print) if [[ -z "$serverJar" ]]; then if [ -f "${FTB_BASE_DIR}/settings.cfg" ]; then @@ -86,22 +87,24 @@ if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then log "Installing forge server" dirOfInstaller=$(dirname "${forgeInstallerJar}") - (cd "${dirOfInstaller}"; java -jar $(basename "${forgeInstallerJar}") --installServer) + (cd "${dirOfInstaller}"; java -jar "$(basename "${forgeInstallerJar}")" --installServer) fi echo "${FTB_SERVER_MOD}" > $installMarker fi - export SERVER=$(find ${FTB_BASE_DIR} -type f \( -path "/libraries/*" -o -path "/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -maxdepth 2 -print) + SERVER=$(find "${FTB_BASE_DIR}" -maxdepth 2 -type f \( -path "/libraries/*" -o -path "/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -print) if [[ -z "${SERVER}" || ! -f "${SERVER}" ]]; then log "ERROR unable to locate installed forge server jar" - isDebugging && find ${FTB_BASE_DIR} -name "forge*.jar" + isDebugging && find "${FTB_BASE_DIR}" -name "forge*.jar" exit 2 fi + export SERVER - export FTB_DIR=$(dirname "${SERVER}") + FTB_DIR=$(dirname "${SERVER}") + export FTB_DIR - exec ${SCRIPTS:-/}start-setupWorld $@ + exec "${SCRIPTS:-/}start-setupWorld" "$@" fi entryScriptExpr=" @@ -116,8 +119,8 @@ entryScriptExpr=" " if [[ -d ${FTB_BASE_DIR} ]]; then - startScriptCount=$(find ${FTB_BASE_DIR} $entryScriptExpr |wc -l) - if [[ $startScriptCount > 1 ]]; then + startScriptCount=$(find "${FTB_BASE_DIR}" $entryScriptExpr |wc -l) + if (( startScriptCount > 1 )); then log "Conflicting FTB/CurseForge packages have been installed. Please cleanup ${FTB_BASE_DIR}" exit 2 fi @@ -131,22 +134,11 @@ fi if [[ $startScriptCount = 0 ]]; then srv_modpack=${FTB_SERVER_MOD} if isURL "${srv_modpack}"; then - case $srv_modpack in - https://www.feed-the-beast.com/*/download|https://www.curseforge.com/minecraft/modpacks/*/download/*/file) - ;; - https://www.curseforge.com/minecraft/modpacks/*/download/*) - srv_modpack=${srv_modpack}/file;; - https://www.feed-the-beast.com/*) - srv_modpack=${srv_modpack}/download;; - esac - file=$(basename $(dirname $srv_modpack)) - downloaded=/data/${file}.zip - if [ ! -e $downloaded ]; then - log "Downloading FTB modpack... - $srv_modpack -> $downloaded" - curl -sSL -o $downloaded $srv_modpack - fi - srv_modpack=$downloaded + log "Downloading modpack from ${srv_modpack}..." + if ! srv_modpack=$(get -o /data --output-filename --skip-existing "${srv_modpack}"); then + log "ERROR: failed to download modpack" + exit 1 + fi fi if [[ "${srv_modpack:0:5}" == "data/" ]]; then # Prepend with "/" @@ -167,8 +159,8 @@ if [[ $startScriptCount = 0 ]]; then fi log "Unpacking FTB server modpack ${srv_modpack} ..." - mkdir -p ${FTB_BASE_DIR} - unzip -o "${srv_modpack}" -d ${FTB_BASE_DIR} | awk '{printf "."} END {print ""}' + mkdir -p "${FTB_BASE_DIR}" + unzip -o "${srv_modpack}" -d "${FTB_BASE_DIR}" | awk '{printf "."} END {print ""}' installScript=$(find "${FTB_BASE_DIR}" -maxdepth 2 -type f -name install.sh) if [[ "$installScript" ]]; then @@ -181,13 +173,14 @@ if [[ $startScriptCount = 0 ]]; then fi fi -if [[ $(find ${FTB_BASE_DIR} $entryScriptExpr | wc -l) = 0 ]]; then +if [[ $(find "${FTB_BASE_DIR}" $entryScriptExpr | wc -l) = 0 ]]; then # Allow up to 2 levels since some modpacks have a top-level directory named # for the modpack - forgeJar=$(find ${FTB_BASE_DIR} -type f \( -path "/libraries/*" -o -path "/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -maxdepth 2 -print) + forgeJar=$(find "${FTB_BASE_DIR}" -maxdepth 2 -type f \( -path "/libraries/*" -o -path "/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -print) if [[ "$forgeJar" ]]; then - export FTB_BASE_DIR=$(dirname "${forgeJar}") + FTB_BASE_DIR=$(dirname "${forgeJar}") + export FTB_BASE_DIR log "No entry script found, so building one for ${forgeJar}" cat > "${FTB_BASE_DIR}/ServerStart.sh" < 1 ]]; then - log "Ambigous startup scripts in FTB modpack!" - log "found:" - find ${FTB_BASE_DIR} $entryScriptExpr +elif (( scriptCount > 1 )); then + log "Ambiguous startup scripts in FTB modpack! Found:" + find "${FTB_BASE_DIR}" $entryScriptExpr exit 2 fi -export FTB_SERVER_START=$(find "${FTB_BASE_DIR}" $entryScriptExpr) +FTB_SERVER_START=$(find "${FTB_BASE_DIR}" $entryScriptExpr) +export FTB_SERVER_START -export FTB_DIR=$(dirname "${FTB_SERVER_START}") +FTB_DIR=$(dirname "${FTB_SERVER_START}") +export FTB_DIR chmod a+x "${FTB_SERVER_START}" grep fml.queryResult=confirm "${FTB_SERVER_START}" > /dev/null || \ sed -i 's/-jar/-Dfml.queryResult=confirm -jar/' "${FTB_SERVER_START}" sed -i 's/.*read.*Restart now/#\0/' "${FTB_SERVER_START}" legacyJavaFixerPath="${FTB_DIR}/mods/legacyjavafixer.jar" -if isTrue ${FTB_LEGACYJAVAFIXER} && [ ! -e "${legacyJavaFixerPath}" ]; then +if isTrue "${FTB_LEGACYJAVAFIXER}" && [ ! -e "${legacyJavaFixerPath}" ]; then log "Installing legacy java fixer to ${legacyJavaFixerPath}" - curl -sSL -o "${legacyJavaFixerPath}" ${legacyJavaFixerUrl} + if ! get -o "${legacyJavaFixerPath}" ${legacyJavaFixerUrl}; then + log "ERROR failed to download legacy java fixer from ${legacyJavaFixerUrl}" + exit 1 + fi fi if [ -e "${FTB_DIR}/FTBInstall.sh" ]; then @@ -236,4 +233,4 @@ elif [ -e "${FTB_DIR}/Install.sh" ]; then popd fi -exec ${SCRIPTS:-/}start-setupWorld $@ +exec "${SCRIPTS:-/}start-setupWorld" "$@" diff --git a/start-deployForge b/start-deployForge index 394c6050..088f4a6e 100755 --- a/start-deployForge +++ b/start-deployForge @@ -53,13 +53,19 @@ install() { # NOTE $shortForgeVersion will be empty if installer location was given to us log "Finding installed server jar..." unset -v latest - for file in *forge*.jar; do - if ! [[ $file =~ installer ]]; then - if [[ -z $latest ]] || [[ $file -nt $latest ]]; then - latest=$file + # 1.17+ ? + if [ -f /data/run.sh ]; then + latest=/data/run.sh + # else pre 1.17 + else + for file in *forge*.jar; do + if ! [[ $file =~ installer ]]; then + if [[ -z $latest ]] || [[ $file -nt $latest ]]; then + latest=$file + fi fi - fi - done + done + fi if [[ -z $latest ]]; then log "Unable to derive server jar for Forge" exit 2 @@ -67,6 +73,7 @@ install() { export SERVER=$latest log "Using server $SERVER" + debug "Writing install marker at $installMarker" echo "$SERVER" > "$installMarker" } @@ -134,10 +141,10 @@ if [ ! -e "$installMarker" ]; then else SERVER=$(cat "$installMarker") export SERVER - if [ ! -e "$SERVER" ] && versionLessThan 1.17; then + if [ ! -e "$SERVER" ]; then rm "$installMarker" install fi fi -exec "${SCRIPTS:-$(dirname "$0")}/start-setupWorld" "$@" +exec "${SCRIPTS:-/}start-setupWorld" "$@" diff --git a/start-setupModpack b/start-setupModpack index 474dc7c7..3d4f13be 100755 --- a/start-setupModpack +++ b/start-setupModpack @@ -169,29 +169,38 @@ if [[ "${GENERIC_PACK}" ]]; then fi sum_file=/data/.generic_pack.sum - if ! sha256sum -c ${sum_file} -s 2> /dev/null; then + isDebugging && [ -f "$sum_file}" ] && cat "$sum_file" + if ! sha256sum -c "${sum_file}" --status 2> /dev/null; then base_dir=/tmp/generic_pack_base mkdir -p ${base_dir} isDebugging && ls -l "${GENERIC_PACK}" unzip -q -d ${base_dir} "${GENERIC_PACK}" + + # recalculate the actual base directory of content + base_dir=$(find "$base_dir" -type d \( -name mods -o -name plugins -o -name config \) -printf '%h' -quit) + if [[ ! $base_dir ]]; then + log "Unable to find content base of generic pack ${GENERIC_PACK}" + exit 1 + fi + if [ -f /data/manifest.txt ]; then log "Manifest exists from older generic pack, cleaning up ..." - while read f; do + while read -r f; do rm -rf "/data/${f}" done < /data/manifest.txt - find /data/* -type d -exec rmdir --ignore-fail-on-non-empty {} + + # prune empty dirs + find /data -mindepth 1 -depth -type d -empty -delete rm -f /data/manifest.txt fi + log "Writing generic pack manifest ... " - find ${base_dir} -type f -print0 | xargs -0 -I {} echo "{}" | sed "s#${base_dir}/##" > /data/manifest.txt + find "${base_dir}" -type f -printf "%P\n" > /data/manifest.txt + log "Applying generic pack ..." - IFS=' -' - set -f - for d in $(find ${base_dir} -type d); do mkdir -p "$(sed "s#${base_dir}#/data#" <<< $d)"; done - for f in $(find ${base_dir} -type f); do cp -f "$f" "$(sed "s#${base_dir}#/data#" <<< $f)"; done - rm -rf ${base_dir} - sha256sum "${GENERIC_PACK}" > ${sum_file} + cp -R -f "${base_dir}"/* /data + rm -rf /tmp/generic_pack_base + sha256sum "${GENERIC_PACK}" > "${sum_file}" + isDebugging && cat "$sum_file" fi fi