Compare commits

..

16 Commits

Author SHA1 Message Date
Geoff Bourne
81e1cd8cfd Auto-merging via docker-versions-create 2020-07-26 08:30:21 -05:00
Geoff Bourne
8387e9bd26 Auto-merging via docker-versions-create 2020-07-18 18:40:48 -05:00
Geoff Bourne
4afdb289c0 Auto-merging via docker-versions-create 2020-07-11 13:13:48 -05:00
Geoff Bourne
fe637353d8 Auto-merging via docker-versions-create 2020-07-10 17:11:51 -05:00
Geoff Bourne
9160501f0a Auto-merging via docker-versions-create 2020-07-04 14:58:15 -05:00
Geoff Bourne
6eba5062ec Auto-merging via docker-versions-create 2020-06-20 15:45:09 -05:00
Geoff Bourne
fc96723db1 Auto-merging via docker-versions-create 2020-06-19 13:27:05 -05:00
Geoff Bourne
8d3e461b4c Auto-merging via docker-versions-create 2020-05-20 08:15:12 -05:00
Geoff Bourne
fd73417411 Auto-merging via docker-versions-create 2020-05-02 09:34:30 -05:00
Geoff Bourne
1207b9a685 Auto-merging via docker-versions-create 2020-04-25 12:11:09 -05:00
Geoff Bourne
e6259bfd9d Auto-merging via docker-versions-create 2020-04-17 21:29:12 -05:00
Geoff Bourne
b5e7b952e4 Auto-merging via docker-versions-create 2020-04-11 08:51:52 -05:00
Geoff Bourne
ac5b960182 Auto-merging via docker-versions-create 2020-04-10 11:08:59 -05:00
Geoff Bourne
3299dec733 Auto-merging via docker-versions-create 2020-04-03 13:31:44 -05:00
Geoff Bourne
578f06087f Changed JVM_XX_OPTS to use default GC 2020-03-13 10:55:19 -05:00
Geoff Bourne
fb364e8301 Prepared adopt13 branch 2020-03-02 21:08:22 -06:00
62 changed files with 868 additions and 1961 deletions

View File

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

View File

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

View File

@@ -1,7 +0,0 @@
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@@ -1,84 +0,0 @@
name: Build and publish multiarch
on:
push:
branches:
- master
- "*-multiarch"
- "multiarch*"
- java8-openj9
- java11*
- java15*
- java16*
- test/multiarch/*
tags:
- "[0-9]+.[0-9]+.[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+-multiarch*"
- "[0-9]+.[0-9]+.[0-9]+-*multiarch"
- "[0-9]+.[0-9]+.[0-9]+-java8-openj9"
- "[0-9]+.[0-9]+.[0-9]+-java11*"
- "[0-9]+.[0-9]+.[0-9]+-java15"
- "[0-9]+.[0-9]+.[0-9]+-java16*"
paths-ignore:
- "*.md"
- "docs/**"
- "examples/**"
jobs:
docker-buildx:
runs-on: ubuntu-20.04
env:
CACHE_NAME: java15
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
- name: Docker meta
id: meta
uses: docker/metadata-action@v3
with:
images: |
itzg/minecraft-server
tags: |
type=ref,event=branch
type=ref,event=tag
type=edge,branch=master
flavor: |
latest=false
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Cache Docker layers
uses: actions/cache@v2.1.5
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ env.CACHE_NAME }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-${{ env.CACHE_NAME }}-
${{ runner.os }}-buildx-
- name: Set up QEMU
uses: docker/setup-qemu-action@v1.1.0
- 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.4.0
with:
context: .
platforms: linux/amd64,linux/arm/v7,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
# ensure latest base image is used
pull: true
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
labels: ${{ steps.meta.outputs.labels }}
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}

View File

@@ -1,20 +0,0 @@
name: Generate README table of contents
on:
push:
branches:
- master
paths:
- README.md
jobs:
generate:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v2.3.4
- run: |
curl https://raw.githubusercontent.com/ekalinin/github-markdown-toc/master/gh-md-toc -o gh-md-toc
chmod a+x gh-md-toc
./gh-md-toc --insert --no-backup README.md
- uses: stefanzweifel/git-auto-commit-action@v4.11.0
with:
commit_message: "docs: Auto update markdown TOC"

View File

@@ -3,24 +3,24 @@ name: Build and Publish
on: on:
push: push:
branches: branches:
- java8 - master
- openj9 - openj9
- openj9-11 - openj9-nightly
- adopt11 - adopt11
- test/* - adopt13
tags: tags:
- "[0-9]+.[0-9]+.[0-9]+-java8" - "[0-9]+.[0-9]+.[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+-openj9" - "[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]+-openj9-nightly"
- "[0-9]+.[0-9]+.[0-9]+-adopt11" - "[0-9]+.[0-9]+.[0-9]+-adopt11"
- "[0-9]+.[0-9]+.[0-9]+-adopt13"
jobs: jobs:
test: test:
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2.3.4 - uses: actions/checkout@v2
- name: Run tests - name: Run tests
run: | run: |
@@ -28,70 +28,20 @@ jobs:
build: build:
needs: needs:
- test - test
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
env:
CACHE_NAME: java15
steps: steps:
- uses: actions/checkout@v2.3.4 - uses: actions/checkout@v2
- name: Prepare - name: Build and push Docker images
id: prep uses: docker/build-push-action@v1.1.0
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.1.5
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ env.CACHE_NAME }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-${{ env.CACHE_NAME }}-
${{ runner.os }}-buildx-
- name: Login to DockerHub
uses: docker/login-action@v1
with: with:
repository: itzg/minecraft-server
username: ${{ secrets.DOCKER_USER }} username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
tag_with_ref: true
- name: Build and push tag_with_sha: false
id: docker_build cache_froms: itzg/minecraft-server:latest
uses: docker/build-push-action@v2.4.0 add_git_labels: true
with: labels: org.opencontainers.image.url=https://github.com/itzg/docker-minecraft-server,org.opencontainers.image.documentation=https://github.com/itzg/docker-minecraft-server
context: .
file: ./Dockerfile
# ensure latest base image is used
pull: true
# publish
push: true 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

@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2.3.4 - uses: actions/checkout@v2
- name: Run tests - name: Run tests
run: | run: |

3
.gitignore vendored
View File

@@ -1,4 +1,3 @@
/data/ /data/
/.idea/ /.idea/
*.iml *.iml
/gh-md-toc

View File

@@ -1,11 +0,0 @@
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,32 @@
FROM adoptopenjdk:15-jre FROM adoptopenjdk/openjdk13:alpine-jre
LABEL org.opencontainers.image.authors="Geoff Bourne <itzgeoff@gmail.com>" LABEL org.opencontainers.image.authors="Geoff Bourne <itzgeoff@gmail.com>"
RUN apt-get update \ # upgrade all packages since alpine jre8 base image tops out at 8u212
&& DEBIAN_FRONTEND=noninteractive \ RUN apk -U --no-cache upgrade
apt-get install -y \
imagemagick \
gosu \
sudo \
net-tools \
curl wget \
git \
jq \
dos2unix \
mysql-client \
tzdata \
rsync \
nano \
unzip \
knockd \
ttf-dejavu \
&& apt-get clean
RUN addgroup --gid 1000 minecraft \ RUN apk add --no-cache -U \
&& adduser --system --shell /bin/false --uid 1000 --ingroup minecraft --home /data minecraft openssl \
imagemagick \
lsof \
su-exec \
shadow \
bash \
curl iputils wget \
git \
jq \
mysql-client \
tzdata \
rsync \
nano \
sudo \
knock \
ttf-dejavu
RUN addgroup -g 1000 minecraft \
&& adduser -Ss /bin/false -u 1000 -G minecraft -h /home/minecraft minecraft \
&& mkdir -m 777 /data \
&& chown minecraft:minecraft /data /home/minecraft
COPY files/sudoers* /etc/sudoers.d COPY files/sudoers* /etc/sudoers.d
@@ -31,9 +34,9 @@ EXPOSE 25565 25575
# hook into docker BuildKit --platform support # hook into docker BuildKit --platform support
# see https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope # see https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
ARG TARGETOS ARG TARGETOS=linux
ARG TARGETARCH ARG TARGETARCH=amd64
ARG TARGETVARIANT ARG TARGETVARIANT=""
ARG EASY_ADD_VER=0.7.1 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 ADD https://github.com/itzg/easy-add/releases/download/${EASY_ADD_VER}/easy-add_${TARGETOS}_${TARGETARCH}${TARGETVARIANT} /usr/bin/easy-add
@@ -48,11 +51,11 @@ 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 --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} \ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=0.7.1 --var app=mc-monitor --file {{.app}} \ --var version=0.1.7 --var app=mc-monitor --file {{.app}} \
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz --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} \ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=1.5.0 --var app=mc-server-runner --file {{.app}} \ --var version=1.4.3 --var app=mc-server-runner --file {{.app}} \
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz --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} \ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
@@ -66,15 +69,12 @@ COPY server.properties /tmp/server.properties
COPY log4j2.xml /tmp/log4j2.xml COPY log4j2.xml /tmp/log4j2.xml
WORKDIR /data WORKDIR /data
STOPSIGNAL SIGTERM
ENV UID=1000 GID=1000 \ ENV UID=1000 GID=1000 \
MEMORY="1G" \ MEMORY="1G" \
TYPE=VANILLA VERSION=LATEST \ TYPE=VANILLA VERSION=LATEST FORGEVERSION=RECOMMENDED SPONGEBRANCH=STABLE SPONGEVERSION= FABRICVERSION=LATEST LEVEL=world \
ENABLE_RCON=true RCON_PORT=25575 RCON_PASSWORD=minecraft \ PVP=true DIFFICULTY=easy ENABLE_RCON=true RCON_PORT=25575 RCON_PASSWORD=minecraft \
SERVER_PORT=25565 ONLINE_MODE=TRUE SERVER_NAME="Dedicated Server" \ 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 \ ENABLE_AUTOPAUSE=false AUTOPAUSE_TIMEOUT_EST=3600 AUTOPAUSE_TIMEOUT_KN=120 AUTOPAUSE_TIMEOUT_INIT=600 AUTOPAUSE_PERIOD=10
AUTOPAUSE_PERIOD=10 AUTOPAUSE_KNOCK_INTERFACE=eth0
COPY start* / COPY start* /
COPY health.sh / COPY health.sh /
@@ -84,6 +84,5 @@ RUN dos2unix /start* && chmod +x /start*
RUN dos2unix /health.sh && chmod +x /health.sh RUN dos2unix /health.sh && chmod +x /health.sh
RUN dos2unix /autopause/* && chmod +x /autopause/*.sh RUN dos2unix /autopause/* && chmod +x /autopause/*.sh
ENTRYPOINT [ "/start" ] ENTRYPOINT [ "/start" ]
HEALTHCHECK --start-period=1m CMD /health.sh HEALTHCHECK --start-period=1m CMD /health.sh

1111
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,7 @@
#!/bin/bash #!/bin/bash
#set -x #set -x
# Use this variable to indicate a list of branches that docker hub is watching # Use this variable to indicate a list of branches that docker hub is watching
branches_list=( branches_list=('openj9' 'openj9-nightly' 'adopt11' 'adopt13' 'multiarch')
'java8'
'java8-multiarch'
'java8-openj9'
'java11'
'java11-openj9'
'java15'
'java16'
'java16-openj9'
'multiarch-latest'
)
function TrapExit { function TrapExit {
echo "Checking out back in master" echo "Checking out back in master"

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

View File

@@ -1,4 +1,4 @@
version: '3.8' version: '3'
services: services:
minecraft: minecraft:

View File

@@ -1,8 +1,8 @@
version: '3.8' version: '3.2'
services: services:
mc: mc:
image: itzg/minecraft-server:java8 image: itzg/minecraft-server
volumes: volumes:
- ./modpacks:/modpacks:ro - ./modpacks:/modpacks:ro
environment: environment:

View File

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

View File

@@ -1,8 +1,8 @@
version: "3.8" version: "3.7"
services: services:
mc: mc:
image: itzg/minecraft-server:java8 image: itzg/minecraft-server
ports: ports:
# expose the Minecraft server port outside of container # expose the Minecraft server port outside of container
- 25565:25565 - 25565:25565

View File

@@ -1,9 +1,9 @@
version: "3.8" version: "3.7"
services: services:
mc: mc:
# FTBA support is only available in non-Alpine images # FTBA support is only available in multiarch image tag
image: itzg/minecraft-server:java8-multiarch image: itzg/minecraft-server:multiarch
ports: ports:
# expose the Minecraft server port outside of container # expose the Minecraft server port outside of container
- 25565:25565 - 25565:25565

View File

@@ -1,4 +1,4 @@
version: '3.8' version: '3.7'
services: services:
mc: mc:

View File

@@ -1,4 +1,4 @@
version: '3.8' version: '3'
services: services:
mc: mc:

View File

@@ -1,12 +0,0 @@
version: "3.8"
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,11 +1,11 @@
version: '3.8' version: '3'
# Forge with Sponge API support. THIS REQUIRES DOWNLOADING SPONGEFORGE. # Forge with Sponge API support. THIS REQUIRES DOWNLOADING SPONGEFORGE.
# Place the SpongeForge jar file in /data/mods. Other Forge mods go here as well. # Place the SpongeForge jar file in /data/mods. Other Forge mods go here as well.
# Place Sponge mods in /data/mods/plugins. Yes, this is a directory inside the Forge mod directory. Do NOT use /data/plugins. # Place Sponge mods in /data/mods/plugins. Yes, this is a directory inside the Forge mod directory. Do NOT use /data/plugins.
services: services:
minecraft: minecraft:
image: itzg/minecraft-server:java8 image: itzg/minecraft-server
ports: ports:
- "25565:25565" - "25565:25565"
volumes: volumes:

View File

@@ -1,4 +1,4 @@
version: "3.8" version: "3.7"
services: services:
mc: mc:

View File

@@ -1,3 +1,3 @@
Place server [modpacks downloaded from CurseForge](https://www.curseforge.com/minecraft/modpacks) in this directory. Please server [modpacks downloaded from CurseForge](https://www.curseforge.com/minecraft/modpacks) in this directory.
The example [`docker-compose-curseforge.yml`](../docker-compose-curseforge.yml) references a modpack downloaded from <https://www.curseforge.com/minecraft/modpacks/skyfactory-4/files/2787018>. 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,48 +2,23 @@
. /autopause/autopause-fcns.sh . /autopause/autopause-fcns.sh
. ${SCRIPTS:-/}start-utils . /start-utils
sudo /usr/sbin/knockd -c /autopause/knockd-config.cfg -d
autopause_error_loop() { if [ $? -ne 0 ] ; then
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 : while :
do do
sleep 1800 if [[ -n $(ps -o comm | grep java) ]] ; then
logAutopause "Autopause failed to initialize." break
fi
sleep 0.1
done 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 "Failed to start knockd daemon."
logAutopause "Probable cause: Unable to attach to interface \"$AUTOPAUSE_KNOCK_INTERFACE\"." logAutopause "Possible cause: docker's host network mode."
autopause_error_loop logAutopause "Recreate without host mode or disable autopause functionality."
logAutopause "Stopping server."
killall -SIGTERM java
exit 1
fi fi
STATE=INIT STATE=INIT

View File

@@ -5,19 +5,15 @@ current_uptime() {
} }
java_running() { java_running() {
[[ $( ps -ax -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]] [[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]]
}
java_process_exists() {
[[ -n "$(ps -ax -o comm | grep 'java')" ]]
} }
rcon_client_exists() { rcon_client_exists() {
[[ -n "$(ps -ax -o comm | grep 'rcon-cli')" ]] [[ -n "$(ps -a -o comm | grep 'rcon-cli')" ]]
} }
mc_server_listening() { mc_server_listening() {
[[ -n $(netstat -tln | grep -e "0.0.0.0:$SERVER_PORT" -e ":::$SERVER_PORT" | grep LISTEN) ]] [[ -n $(netstat -tln | grep "0.0.0.0:$SERVER_PORT" | grep LISTEN) ]]
} }
java_clients_connected() { java_clients_connected() {
@@ -33,7 +29,7 @@ java_clients_connected() {
# remember, that the host network mode does not work with autopause because of the knockd utility # remember, that the host network mode does not work with autopause because of the knockd utility
for (( i=0; i<${#connections[@]}; i++ )) for (( i=0; i<${#connections[@]}; i++ ))
do do
if [[ ! $(echo "${connections[$i]}" | awk '{print $5}') =~ ^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$ ]] ; then if [[ ! $(echo "${connections[$i]}" | awk '{print $5}') =~ ^\s*127\.0\.0\.1:.*$ ]] ; then
# not localhost # not localhost
return 0 return 0
fi fi

View File

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

View File

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

View File

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

View File

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

View File

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

9
start
View File

@@ -5,7 +5,7 @@
umask 0002 umask 0002
chmod g+w /data chmod g+w /data
if ! isTrue "${SKIP_SUDO:-false}" && [ $(id -u) = 0 ]; then if [ $(id -u) = 0 ]; then
runAsUser=minecraft runAsUser=minecraft
runAsGroup=minecraft runAsGroup=minecraft
@@ -36,11 +36,16 @@ if ! isTrue "${SKIP_SUDO:-false}" && [ $(id -u) = 0 ]; then
chown -R ${runAsUser}:${runAsGroup} /data chown -R ${runAsUser}:${runAsGroup} /data
fi 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 if [[ ${SKIP_NSSWITCH_CONF^^} != TRUE ]]; then
echo 'hosts: files dns' > /etc/nsswitch.conf echo 'hosts: files dns' > /etc/nsswitch.conf
fi fi
exec gosu ${runAsUser}:${runAsGroup} ${SCRIPTS:-/}start-configuration $@ exec su-exec ${runAsUser}:${runAsGroup} ${SCRIPTS:-/}start-configuration $@
else else
exec ${SCRIPTS:-/}start-configuration $@ exec ${SCRIPTS:-/}start-configuration $@
fi fi

View File

@@ -4,20 +4,18 @@
log "Autopause functionality enabled" log "Autopause functionality enabled"
cp /autopause/knockd-config.cfg /tmp/knockd-config.cfg
# update server port to listen to # update server port to listen to
regseq="^\s*sequence\s*=\s*$SERVER_PORT\s*$" regseq="^\s*sequence\s*=\s*$SERVER_PORT\s*$"
linenum=$(grep -nm1 sequence /tmp/knockd-config.cfg | cut -d : -f 1 | tail -n1) linenum=$(grep -nm1 sequence /autopause/knockd-config.cfg | cut -d : -f 1 | tail -n1)
if ! [[ $(awk "NR==$linenum" /tmp/knockd-config.cfg) =~ $regseq ]]; then if ! [[ $(awk "NR==$linenum" /autopause/knockd-config.cfg) =~ $regseq ]]; then
sed -i "${linenum}s/sequence.*/sequence = $SERVER_PORT/" /tmp/knockd-config.cfg sed -i "${linenum}s/sequence.*/sequence = $SERVER_PORT/" /autopause/knockd-config.cfg
log "Updated server port in knockd config" log "Updated server port in knockd config"
fi fi
# update rcon port to listen to # update rcon port to listen to
regseq="^\s*sequence\s*=\s*$RCON_PORT\s*$" regseq="^\s*sequence\s*=\s*$RCON_PORT\s*$"
linenum=$(grep -nm2 sequence /tmp/knockd-config.cfg | cut -d : -f 1 | tail -n1) linenum=$(grep -nm2 sequence /autopause/knockd-config.cfg | cut -d : -f 1 | tail -n1)
if ! [[ $(awk "NR==$linenum" /tmp/knockd-config.cfg) =~ $regseq ]]; then if ! [[ $(awk "NR==$linenum" /autopause/knockd-config.cfg) =~ $regseq ]]; then
sed -i "${linenum}s/sequence.*/sequence = $RCON_PORT/" /tmp/knockd-config.cfg sed -i "${linenum}s/sequence.*/sequence = $RCON_PORT/" /autopause/knockd-config.cfg
log "Updated rcon port in knockd config" log "Updated rcon port in knockd config"
fi fi
@@ -46,15 +44,10 @@ if ! [[ $AUTOPAUSE_TIMEOUT_INIT =~ ^[0-9]+$ ]] ; then
export AUTOPAUSE_TIMEOUT_INIT export AUTOPAUSE_TIMEOUT_INIT
log "Warning: AUTOPAUSE_TIMEOUT_INIT is not numeric, set to 600 (seconds)" log "Warning: AUTOPAUSE_TIMEOUT_INIT is not numeric, set to 600 (seconds)"
fi 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" && "$MAX_TICK_TIME" != "-1" ]] ; then if [[ -n $MAX_TICK_TIME ]] ; then
log "Warning: MAX_TICK_TIME is non-default, for autopause to work properly, this check should be disabled (-1 for versions >= 1.8.1)" log "Warning: MAX_TICK_TIME is non-default, for autopause to work properly, this check should be disabled (-1 for versions >= 1.8.1)"
elif [[ -z "$MAX_TICK_TIME" ]] ; then else
if versionLessThan 1.8.1; then if versionLessThan 1.8.1; then
# 10 years # 10 years
MAX_TICK_TIME=315360000000 MAX_TICK_TIME=315360000000

View File

@@ -1,22 +1,15 @@
#!/bin/bash #!/bin/bash
set -euo pipefail
IFS=$'\n\t'
. ${SCRIPTS:-/}start-utils . ${SCRIPTS:-/}start-utils
: ${EULA:=}
: ${PROXY:=}
: ${RCON_PASSWORD_FILE:=}
shopt -s nullglob shopt -s nullglob
#umask 002 #umask 002
export HOME=/data export HOME=/data
log "Running as uid=$(id -u) gid=$(id -g) with /data as '$(ls -lnd /data)'"
if [ ! -e /data/eula.txt ]; then if [ ! -e /data/eula.txt ]; then
if ! isTrue "$EULA"; then EULA="${EULA,,}"
if [ "$EULA" != "true" ]; then
log "" log ""
log "Please accept the Minecraft EULA at" log "Please accept the Minecraft EULA at"
log " https://account.mojang.com/documents/minecraft_eula" log " https://account.mojang.com/documents/minecraft_eula"
@@ -26,10 +19,24 @@ if [ ! -e /data/eula.txt ]; then
exit 1 exit 1
fi fi
writeEula echo "# Generated via Docker on $(date)" > /data/eula.txt
if ! echo "eula=$EULA" >> /data/eula.txt; then
log "ERROR: unable to write eula to /data. Please make sure attached directory is writable by uid=${UID}"
exit 2
fi
fi 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 if [[ $PROXY ]]; then
export http_proxy="$PROXY" export http_proxy="$PROXY"
export https_proxy="$PROXY" export https_proxy="$PROXY"
@@ -54,11 +61,7 @@ if [[ $RCON_PASSWORD_FILE ]]; then
log "" log ""
fi fi
if ! which java > /dev/null; then export SERVER_PROPERTIES=/data/server.properties
log "Fixing PATH to include java"
PATH="${PATH}:/opt/java/openjdk/bin"
fi
export VERSIONS_JSON=https://launchermeta.mojang.com/mc/game/version_manifest.json export VERSIONS_JSON=https://launchermeta.mojang.com/mc/game/version_manifest.json
case "X$VERSION" in case "X$VERSION" in
@@ -98,12 +101,6 @@ case "${TYPE^^}" in
;; ;;
FORGE) FORGE)
log "**********************************************************************"
log "WARNING: The image tag itzg/minecraft-server:java8 is recommended"
log " since some mods require Java 8"
log " Exception traces reporting ClassCastException: class jdk.internal.loader.ClassLoaders\$AppClassLoader"
log " can be fixed with java8"
log "**********************************************************************"
exec ${SCRIPTS:-/}start-deployForge "$@" exec ${SCRIPTS:-/}start-deployForge "$@"
;; ;;
@@ -111,18 +108,8 @@ case "${TYPE^^}" in
exec ${SCRIPTS:-/}start-deployFabric "$@" exec ${SCRIPTS:-/}start-deployFabric "$@"
;; ;;
FTBA)
exec ${SCRIPTS:-/}start-deployFTBA "$@"
;;
FTB|CURSEFORGE) FTB|CURSEFORGE)
log "**********************************************************************" exec ${SCRIPTS:-/}start-deployFTB "$@"
log "WARNING: The image tag itzg/minecraft-server:java8 is recommended"
log " since some mods require Java 8"
log " Exception traces reporting ClassCastException: class jdk.internal.loader.ClassLoaders\$AppClassLoader"
log " can be fixed with java8"
log "**********************************************************************"
exec ${SCRIPTS:-/}start-deployCF "$@"
;; ;;
VANILLA) VANILLA)
@@ -153,27 +140,11 @@ case "${TYPE^^}" in
exec ${SCRIPTS:-/}start-deployCatserver "$@" exec ${SCRIPTS:-/}start-deployCatserver "$@"
;; ;;
PURPUR)
exec ${SCRIPTS:-/}start-deployPurpur "$@"
;;
YATOPIA)
exec ${SCRIPTS:-/}start-deployYatopia "$@"
;;
AIRPLANE)
exec ${SCRIPTS:-/}start-deployAirplane "$@"
;;
CANYON)
exec ${SCRIPTS:-/}start-deployCanyon "$@"
;;
*) *)
log "Invalid type: '$TYPE'" log "Invalid type: '$TYPE'"
log "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTBA (multiarch-only)," log "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTBA (multiarch-only),"
log " CURSE_INSTANCE, CURSEFORGE, SPONGEVANILLA, TUINITY, PURPUR" log " CURSE_INSTANCE, CURSEFORGE, SPONGEVANILLA,"
log " CUSTOM, MAGMA, MOHIST, CATSERVER, YATOPIA, AIRPLANE, CANYON" log " CUSTOM, MAGMA, MOHIST, CATSERVER"
exit 1 exit 1
;; ;;

View File

@@ -1,36 +0,0 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
. ${SCRIPTS:-/}start-utils
isDebugging && set -x
JAVA_VER=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1)
if [ "${JAVA_VER}" != "8" ] && [ "${JAVA_VER}" != "11" ]; then
log "ERROR: Airplane server type only supports Java versions 8 and 11"
exit 1
fi
if [ "${VERSION}" != "LATEST" ]; then
log "ERROR: Airplane server type only supports VERSION=LATEST"
exit 1
fi
export SERVER=airplane-${VANILLA_VERSION}-jdk${JAVA_VER}.jar
if [ ! -f "$SERVER" ] || isTrue "$FORCE_REDOWNLOAD"; then
downloadUrl="https://dl.airplane.gg/latest/Airplane-JDK${JAVA_VER}/launcher-airplane.jar"
log "Downloading Airplane from $downloadUrl ..."
curl -fsSL -o "$SERVER" "$downloadUrl"
if [ ! -f "$SERVER" ]; then
log "ERROR: failed to download from $downloadUrl (status=$?)"
exit 3
fi
fi
# Normalize on Spigot for later operations
export TYPE=SPIGOT
export SKIP_LOG4J_CONFIG=true
exec ${SCRIPTS:-/}start-spiget "$@"

View File

@@ -1,7 +1,6 @@
#!/bin/bash #!/bin/bash
. ${SCRIPTS:-/}start-utils . ${SCRIPTS:-/}start-utils
isDebugging && set -x
set -e set -e
@@ -59,41 +58,24 @@ function downloadSpigot {
;; ;;
esac 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 if [[ -z $downloadUrl ]]; then
downloadUrl="https://cdn.getbukkit.org/${getbukkitFlavor}/${getbukkitFlavor}-${VANILLA_VERSION}.jar" downloadUrl="https://cdn.getbukkit.org/${getbukkitFlavor}/${getbukkitFlavor}-${VANILLA_VERSION}.jar"
fi fi
setServerVar
if [ -f $SERVER ]; then if [ -f $SERVER ]; then
# tell curl to only download when newer # tell curl to only download when newer
curlArgs="-z $SERVER" zarg="-z $SERVER"
fi
if isDebugging; then
curlArgs="$curlArgs -v"
fi fi
log "Downloading $match from $downloadUrl ..." log "Downloading $match from $downloadUrl ..."
curl -fsSL -o $SERVER $curlArgs "$downloadUrl" curl -fsSL -o $SERVER $zarg "$downloadUrl"
if [[ $? != 0 || $(grep -c "DOCTYPE html" $SERVER) != 0 ]]; then if [[ $? != 0 || $(grep -c "DOCTYPE html" $SERVER) != 0 ]]; then
cat <<EOF cat <<EOF
ERROR: failed to download from $downloadUrl ERROR: failed to download from $downloadUrl
Visit https://getbukkit.org/download/${getbukkitFlavor} to lookup the Visit https://getbukkit.org/download/${getbukkitFlavor} to lookup the
exact version, such as 1.4.6-R0.4-SNAPSHOT or 1.8-R0.1-SNAPSHOT-latest. exact version, such as 1.4.6-R0.4-SNAPSHOT or 1.8-R0.1-SNAPSHOT-LATEST
Click into the version entry to find the **exact** version, because something
like "1.8" is not sufficient according to their download naming.
EOF EOF
if isDebugging && [[ $(grep -c "DOCTYPE html" $SERVER) != 0 ]]; then
cat $SERVER
fi
# remove invalid download
rm $SERVER
exit 3 exit 3
fi fi
@@ -101,19 +83,17 @@ EOF
export JVM_OPTS export JVM_OPTS
} }
function setServerVar {
case "$TYPE" in case "$TYPE" in
*BUKKIT|*bukkit) *BUKKIT|*bukkit)
export SERVER=craftbukkit_server-${VANILLA_VERSION}.jar export SERVER=craftbukkit_server-${VANILLA_VERSION}.jar
;; ;;
*) *)
export SERVER=spigot_server-${VANILLA_VERSION}.jar export SERVER=spigot_server-${VANILLA_VERSION}.jar
;; ;;
esac esac
}
if isTrue "$BUILD_SPIGOT_FROM_SOURCE" || isTrue "$BUILD_FROM_SOURCE"; then if isTrue "$BUILD_SPIGOT_FROM_SOURCE" || isTrue "$BUILD_FROM_SOURCE"; then
setServerVar
if [ ! -f $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then if [ ! -f $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
buildSpigotFromSource buildSpigotFromSource
fi fi
@@ -125,4 +105,5 @@ fi
export TYPE=SPIGOT export TYPE=SPIGOT
export SKIP_LOG4J_CONFIG=true export SKIP_LOG4J_CONFIG=true
exec ${SCRIPTS:-/}start-spiget "$@" # Continue to Final Setup
exec ${SCRIPTS:-/}start-finalSetupWorld $@

View File

@@ -1,54 +0,0 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
. ${SCRIPTS:-/}start-utils
isDebugging && set -x
: ${CANYON_BUILD:=lastSuccessfulBuild}
JAVA_VER=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1)
if [ "${JAVA_VER}" != "8" ]; then
log "ERROR: Canyon server type only supports Java version 8"
exit 1
fi
if [ "${VERSION}" != "b1.7.3" ]; then
log "ERROR: Canyon server type only supports VERSION=b1.7.3"
exit 1
fi
canyonJob="https://ci.velocitypowered.com/job/Canyon"
buildRelPath=$(
curl -fsSL "${canyonJob}/${CANYON_BUILD}/api/json" |
jq -r '.artifacts[0].relativePath'
)
buildNumber=$(
curl -fsSL "${canyonJob}/${CANYON_BUILD}/api/json" |
jq -r '.number'
)
baseName=$(basename "${buildRelPath}")
# Add build tag to non-tagged builds for version detection
if [ ${baseName%.*} = 'canyon-server' ]; then
export SERVER=${baseName%.*}_build${buildNumber}.jar
else
export SERVER="${baseName}"
fi
if [ ! -f "$SERVER" ]; then
downloadUrl="${canyonJob}/${CANYON_BUILD}/artifact/${buildRelPath}"
log "Downloading Canyon build ${buildNumber} from $downloadUrl ..."
curl -fsSL -o "$SERVER" "$downloadUrl"
if [ ! -f "$SERVER" ]; then
log "ERROR: failed to download from $downloadUrl (status=$?)"
exit 3
fi
fi
# Normalize on Spigot for later operations
export TYPE=SPIGOT
export SKIP_LOG4J_CONFIG=true
exec ${SCRIPTS:-/}start-spiget "$@"

View File

@@ -1,7 +1,6 @@
#!/bin/bash #!/bin/bash
. ${SCRIPTS:-/}start-utils . ${SCRIPTS:-/}start-utils
isDebugging && set -x
if isURL ${CUSTOM_SERVER}; then if isURL ${CUSTOM_SERVER}; then
filename=$(basename ${CUSTOM_SERVER}) filename=$(basename ${CUSTOM_SERVER})
@@ -18,16 +17,12 @@ if isURL ${CUSTOM_SERVER}; then
fi fi
elif [[ -f ${CUSTOM_SERVER} ]]; then elif [[ -f ${CUSTOM_SERVER} ]]; then
export SERVER=${CUSTOM_SERVER} log "Using custom server jar at ${CUSTOM_SERVER} ..."
elif [[ ${GENERIC_PACK} ]]; then
log "Using custom server jar from generic pack at ${CUSTOM_SERVER} ..."
export SERVER=${CUSTOM_SERVER} export SERVER=${CUSTOM_SERVER}
else else
log "CUSTOM_SERVER is not properly set to a URL or existing jar file" log "CUSTOM_SERVER is not properly set to a URL or existing jar file"
exit 2 exit 2
fi fi
export SKIP_LOG4J_CONFIG=true export SKIP_LOG4J_CONFIG=true

View File

@@ -4,30 +4,9 @@ set -e
. ${SCRIPTS:-/}start-utils . ${SCRIPTS:-/}start-utils
loadForgeVars() { export FTB_BASE_DIR=/data/FeedTheBeast
cfgFile=${1?} legacyJavaFixerUrl=http://ftb.cursecdn.com/FTB2/maven/net/minecraftforge/lex/legacyjavafixer/1.0/legacyjavafixer-1.0.jar
pat='^([^#;][^=]+)=[:space:]*([^;]*)' export TYPE=FEED-THE-BEAST
while read -r line || [[ -n "$line" ]] ; do
if [[ $line =~ $pat ]]; then
#echo "MATCHED $line"
k=${BASH_REMATCH[1]}
v=${BASH_REMATCH[2]}
case $k in
FORGEURL)
forgeInstallerUrl="$v"
;;
esac
fi
done < "$cfgFile"
}
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} FTB_SERVER_MOD=${FTB_SERVER_MOD:-$CF_SERVER_MOD}
@@ -35,7 +14,7 @@ log "Looking for Feed-The-Beast / CurseForge server modpack."
requireVar FTB_SERVER_MOD 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 if ! [ -f ${FTB_SERVER_MOD} ]; then
log "ERROR unable to find requested modpack file ${FTB_SERVER_MOD}" log "ERROR unable to find requested modpack file ${FTB_SERVER_MOD}"
exit 2 exit 2
fi fi
@@ -48,7 +27,7 @@ if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then
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 if [[ "${serverJar}" ]]; then
rm -rf $(dirname "${serverJar}")/{mods,*.jar,libraries,resources,scripts,config} rm -rf $(dirname "${serverJar}")/{mods,*.jar,libraries,resources,scripts}
fi fi
else else
needsInstall=false needsInstall=false
@@ -58,40 +37,22 @@ if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then
if $needsInstall; then if $needsInstall; then
log "Unpacking FTB server modpack ${FTB_SERVER_MOD} ..." log "Unpacking FTB server modpack ${FTB_SERVER_MOD} ..."
mkdir -p ${FTB_BASE_DIR} mkdir -p ${FTB_BASE_DIR}
unzip -o "${FTB_SERVER_MOD}" -d ${FTB_BASE_DIR} | awk '{printf "."} END {print ""}' 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) forgeInstallerJar=$(find ${FTB_BASE_DIR} -name "forge*installer.jar")
if [[ -z "$serverJar" ]]; then if [[ -z "${forgeInstallerJar}" ]]; then
log "ERROR Unable to find forge installer in modpack."
if [ -f "${FTB_BASE_DIR}/settings.cfg" ]; then log " Make sure you downloaded the server files."
loadForgeVars "${FTB_BASE_DIR}/settings.cfg" exit 2
if [[ $forgeInstallerUrl ]]; then
forgeInstallerJar="${FTB_BASE_DIR}/forge-installer.jar"
if ! curl -fsSL -o "$forgeInstallerJar" "$forgeInstallerUrl" ; then
log "ERROR failed to download Forge installer from $forgeInstallerUrl"
exit 2
fi
fi
else
forgeInstallerJar=$(find "${FTB_BASE_DIR}" -name "forge*installer.jar")
fi
if [[ -z "${forgeInstallerJar}" ]]; then
log "ERROR Unable to find forge installer in modpack"
log " or download using modpack config."
log " Make sure you downloaded the server files."
exit 2
fi
log "Installing forge server"
(cd $(dirname "${forgeInstallerJar}"); java -jar $(basename "${forgeInstallerJar}") --installServer)
fi fi
log "Installing forge server"
(cd $(dirname "${forgeInstallerJar}"); java -jar $(basename ${forgeInstallerJar}) --installServer) | awk '{printf "."} END {print ""}'
echo "${FTB_SERVER_MOD}" > $installMarker echo "${FTB_SERVER_MOD}" > $installMarker
fi fi
export SERVER=$(find ${FTB_BASE_DIR} -type f \( -path "*/libraries/*" -o -path "*/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -print) export SERVER=$(find ${FTB_BASE_DIR} -not -name "forge*installer.jar" -name "forge*.jar")
if [[ -z "${SERVER}" || ! -f "${SERVER}" ]]; then if [[ -z "${SERVER}" || ! -f "${SERVER}" ]]; then
log "ERROR unable to locate installed forge server jar" 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"
@@ -109,7 +70,6 @@ entryScriptExpr="
-o -name ServerStartLinux.sh -o -name ServerStartLinux.sh
-o -name LaunchServer.sh -o -name LaunchServer.sh
-o -name server-start.sh -o -name server-start.sh
-o -name start-server.sh
-o -name startserver.sh -o -name startserver.sh
-o -name StartServer.sh -o -name StartServer.sh
" "
@@ -129,7 +89,7 @@ fi
# this allows saving just the world separate from the rest of the data directory # this allows saving just the world separate from the rest of the data directory
if [[ $startScriptCount = 0 ]]; then if [[ $startScriptCount = 0 ]]; then
srv_modpack=${FTB_SERVER_MOD} srv_modpack=${FTB_SERVER_MOD}
if isURL "${srv_modpack}"; then if isURL ${srv_modpack}; then
case $srv_modpack in case $srv_modpack in
https://www.feed-the-beast.com/*/download|https://www.curseforge.com/minecraft/modpacks/*/download/*/file) https://www.feed-the-beast.com/*/download|https://www.curseforge.com/minecraft/modpacks/*/download/*/file)
;; ;;
@@ -147,19 +107,19 @@ if [[ $startScriptCount = 0 ]]; then
fi fi
srv_modpack=$downloaded srv_modpack=$downloaded
fi fi
if [[ "${srv_modpack:0:5}" == "data/" ]]; then if [[ ${srv_modpack:0:5} == "data/" ]]; then
# Prepend with "/" # Prepend with "/"
srv_modpack="/${srv_modpack}" srv_modpack=/${srv_modpack}
fi fi
if [[ ! "${srv_modpack:0:1}" == "/" ]]; then if [[ ! ${srv_modpack:0:1} == "/" ]]; then
# If not an absolute path, assume file is in "/data" # If not an absolute path, assume file is in "/data"
srv_modpack=/data/${srv_modpack} srv_modpack=/data/${srv_modpack}
fi fi
if [[ ! -f "${srv_modpack}" ]]; then if [[ ! -f ${srv_modpack} ]]; then
log "FTB server modpack ${srv_modpack} not found." log "FTB server modpack ${srv_modpack} not found."
exit 2 exit 2
fi 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 "FTB server modpack ${srv_modpack} is not a zip archive."
log "Please set FTB_SERVER_MOD to a file with a .zip extension." log "Please set FTB_SERVER_MOD to a file with a .zip extension."
exit 2 exit 2
@@ -167,17 +127,7 @@ if [[ $startScriptCount = 0 ]]; then
log "Unpacking FTB server modpack ${srv_modpack} ..." log "Unpacking FTB server modpack ${srv_modpack} ..."
mkdir -p ${FTB_BASE_DIR} 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 ""}'
installScript=$(find "${FTB_BASE_DIR}" -maxdepth 2 -type f -name install.sh)
if [[ "$installScript" ]]; then
(
cd "$(dirname "${installScript}")"
chmod +x ./install.sh
log "Running included install.sh"
./install.sh
)
fi
fi fi
if [[ $(find ${FTB_BASE_DIR} $entryScriptExpr | wc -l) = 0 ]]; then if [[ $(find ${FTB_BASE_DIR} $entryScriptExpr | wc -l) = 0 ]]; then
@@ -215,7 +165,7 @@ export FTB_SERVER_START=$(find "${FTB_BASE_DIR}" $entryScriptExpr)
export FTB_DIR=$(dirname "${FTB_SERVER_START}") export FTB_DIR=$(dirname "${FTB_SERVER_START}")
chmod a+x "${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/-jar/-Dfml.queryResult=confirm -jar/' "${FTB_SERVER_START}"
sed -i 's/.*read.*Restart now/#\0/' "${FTB_SERVER_START}" sed -i 's/.*read.*Restart now/#\0/' "${FTB_SERVER_START}"
legacyJavaFixerPath="${FTB_DIR}/mods/legacyjavafixer.jar" legacyJavaFixerPath="${FTB_DIR}/mods/legacyjavafixer.jar"

View File

@@ -1,75 +0,0 @@
#!/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
# some modpacks result in --w----r-- permissions
chmod a+r version.json
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,34 +7,36 @@ export TYPE=FABRIC
FABRIC_INSTALLER=${FABRIC_INSTALLER:-} FABRIC_INSTALLER=${FABRIC_INSTALLER:-}
FABRIC_INSTALLER_URL=${FABRIC_INSTALLER_URL:-} FABRIC_INSTALLER_URL=${FABRIC_INSTALLER_URL:-}
FABRIC_INSTALLER_VERSION=${FABRIC_INSTALLER_VERSION:-${FABRICVERSION:-LATEST}} FABRICVERSION=${FABRICVERSION:-LATEST}
if [[ -z $FABRIC_INSTALLER && -z $FABRIC_INSTALLER_URL ]]; then if [[ -z $FABRIC_INSTALLER && -z $FABRIC_INSTALLER_URL ]]; then
log "Checking Fabric version information." log "Checking Fabric version information."
case $FABRIC_INSTALLER_VERSION in case $FABRICVERSION in
LATEST) LATEST)
FABRIC_INSTALLER_VERSION=$(maven-metadata-release https://maven.fabricmc.net/net/fabricmc/fabric-installer/maven-metadata.xml) FABRIC_VERSION=$(maven-metadata-release https://maven.fabricmc.net/net/fabricmc/fabric-installer/maven-metadata.xml)
;;
*)
FABRIC_VERSION=$FABRICVERSION
;; ;;
esac esac
FABRIC_INSTALLER="/tmp/fabric-installer-${FABRIC_INSTALLER_VERSION}.jar" FABRIC_INSTALLER="/tmp/fabric-installer-$FABRIC_VERSION.jar"
markerVersion=$FABRIC_INSTALLER_VERSION
elif [[ -z $FABRIC_INSTALLER ]]; then elif [[ -z $FABRIC_INSTALLER ]]; then
FABRIC_INSTALLER="/tmp/fabric-installer.jar" FABRIC_INSTALLER="/tmp/fabric-installer.jar"
markerVersion=custom
elif [[ ! -e $FABRIC_INSTALLER ]]; then elif [[ ! -e $FABRIC_INSTALLER ]]; then
log "ERROR: the given Fabric installer doesn't exist : $FABRIC_INSTALLER" log "ERROR: the given Fabric installer doesn't exist : $FABRIC_INSTALLER"
exit 2 exit 2
fi fi
installMarker="/data/.fabric-installed-${VANILLA_VERSION}-${markerVersion}" installMarker="/data/.fabric-installed-${VANILLA_VERSION}-${FABRIC_VERSION:-manual}"
debug Checking for installMarker ${installMarker} debug Checking for installMarker ${installMarker}
if [[ ! -e $installMarker ]]; then if [[ ! -e $installMarker ]]; then
if [[ ! -e $FABRIC_INSTALLER ]]; then if [[ ! -e $FABRIC_INSTALLER ]]; then
if [[ -z $FABRIC_INSTALLER_URL ]]; then if [[ -z $FABRIC_INSTALLER_URL ]]; then
log "Downloading installer version $FABRIC_INSTALLER_VERSION" log "Downloading $FABRIC_VERSION"
downloadUrl="https://maven.fabricmc.net/net/fabricmc/fabric-installer/${FABRIC_INSTALLER_VERSION}/fabric-installer-${FABRIC_INSTALLER_VERSION}.jar" downloadUrl="https://maven.fabricmc.net/net/fabricmc/fabric-installer/$FABRIC_VERSION/fabric-installer-$FABRIC_VERSION.jar"
log "...trying $downloadUrl" log "...trying $downloadUrl"
curl -o $FABRIC_INSTALLER -fsSL $downloadUrl curl -o $FABRIC_INSTALLER -fsSL $downloadUrl
else else
@@ -47,17 +49,14 @@ if [[ ! -e $installMarker ]]; then
fi fi
if isDebugging; then if isDebugging; then
debug "Installing Fabric ${VANILLA_VERSION} using $FABRIC_INSTALLER" debug "Installing Fabric $FABRIC_VERSION using $FABRIC_INSTALLER with mcversion ${VANILLA_VERSION}"
else else
log "Installing Fabric using $FABRIC_INSTALLER" log "Installing Fabric $FABRIC_VERSION using $FABRIC_INSTALLER"
fi fi
tries=3 tries=3
set +e set +e
while ((--tries >= 0)); do while ((--tries >= 0)); do
java -jar $FABRIC_INSTALLER server \ java -jar $FABRIC_INSTALLER server -mcversion $VANILLA_VERSION -downloadMinecraft
-mcversion $VANILLA_VERSION \
-downloadMinecraft \
-dir /data
if [[ $? == 0 ]]; then if [[ $? == 0 ]]; then
break break
fi fi

View File

@@ -1,9 +1,8 @@
#!/bin/bash #!/bin/bash
. ${SCRIPTS:-/}start-utils . ${SCRIPTS:-/}start-utils
export TYPE=FORGE export TYPE=FORGE
: ${FORGEVERSION:=RECOMMENDED}
isDebugging && set -x
if [[ -z $FORGE_INSTALLER && -z $FORGE_INSTALLER_URL ]]; then if [[ -z $FORGE_INSTALLER && -z $FORGE_INSTALLER_URL ]]; then
norm=$VANILLA_VERSION norm=$VANILLA_VERSION
@@ -46,8 +45,6 @@ elif [[ -z $FORGE_INSTALLER ]]; then
elif [[ ! -e $FORGE_INSTALLER ]]; then elif [[ ! -e $FORGE_INSTALLER ]]; then
log "ERROR: the given Forge installer doesn't exist : $FORGE_INSTALLER" log "ERROR: the given Forge installer doesn't exist : $FORGE_INSTALLER"
exit 2 exit 2
else
shortForgeVersion=$VANILLA_VERSION-custom
fi fi
installMarker="/data/.forge-installed-$shortForgeVersion" installMarker="/data/.forge-installed-$shortForgeVersion"
@@ -100,11 +97,7 @@ if [ ! -e $installMarker ]; then
log "Finding installed server jar..." log "Finding installed server jar..."
unset -v latest unset -v latest
for file in *forge*.jar; do for file in *forge*.jar; do
if ! [[ $file =~ installer ]]; then [[ $file =~ installer ]] || [[ $file -nt $latest ]] && latest=$file
if [[ -z $latest ]] || [[ $file -nt $latest ]]; then
latest=$file
fi
fi
done done
if [[ -z $latest ]]; then if [[ -z $latest ]]; then
log "Unable to derive server jar for Forge" log "Unable to derive server jar for Forge"

View File

@@ -6,27 +6,26 @@ set -e
isDebugging && set -x isDebugging && set -x
requireVar VANILLA_VERSION requireVar VANILLA_VERSION
: ${MOHIST_BUILD:=lastSuccessfulBuild}
mohistJobs=https://ci.codemc.io/job/MohistMC/job/ mohistJobs=https://ci.codemc.io/job/Mohist-Community/job/
mohistJob=${mohistJobs}Mohist-${VANILLA_VERSION}/ mohistJob=${mohistJobs}Mohist-${VANILLA_VERSION}/
if ! curl -X HEAD -o /dev/null -fsSL "${mohistJob}"; then if ! curl -X HEAD -o /dev/null -fsSL "${mohistJob}"; then
log "ERROR: mohist builds do not exist for ${VANILLA_VERSION}" log "ERROR: mohist builds do not exist for ${VANILLA_VERSION}"
log " check https://ci.codemc.io/job/MohistMC/ for available versions" log " check https://ci.codemc.io/job/Mohist-Community/ for available versions"
log " and set VERSION accordingly" log " and set VERSION accordingly"
exit 1 exit 1
fi fi
buildRelPath=$( latestBuildRelPath=$(
curl -fsSL "${mohistJob}${MOHIST_BUILD}/api/json" | curl -fsSL "${mohistJob}lastSuccessfulBuild/api/json" |
jq -r '.artifacts[0].relativePath' jq -r '.artifacts[0].relativePath'
) )
baseName=$(basename "${buildRelPath}") baseName=$(basename "${latestBuildRelPath}")
if [[ ${baseName} != *-server.jar* ]]; then if [[ ${baseName} != *-server.jar* ]]; then
log "ERROR: mohist build for ${VANILLA_VERSION} is not a valid server jar, found ${baseName}" log "ERROR: mohist build for ${VANILLA_VERSION} is not a valid server jar, found ${baseName}"
log " check https://ci.codemc.io/job/MohistMC/ for available versions" log " check https://ci.codemc.io/job/Mohist-Community/ for available versions"
log " and set VERSION accordingly" log " and set VERSION accordingly"
exit 1 exit 1
fi fi
@@ -35,7 +34,7 @@ export SERVER="/data/${baseName}"
if [ ! -f ${SERVER} ]; then if [ ! -f ${SERVER} ]; then
log "Downloading ${baseName}" log "Downloading ${baseName}"
curl -o "${SERVER}" -fsSL "${mohistJob}${MOHIST_BUILD}/artifact/${buildRelPath}" curl -o "${SERVER}" -fsSL "${mohistJob}lastSuccessfulBuild/artifact/${latestBuildRelPath}"
fi fi
export SKIP_LOG4J_CONFIG=true export SKIP_LOG4J_CONFIG=true

View File

@@ -1,79 +1,24 @@
#!/bin/bash #!/bin/bash
. ${SCRIPTS:-/}start-utils . ${SCRIPTS:-/}start-utils
set -o pipefail
isDebugging && set -x
if [[ $PAPER_DOWNLOAD_URL ]]; then : ${PAPERBUILD:=latest}
export SERVER=$(getFilenameFromUrl "${PAPER_DOWNLOAD_URL}") export SERVER=paper_server-${VANILLA_VERSION}-${PAPERBUILD}.jar
if [ -f "$SERVER" ]; then if [ -f "$SERVER" ] && ! isTrue "$FORCE_REDOWNLOAD"; then
zarg=(-z "$SERVER") zarg="-z '$SERVER'"
fi fi
echo "Preparing custom PaperMC jar from $PAPER_DOWNLOAD_URL" 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" "${zarg[@]}" "${PAPER_DOWNLOAD_URL}" if ! curl -fsSL -o "$SERVER" $zarg "$downloadUrl"; then
else log "ERROR: failed to download from $downloadUrl (status=$?)"
# PaperMC API v2 docs : https://papermc.io/api/docs/swagger-ui/index.html?configUrl=/api/openapi/swagger-config exit 3
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 ..."
shopt -s nullglob
for f in paper-*.jar; do
[[ $f != $SERVER ]] && rm $f
done
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 fi
# Normalize on Spigot for downstream operations # Normalize on Spigot for downstream operations
export TYPE=SPIGOT export TYPE=SPIGOT
export SKIP_LOG4J_CONFIG=true export SKIP_LOG4J_CONFIG=true
exec ${SCRIPTS:-/}start-spiget "$@" # Continue to Final Setup
exec ${SCRIPTS:-/}start-finalSetupWorld $@

View File

@@ -1,37 +0,0 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
. ${SCRIPTS:-/}start-utils
isDebugging && set -x
: ${VANILLA_VERSION:?}
: ${PURPUR_BUILD:=LATEST}
: ${FORCE_REDOWNLOAD:=false}
if [[ ${PURPUR_BUILD} == LATEST ]]; then
PURPUR_BUILD=$(curl -fsSL "https://purpur.pl3x.net/api/v1/purpur/${VANILLA_VERSION}" |
jq -r '.builds.latest' || echo "")
if [[ -z ${PURPUR_BUILD} ]]; then
log "ERROR: Failed to locate a Purpur build for ${VANILLA_VERSION}."
log " Please check if a download is available at https://purpur.pl3x.net/downloads/"
exit 3
fi
fi
export SERVER="purpur-${VANILLA_VERSION}-${PURPUR_BUILD}.jar"
if [ ! -f "$SERVER" ] || isTrue "$FORCE_REDOWNLOAD"; then
downloadUrl="https://purpur.pl3x.net/api/v1/purpur/${VANILLA_VERSION}/${PURPUR_BUILD}/download"
log "Downloading Purpur from $downloadUrl ..."
if ! curl -fsSL -o "$SERVER" "$downloadUrl"; then
log "ERROR: failed to download from $downloadUrl (status=$?)"
exit 3
fi
fi
# Normalize on Spigot for later operations
export TYPE=SPIGOT
export SKIP_LOG4J_CONFIG=true
exec ${SCRIPTS:-/}start-spiget "$@"

View File

@@ -3,8 +3,6 @@
. ${SCRIPTS:-/}start-utils . ${SCRIPTS:-/}start-utils
export TYPE=spongevanilla export TYPE=spongevanilla
: ${SPONGEBRANCH:=STABLE}
: ${SPONGEVERSION:=}
# Parse branch # Parse branch
log "Choosing branch for Sponge" log "Choosing branch for Sponge"

View File

@@ -20,7 +20,8 @@ if [ ! -f "$SERVER" ] || [ -n "$FORCE_REDOWNLOAD" ]; then
fi fi
fi fi
# Normalize on Spigot for later operations # Normalize on Spigot for operations below
export TYPE=SPIGOT export TYPE=SPIGOT
exec ${SCRIPTS:-/}start-spiget "$@" # Continue to Final Setup
exec ${SCRIPTS:-/}start-finalSetupWorld $@

View File

@@ -1,30 +0,0 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
. ${SCRIPTS:-/}start-utils
isDebugging && set -x
: ${VANILLA_VERSION:?}
: ${RELEASE:=stable}
: ${FORCE_REDOWNLOAD:=false}
requireEnum RELEASE stable latest
export SERVER="yatopia-${RELEASE}-${VANILLA_VERSION}.jar"
if [ ! -f "$SERVER" ] || isTrue "$FORCE_REDOWNLOAD"; then
downloadUrl="https://api.yatopiamc.org/v2/${RELEASE}Build/download?branch=ver/${VANILLA_VERSION}"
log "Downloading Yatopia from $downloadUrl ..."
if ! curl -fsSL -o "$SERVER" "$downloadUrl"; then
log "ERROR: failed to download from $downloadUrl (status=$?)"
exit 3
fi
fi
# Normalize on Spigot for later operations
export TYPE=SPIGOT
export SKIP_LOG4J_CONFIG=true
# Continue to Final Setup
exec ${SCRIPTS:-/}start-finalSetupWorld $@

View File

@@ -5,7 +5,7 @@
: ${ENV_VARIABLE_PREFIX:=CFG_} : ${ENV_VARIABLE_PREFIX:=CFG_}
if isTrue "${REPLACE_ENV_VARIABLES}"; then if isTrue "${REPLACE_ENV_VARIABLES}"; then
log "Replacing env variables in configs that match the prefix $ENV_VARIABLE_PREFIX ..." log "Replacing env variables in configs that match the prefix $ENV_VARIABLE_PREFIX..."
# File excludes # File excludes
fileExcludes= fileExcludes=
@@ -22,30 +22,28 @@ if isTrue "${REPLACE_ENV_VARIABLES}"; then
isDebugging && echo "Using find file exclusions: $fileExcludes" isDebugging && echo "Using find file exclusions: $fileExcludes"
isDebugging && echo "Using find directory exclusions: $dirExcludes" isDebugging && echo "Using find directory exclusions: $dirExcludes"
for name in $(compgen -v $ENV_VARIABLE_PREFIX); do while IFS='=' read -r name value ; do
# check if name of env variable matches the prefix # check if name of env variable matches the prefix
# sanity check environment variables to avoid code injections # sanity check environment variables to avoid code injections
# Read content from file environment if [[ "$name" = $ENV_VARIABLE_PREFIX* ]] \
if [[ $name = *"_FILE" ]]; then && [[ $value =~ ^[0-9a-zA-Z_:/=?.+\-]*$ ]] \
value=$(<${!name}) && [[ $name =~ ^[0-9a-zA-Z_\-]*$ ]]; then
name="${name%_FILE}" # Read content from file environment
else if [[ $name = *"_FILE" ]] && [[ -f $value ]]; then
value=${!name} name="${name/_FILE/}"
value=$(<$value)
fi
log "Replacing $name with $value ..."
find /data/ \
$dirExcludes \
-type f \
\( -name "*.yml" -or -name "*.yaml" -or -name "*.txt" -or -name "*.cfg" \
-or -name "*.conf" -or -name "*.properties" \) \
$fileExcludes \
-exec sed -i 's#${'"$name"'}#'"$value"'#g' {} \;
fi fi
done < <(env)
log "Replacing $name with $value ..."
value=${value//\\/\\\\}
value=${value//#/\\#}
find /data/ \
$dirExcludes \
-type f \
\( -name "*.yml" -or -name "*.yaml" -or -name "*.txt" -or -name "*.cfg" \
-or -name "*.conf" -or -name "*.properties" -or -name "*.hjson" -or -name "*.json" \) \
$fileExcludes \
-exec sed -i 's#${'"$name"'}#'"$value"'#g' {} \;
done
fi fi
exec ${SCRIPTS:-/}start-minecraftFinalSetup $@ exec ${SCRIPTS:-/}start-minecraftFinalSetup $@

View File

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

View File

@@ -1,111 +1,80 @@
#!/bin/bash #!/bin/bash
set -e -o pipefail set -e
. ${SCRIPTS:-/}start-utils . ${SCRIPTS:-/}start-utils
if isDebugging; then
set -x
fi
# CURSE_URL_BASE used in manifest downloads below # CURSE_URL_BASE used in manifest downloads below
CURSE_URL_BASE=${CURSE_URL_BASE:-https://minecraft.curseforge.com/projects} CURSE_URL_BASE=${CURSE_URL_BASE:-https://minecraft.curseforge.com/projects}
# Remove old mods/plugins # Remove old mods/plugins
if isTrue ${REMOVE_OLD_MODS:-false}; then if [ "$REMOVE_OLD_MODS" = "TRUE" ]; then
removeOldMods /data/mods if [ "$TYPE" = "SPIGOT" ]; then
removeOldMods /data/plugins rm -rf /data/plugins/*
else
rm -rf /data/mods/*
fi
fi fi
# If supplied with a URL for a modpack (simple zip of jars), download it and unpack # If supplied with a URL for a modpack (simple zip of jars), download it and unpack
if [[ "$MODPACK" ]]; then if [[ "$MODPACK" ]]; then
if isURL "${MODPACK}"; then EFFECTIVE_MODPACK_URL=$(curl -Ls -o /dev/null -w %{url_effective} $MODPACK)
if [[ "${MODPACK}" == *.zip ]]; then case "X$EFFECTIVE_MODPACK_URL" in
downloadUrl="${MODPACK}" X[Hh][Tt][Tt][Pp]*.zip)
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"
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"
fi
else else
downloadUrl=$(curl -Ls -o /dev/null -w %{effective_url} $MODPACK) mkdir -p /data/mods
if ! [[ $downloadUrl == *.zip ]]; then if ! unzip -o -d /data/mods /tmp/modpack.zip; then
log "ERROR Invalid URL given for MODPACK: $downloadUrl resolved from $MODPACK" log "ERROR: failed to unzip the modpack from $EFFECTIVE_MODPACK_URL"
log " Must be HTTP, HTTPS or FTP and a ZIP file"
exit 1
fi fi
fi fi
rm -f /tmp/modpack.zip
log "Downloading mod/plugin pack" ;;
log " from $downloadUrl ..." *)
if ! curl -sSL -o /tmp/modpack.zip "$downloadUrl"; then log "Invalid URL given for modpack: Must be HTTP or HTTPS and a ZIP file"
log "ERROR: failed to download from $downloadUrl" ;;
exit 2 esac
fi
elif [[ "$MODPACK" =~ .*\.zip ]]; then
if ! cp $MODPACK /tmp/modpack.zip; then
log "ERROR: failed to copy from $MODPACK"
exit 2
fi
else
log "ERROR Invalid URL or Path given for MODPACK: $MODPACK"
exit 1
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 $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 $downloadUrl"
fi
fi
rm -f /tmp/modpack.zip
fi fi
# If supplied with a URL for a plugin download it. # If supplied with a URL for a plugin download it.
if [[ "$MODS" ]]; then if [[ "$MODS" ]]; then
if [ "$TYPE" = "SPIGOT" ]; then for i in ${MODS//,/ }
out_dir=/data/plugins do
else EFFECTIVE_MOD_URL=$(curl -Ls -o /dev/null -w %{url_effective} $i)
out_dir=/data/mods case "X$EFFECTIVE_MOD_URL" in
fi X[Hh][Tt][Tt][Pp]*.jar)
mkdir -p "$out_dir" log "Downloading mod/plugin via HTTP"
log " from $EFFECTIVE_MOD_URL ..."
for i in ${MODS//,/ } if ! curl -sSL -o /tmp/${EFFECTIVE_MOD_URL##*/} $EFFECTIVE_MOD_URL; then
do log "ERROR: failed to download from $EFFECTIVE_MOD_URL to /tmp/${EFFECTIVE_MOD_URL##*/}"
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
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
elif [[ -f "$i" && "$i" =~ .*\.jar ]]; then
log "Copying plugin located at $i ..."
out_file=$(basename "$i")
if ! cp "$i" "${out_dir}/$out_file"; then
log "ERROR: failed to copy from $i into $out_dir"
exit 2 exit 2
fi fi
elif [[ -d "$i" ]]; then
log "Copying plugin jars from $i ..." if [ "$TYPE" = "SPIGOT" ]; then
cp "$i"/*.jar "${out_dir}" mkdir -p /data/plugins
else mv /tmp/${EFFECTIVE_MOD_URL##*/} /data/plugins/${EFFECTIVE_MOD_URL##*/}
log "ERROR Invalid URL or path given in MODS: $i" else
exit 2 mkdir -p /data/mods
fi mv /tmp/${EFFECTIVE_MOD_URL##*/} /data/mods/${EFFECTIVE_MOD_URL##*/}
done fi
rm -f /tmp/${EFFECTIVE_MOD_URL##*/}
;;
*)
log "Invalid URL given for modpack: Must be HTTP or HTTPS and a JAR file"
;;
esac
done
fi fi
if [[ "$MANIFEST" ]]; then if [[ "$MANIFEST" ]]; then
@@ -113,7 +82,7 @@ if [[ "$MANIFEST" ]]; then
EFFECTIVE_MANIFEST_FILE=$MANIFEST EFFECTIVE_MANIFEST_FILE=$MANIFEST
elif isURL "$MANIFEST"; then elif isURL "$MANIFEST"; then
EFFECTIVE_MANIFEST_FILE=/tmp/manifest.json EFFECTIVE_MANIFEST_FILE=/tmp/manifest.json
EFFECTIVE_MANIFEST_URL=$(curl -Ls -o /dev/null -w %{effective_url} $MANIFEST) EFFECTIVE_MANIFEST_URL=$(curl -Ls -o /dev/null -w %{url_effective} $MANIFEST)
curl -Ls -o $EFFECTIVE_MANIFEST_FILE "$EFFECTIVE_MANIFEST_URL" curl -Ls -o $EFFECTIVE_MANIFEST_FILE "$EFFECTIVE_MANIFEST_URL"
else else
log "MANIFEST='$MANIFEST' is not a valid manifest url or location" log "MANIFEST='$MANIFEST' is not a valid manifest url or location"
@@ -134,7 +103,7 @@ case "X$EFFECTIVE_MANIFEST_FILE" in
do do
if [ ! -f $MOD_DIR/${p}_${f}.jar ] if [ ! -f $MOD_DIR/${p}_${f}.jar ]
then then
redirect_url="$(curl -Ls -o /dev/null -w %{effective_url} ${CURSE_URL_BASE}/${p})" redirect_url="$(curl -Ls -o /dev/null -w %{url_effective} ${CURSE_URL_BASE}/${p})"
url="$redirect_url/download/${f}/file" url="$redirect_url/download/${f}/file"
log Downloading curseforge mod $url log Downloading curseforge mod $url
# Manifest usually doesn't have mod names. Using id should be fine, tho # Manifest usually doesn't have mod names. Using id should be fine, tho
@@ -153,17 +122,17 @@ fi
if [[ "${GENERIC_PACK}" ]]; then if [[ "${GENERIC_PACK}" ]]; then
if isURL "${GENERIC_PACK}"; then if isURL "${GENERIC_PACK}"; then
log "Downloading generic pack ..." generic_pack_url=${GENERIC_PACK}
curl -fsSL -o /tmp/generic_pack.zip "${GENERIC_PACK}" GENERIC_PACK=/tmp/$(basename ${generic_pack_url})
GENERIC_PACK=/tmp/generic_pack.zip log "Downloading generic pack from ${generic_pack_url} ..."
curl -fsSL -o ${GENERIC_PACK} ${generic_pack_url}
fi fi
sum_file=/data/.generic_pack.sum sum_file=/data/.generic_pack.sum
if ! sha256sum -c ${sum_file} -s 2> /dev/null; then if ! sha256sum -c ${sum_file} -s 2> /dev/null; then
base_dir=/tmp/generic_pack_base base_dir=/tmp/generic_pack_base
mkdir -p ${base_dir} mkdir -p ${base_dir}
isDebugging && ls -l "${GENERIC_PACK}" unzip -q -d ${base_dir} ${GENERIC_PACK}
unzip -q -d ${base_dir} "${GENERIC_PACK}"
if [ -f /data/manifest.txt ]; then if [ -f /data/manifest.txt ]; then
log "Manifest exists from older generic pack, cleaning up ..." log "Manifest exists from older generic pack, cleaning up ..."
while read f; do while read f; do
@@ -181,7 +150,7 @@ if [[ "${GENERIC_PACK}" ]]; then
for d in $(find ${base_dir} -type d); do mkdir -p "$(sed "s#${base_dir}#/data#" <<< $d)"; done 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 for f in $(find ${base_dir} -type f); do cp -f "$f" "$(sed "s#${base_dir}#/data#" <<< $f)"; done
rm -rf ${base_dir} rm -rf ${base_dir}
sha256sum "${GENERIC_PACK}" > ${sum_file} sha256sum ${GENERIC_PACK} > ${sum_file}
fi fi
fi fi

View File

@@ -1,40 +0,0 @@
#!/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
: ${COPY_MODS_DEST:="/data/mods"}
if [ -d /mods ]; then
log "Copying any mods over..."
mkdir -p $COPY_MODS_DEST
rsync -a --out-format="update:%f:Last Modified %M" "${rsyncArgs[@]}" --prune-empty-dirs --update /mods/ $COPY_MODS_DEST
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 $@

23
start-finalSetupPlugins Executable file
View File

@@ -0,0 +1,23 @@
#!/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

@@ -2,8 +2,6 @@
. ${SCRIPTS:-/}start-utils . ${SCRIPTS:-/}start-utils
: ${SERVER_PROPERTIES:=/data/server.properties}
# FUNCTIONS # FUNCTIONS
function setServerProp { function setServerProp {
local prop=$1 local prop=$1
@@ -14,15 +12,10 @@ function setServerProp {
TRUE|FALSE) TRUE|FALSE)
var=${var,,} ;; var=${var,,} ;;
esac esac
if grep "${prop}" "$SERVER_PROPERTIES" > /dev/null; then log "Setting ${prop} to '${var}' in ${SERVER_PROPERTIES}"
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 "Adding ${prop} with '${var}' in ${SERVER_PROPERTIES}"
echo "${prop}=${var//\\/\\\\}" >> "$SERVER_PROPERTIES"
fi
else else
isDebugging && log "Skip setting ${prop}" log "Skip setting ${prop}"
fi fi
} }
@@ -31,10 +24,6 @@ function customizeServerProps {
log "Creating whitelist" log "Creating whitelist"
setServerProp "whitelist" "true" setServerProp "whitelist" "true"
setServerProp "white-list" "true" setServerProp "white-list" "true"
else
log "Disabling whitelist"
setServerProp "whitelist" "false"
setServerProp "white-list" "false"
fi fi
# If not provided, generate a reasonable default message-of-the-day, # If not provided, generate a reasonable default message-of-the-day,
@@ -80,7 +69,7 @@ function customizeServerProps {
setServerProp "max-world-size" "$MAX_WORLD_SIZE" setServerProp "max-world-size" "$MAX_WORLD_SIZE"
setServerProp "level-name" "$LEVEL" setServerProp "level-name" "$LEVEL"
setServerProp "level-seed" "$SEED" setServerProp "level-seed" "$SEED"
setServerProp "pvp" "${PVP}" setServerProp "pvp" "$PVP"
setServerProp "generator-settings" "$GENERATOR_SETTINGS" setServerProp "generator-settings" "$GENERATOR_SETTINGS"
setServerProp "online-mode" "$ONLINE_MODE" setServerProp "online-mode" "$ONLINE_MODE"
setServerProp "allow-flight" "$ALLOW_FLIGHT" setServerProp "allow-flight" "$ALLOW_FLIGHT"
@@ -181,8 +170,8 @@ function customizeServerProps {
} }
# Deploy server.properties file # Deploy server.properties file
if [[ ${TYPE} == "CURSEFORGE" ]]; then if [[ ${TYPE} == "FEED-THE-BEAST" ]]; then
export SERVER_PROPERTIES="${FTB_DIR}/server.properties" export SERVER_PROPERTIES=${FTB_DIR}/server.properties
log "detected FTB, changing properties path to ${SERVER_PROPERTIES}" log "detected FTB, changing properties path to ${SERVER_PROPERTIES}"
fi fi
@@ -214,7 +203,7 @@ fi
if isDebugging; then if isDebugging; then
log "DEBUG Dumping server.properties" log "DEBUG Dumping server.properties"
cat "${SERVER_PROPERTIES}" cat /data/server.properties
fi fi
exec ${SCRIPTS:-/}start-finalSetupEnvVariables $@ exec ${SCRIPTS:-/}start-finalSetupEnvVariables $@

View File

@@ -4,23 +4,13 @@
set -e set -e
isDebugging && set -x isDebugging && set -x
: ${LEVEL:=world} if [ $TYPE = "FEED-THE-BEAST" ]; then
export LEVEL
if [ $TYPE = "CURSEFORGE" ]; then
worldDest=$FTB_DIR/$LEVEL worldDest=$FTB_DIR/$LEVEL
else else
worldDest=/data/$LEVEL worldDest=/data/$LEVEL
fi fi
if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] ); then if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] ); then
if isTrue "${FORCE_WORLD_COPY}"; then
log "Removing existing world data in $worldDest ${worldDest}_nether ${worldDest}_the_end"
rm -rf "$worldDest" \
"${worldDest}_nether" \
"${worldDest}_the_end"
fi
if isURL $WORLD; then if isURL $WORLD; then
curl -fsSL "$WORLD" -o /tmp/world.zip curl -fsSL "$WORLD" -o /tmp/world.zip
zipSrc=/tmp/world.zip zipSrc=/tmp/world.zip
@@ -35,12 +25,7 @@ if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] );
mkdir -p /tmp/world-data mkdir -p /tmp/world-data
(cd /tmp/world-data && unzip -o -q "$zipSrc") (cd /tmp/world-data && unzip -o -q "$zipSrc")
if [ "$TYPE" = "SPIGOT" ]; then baseDirs=$(find /tmp/world-data -name "level.dat" -exec dirname "{}" \;)
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) count=$(echo "$baseDirs" | wc -l)
if [[ $count -gt 1 ]]; then if [[ $count -gt 1 ]]; then
baseDir="$(echo "$baseDirs" | sed -n ${WORLD_INDEX:-1}p)" baseDir="$(echo "$baseDirs" | sed -n ${WORLD_INDEX:-1}p)"
@@ -53,11 +38,6 @@ if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] );
exit 1 exit 1
fi fi
rsync --remove-source-files --recursive --delete "$baseDir/" "$worldDest" 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 else
log "Cloning world directory from $WORLD ..." log "Cloning world directory from $WORLD ..."
rsync --recursive --delete "${WORLD%/}"/ "$worldDest" rsync --recursive --delete "${WORLD%/}"/ "$worldDest"
@@ -66,8 +46,8 @@ if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] );
if [ "$TYPE" = "SPIGOT" ]; then if [ "$TYPE" = "SPIGOT" ]; then
# Reorganise if a Spigot server # Reorganise if a Spigot server
log "Moving End and Nether maps to Spigot location" log "Moving End and Nether maps to Spigot location"
[ -d "$worldDest/DIM1" ] && mv -f "$worldDest/DIM1" "${worldDest}_the_end" [ -d "$worldDest/DIM1" ] && mv -f "$worldDest/DIM1" "/data/${LEVEL}_the_end"
[ -d "$worldDest/DIM-1" ] && mv -f "$worldDest/DIM-1" "${worldDest}_nether" [ -d "$worldDest/DIM-1" ] && mv -f "$worldDest/DIM-1" "/data/${LEVEL}_nether"
fi fi
fi fi

View File

@@ -1,53 +1,42 @@
#!/bin/bash #!/bin/bash
. ${SCRIPTS:-/}start-utils . ${SCRIPTS:-/}start-utils
isDebugging && set -x
if [ -n "$OPS" ]; then if [ -n "$OPS" ]; then
log "Updating ops" log "Setting/adding ops"
rm -f /data/ops.txt.converted rm -rf /data/ops.txt.converted
echo $OPS | awk -v RS=, '{print}' > /data/ops.txt echo $OPS | awk -v RS=, '{print}' > /data/ops.txt
fi fi
if isTrue "${OVERRIDE_OPS}"; then
log "Recreating ops.json file at server startup"
rm -f /data/ops.json
fi
if [ -n "$WHITELIST" ]; then if [ -n "$WHITELIST" ]; then
log "Updating whitelist" log "Setting whitelist"
rm -f /data/white-list.txt.converted rm -rf /data/white-list.txt.converted
echo $WHITELIST | awk -v RS=, '{print}' > /data/white-list.txt echo $WHITELIST | awk -v RS=, '{print}' > /data/white-list.txt
fi fi
if isTrue "${OVERRIDE_WHITELIST}"; then
log "Recreating whitelist.json file at server startup"
rm -f /data/whitelist.json
fi
if [ -n "$ICON" ]; then if [ -n "$ICON" -a ! -e server-icon.png ]; then
if [ ! -e server-icon.png ] || [ "${OVERRIDE_ICON}" == "TRUE" ]; then log "Using server icon from $ICON..."
log "Using server icon from $ICON..." # Not sure what it is yet...call it "img"
# Not sure what it is yet...call it "img" curl -sSL -o /tmp/icon.img $ICON
curl -sSL -o /tmp/icon.img $ICON specs=$(identify /tmp/icon.img | awk '{print $2,$3}')
specs=$(identify /tmp/icon.img | awk '{print $2,$3}') if [ "$specs" = "PNG 64x64" ]; then
if [ "$specs" = "PNG 64x64" ]; then mv /tmp/icon.img /data/server-icon.png
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 ${ENABLE_ROLLING_LOGS:-false}; then
# Set up log configuration
LOGFILE="/data/log4j2.xml"
if [ ! -e "$LOGFILE" ]; then
log "Creating log4j2.xml in ${LOGFILE}"
cp /tmp/log4j2.xml "$LOGFILE"
else else
log "log4j2.xml already created, skipping" log "Converting image to 64x64 PNG..."
convert /tmp/icon.img -resize 64x64! /data/server-icon.png
fi fi
JVM_OPTS="-Dlog4j.configurationFile=/data/log4j2.xml ${JVM_OPTS}" fi
if ! isTrue ${SKIP_LOG4J_CONFIG}; then
# Set up log configuration
LOGFILE="/data/log4j2.xml"
if [ ! -e "$LOGFILE" ]; then
log "Creating log4j2.xml in ${LOGFILE}"
cp /tmp/log4j2.xml "$LOGFILE"
else
log "log4j2.xml already created, skipping"
fi
JVM_OPTS="-Dlog4j.configurationFile=/data/log4j2.xml ${JVM_OPTS}"
fi fi
# Make sure files exist and are valid JSON (for pre-1.12 to 1.12 upgrades) # Make sure files exist and are valid JSON (for pre-1.12 to 1.12 upgrades)
@@ -60,14 +49,32 @@ for j in $JSON_FILES; do
fi fi
done 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 # Optional disable console
if versionLessThan 1.14 && [[ ${CONSOLE,,} = false ]]; then if versionLessThan 1.14 && [[ ${CONSOLE,,} = false ]]; then
EXTRA_ARGS+=" --noconsole" EXTRA_ARGS+="--noconsole"
fi fi
# Optional disable GUI for headless servers # Optional disable GUI for headless servers
if [[ ${GUI} = false || ${GUI} = FALSE ]]; then if [[ ${GUI} = false || ${GUI} = FALSE ]]; then
EXTRA_ARGS+=" nogui" EXTRA_ARGS="${EXTRA_ARGS} nogui"
fi fi
# put these prior JVM_OPTS at the end to give any memory settings there higher precedence # put these prior JVM_OPTS at the end to give any memory settings there higher precedence
@@ -82,6 +89,7 @@ if [ -n "$JVM_DD_OPTS" ]; then
fi fi
if isTrue ${ENABLE_JMX}; then if isTrue ${ENABLE_JMX}; then
: ${JMX_HOST:=0.0.0.0}
: ${JMX_PORT:=7091} : ${JMX_PORT:=7091}
JVM_OPTS="${JVM_OPTS} JVM_OPTS="${JVM_OPTS}
-Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.local.only=false
@@ -89,8 +97,8 @@ if isTrue ${ENABLE_JMX}; then
-Dcom.sun.management.jmxremote.rmi.port=${JMX_PORT} -Dcom.sun.management.jmxremote.rmi.port=${JMX_PORT}
-Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.host=${JMX_BINDING:-0.0.0.0} -Dcom.sun.management.jmxremote.host=${JMX_HOST}
-Djava.rmi.server.hostname=${JMX_HOST:-localhost}" -Djava.rmi.server.hostname=${JMX_HOST}"
log "JMX is enabled. Make sure you have port forwarding for ${JMX_PORT}" log "JMX is enabled. Make sure you have port forwarding for ${JMX_PORT}"
fi fi
@@ -144,13 +152,6 @@ if isTrue "${USE_LARGE_PAGES}"; then
" "
fi fi
if isTrue "${USE_FLARE_FLAGS}"; then
JVM_XX_OPTS="${JVM_XX_OPTS}
-XX:+UnlockDiagnosticVMOptions
-XX:+DebugNonSafepoints
"
fi
if isTrue "${DEBUG_MEMORY}"; then if isTrue "${DEBUG_MEMORY}"; then
log "Memory usage and availability (in MB)" log "Memory usage and availability (in MB)"
uname -a uname -a
@@ -162,17 +163,17 @@ JVM_OPTS="-Xms${INIT_MEMORY} -Xmx${MAX_MEMORY} ${JVM_OPTS}"
function copyFilesForCurseForge() { function copyFilesForCurseForge() {
# copy player modification files unconditionally since their # copy player modification files unconditionally since their
# processing into json is additive anyway # processing into json is additive anyway
[ -f /data/ops.txt ] && cp -f /data/ops.txt "${FTB_DIR}/" [ -f /data/ops.txt ] && cp -f /data/ops.txt ${FTB_DIR}/
[ -f /data/white-list.txt ] && cp -f /data/white-list.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 if [ ! -e "${FTB_DIR}/server-icon.png" -a -e /data/server-icon.png ]; then
cp -f /data/server-icon.png "${FTB_DIR}/" cp -f /data/server-icon.png ${FTB_DIR}/
fi fi
cp -f /data/eula.txt "${FTB_DIR}/" cp -f /data/eula.txt "${FTB_DIR}/"
} }
mcServerRunnerArgs="--stop-duration ${STOP_DURATION:-60}s" mcServerRunnerArgs="--stop-duration 60s"
if [[ ${TYPE} == "CURSE_INSTANCE" ]]; then if [[ ${TYPE} == "CURSE_INSTANCE" ]]; then
if isTrue ${DEBUG_EXEC}; then if isTrue ${DEBUG_EXEC}; then
set -x set -x
@@ -180,7 +181,7 @@ if [[ ${TYPE} == "CURSE_INSTANCE" ]]; then
exec mc-server-runner ${mcServerRunnerArgs} \ exec mc-server-runner ${mcServerRunnerArgs} \
--cf-instance-file "${CURSE_INSTANCE_JSON}" \ --cf-instance-file "${CURSE_INSTANCE_JSON}" \
java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar _SERVERJAR_ "$@" $EXTRA_ARGS java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar _SERVERJAR_ "$@" $EXTRA_ARGS
elif [[ ${TYPE} == "CURSEFORGE" && "${SERVER}" ]]; then elif [[ ${TYPE} == "FEED-THE-BEAST" && "${SERVER}" ]]; then
copyFilesForCurseForge copyFilesForCurseForge
cd "${FTB_DIR}" cd "${FTB_DIR}"
@@ -189,7 +190,7 @@ elif [[ ${TYPE} == "CURSEFORGE" && "${SERVER}" ]]; then
set -x set -x
fi fi
exec mc-server-runner ${bootstrapArgs} ${mcServerRunnerArgs} java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar $(basename "${SERVER}") "$@" $EXTRA_ARGS exec mc-server-runner ${bootstrapArgs} ${mcServerRunnerArgs} java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar $(basename "${SERVER}") "$@" $EXTRA_ARGS
elif [[ ${TYPE} == "CURSEFORGE" ]]; then elif [[ ${TYPE} == "FEED-THE-BEAST" ]]; then
mcServerRunnerArgs="${mcServerRunnerArgs} --shell bash" mcServerRunnerArgs="${mcServerRunnerArgs} --shell bash"
copyFilesForCurseForge copyFilesForCurseForge
@@ -207,19 +208,10 @@ EOF
cd "${FTB_DIR}" cd "${FTB_DIR}"
log "Running FTB ${FTB_SERVER_START} in ${FTB_DIR} ..." log "Running FTB ${FTB_SERVER_START} in ${FTB_DIR} ..."
finalArgs=(
"${FTB_SERVER_START}"
)
if isTrue ${DEBUG_EXEC}; then if isTrue ${DEBUG_EXEC}; then
set -x set -x
fi fi
if isTrue ${EXEC_DIRECTLY:-false}; then exec mc-server-runner ${mcServerRunnerArgs} "${FTB_SERVER_START}"
"${finalArgs[@]}"
else
exec mc-server-runner ${mcServerRunnerArgs} "${finalArgs[@]}"
fi
else else
# If we have a bootstrap.txt file... feed that in to the server stdin # If we have a bootstrap.txt file... feed that in to the server stdin
if [ -f /data/bootstrap.txt ]; then if [ -f /data/bootstrap.txt ]; then
@@ -227,23 +219,8 @@ else
fi fi
log "Starting the Minecraft server..." log "Starting the Minecraft server..."
finalArgs=(
$JVM_XX_OPTS
$JVM_OPTS
$expandedDOpts
-jar $SERVER
"$@" $EXTRA_ARGS
)
if isTrue ${DEBUG_EXEC}; then if isTrue ${DEBUG_EXEC}; then
set -x set -x
fi fi
exec mc-server-runner ${bootstrapArgs} ${mcServerRunnerArgs} java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar $SERVER "$@" $EXTRA_ARGS
if isTrue ${EXEC_DIRECTLY:-false}; then
exec java "${finalArgs[@]}"
else
exec mc-server-runner ${bootstrapArgs} ${mcServerRunnerArgs} java "${finalArgs[@]}"
fi
fi fi

View File

@@ -1,62 +0,0 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
. ${SCRIPTS:-/}start-utils
handleDebugMode
: ${SPIGET_RESOURCES:=}
containsJars() {
file=${1?}
pat='\.jar$'
while read -r line; do
if [[ $line =~ $pat ]]; then
return 0
fi
done <<<$(unzip -l "$file")
return 1
}
getResourceFromSpiget() {
resource=${1?}
log "Downloading resource ${resource} ..."
tmpfile="/tmp/${resource}.zip"
url="https://api.spiget.org/v2/resources/${resource}/download"
if ! curl -o "${tmpfile}" -fsSL -H "User-Agent: itzg/minecraft-server" "${extraCurlArgs[@]}" "${url}"; then
log "ERROR failed to download resource '${resource}' from ${url}"
exit 2
fi
mkdir -p /data/plugins
if containsJars "${tmpfile}"; then
log "Extracting contents of resource ${resource} into plugins"
unzip -o -q -d /data/plugins "${tmpfile}"
rm "${tmpfile}"
else
log "Moving resource ${resource} into plugins"
mv "${tmpfile}" "/data/plugins/${resource}.jar"
fi
}
if [[ ${SPIGET_RESOURCES} ]]; then
if isTrue ${REMOVE_OLD_MODS:-false}; then
removeOldMods /data/plugins
REMOVE_OLD_MODS=false
fi
log "Getting plugins via Spiget"
IFS=',' read -r -a resources <<<"${SPIGET_RESOURCES}"
for resource in "${resources[@]}"; do
getResourceFromSpiget "${resource}"
done
fi
# Continue to Final Setup
exec ${SCRIPTS:-/}start-finalSetupWorld $@

View File

@@ -1,138 +1,101 @@
#!/bin/bash #!/bin/bash
function join_by() { function join_by { local d=$1; shift; echo -n "$1"; shift; printf "%s" "${@/#/$d}"; }
local d=$1
shift
echo -n "$1"
shift
printf "%s" "${@/#/$d}"
}
function isURL() { function isURL {
local value=$1 local value=$1
if [[ ${value:0:8} == "https://" || ${value:0:7} == "http://" || ${value:0:6} == "ftp://" ]]; then if [[ ${value:0:8} == "https://" || ${value:0:7} == "http://" ]]; then
return 0 return 0
else else
return 1 return 1
fi fi
} }
function isValidFileURL() { function isTrue {
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,,} local value=${1,,}
result= result=
case ${value} in case ${value} in
true | on) true|on)
result=0 result=0
;; ;;
*) *)
result=1 result=1
;; ;;
esac esac
return ${result} return ${result}
} }
function isDebugging() { function isDebugging {
if isTrue "${DEBUG:-false}"; then if [[ -v DEBUG ]] && [[ ${DEBUG^^} = TRUE ]]; then
return 0 return 0
else else
return 1 return 1
fi fi
} }
function handleDebugMode() { function debug {
if isDebugging; then
set -x
extraCurlArgs=(-v)
fi
}
function debug() {
if isDebugging; then if isDebugging; then
log "DEBUG: $*" log "DEBUG: $*"
fi fi
} }
function logn() { function logn {
echo -n "[init] $*" echo -n "[init] $*"
} }
function log() { function log {
echo "[init] $*" echo "[init] $*"
} }
function logAutopause() { function logAutopause {
echo "[Autopause loop] $*" echo "[Autopause loop] $*"
} }
function logAutopauseAction() { function logAutopauseAction {
echo "[$(date -Iseconds)] [Autopause] $*" echo "[$(date -Iseconds)] [Autopause] $*"
} }
function normalizeMemSize() { function normalizeMemSize {
local scale=1 local scale=1
case ${1,,} in case ${1,,} in
*k) *k)
scale=1024 scale=1024;;
;; *m)
*m) scale=1048576;;
scale=1048576 *g)
;; scale=1073741824;;
*g)
scale=1073741824
;;
esac esac
val=${1:0:-1} val=${1:0: -1}
echo $((val * scale)) echo $(( val * scale ))
} }
function versionLessThan() { function versionLessThan {
local activeParts local activeParts
IFS=. read -ra activeParts <<<"${VANILLA_VERSION}" IFS=. read -ra activeParts <<< "${VANILLA_VERSION}"
local givenParts local givenParts
IFS=. read -ra givenParts <<<"$1" IFS=. read -ra givenParts <<< "$1"
if ((${#activeParts[@]} < 2)); then if (( ${#activeParts[@]} < 2 )); then
return 1 return 1
fi fi
if ((${#activeParts[@]} == 2)); then if (( ${#activeParts[@]} == 2 )); then
if ((activeParts[0] < givenParts[0])) || if (( activeParts[0] < givenParts[0] )) || \
((activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1])); then (( activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1] )); then
return 0 return 0
else else
return 1 return 1
fi fi
else else
if ((activeParts[0] < givenParts[0])) || if (( activeParts[0] < givenParts[0] )) || \
((activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1])) || (( activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1] )) || \
((activeParts[0] == givenParts[0] && activeParts[1] == givenParts[1] && activeParts[2] < givenParts[2])); then (( activeParts[0] == givenParts[0] && activeParts[1] == givenParts[1] && activeParts[2] < givenParts[2] )); then
return 0 return 0
else else
return 1 return 1
@@ -150,33 +113,3 @@ requireVar() {
exit 1 exit 1
fi fi
} }
requireEnum() {
var=${1?}
shift
for allowed in $*; do
if [[ ${!var} = $allowed ]]; then
return 0
fi
done
log "ERROR: $var must be set to one of $@"
# exit 1
}
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
}
function removeOldMods {
if [ -d "$1" ]; then
find "$1" -mindepth 1 -maxdepth ${REMOVE_OLD_MODS_DEPTH:-16} -wholename "${REMOVE_OLD_MODS_INCLUDE:-*}" -not -wholename "${REMOVE_OLD_MODS_EXCLUDE:-}" -delete
fi
}

View File

@@ -10,9 +10,6 @@ services:
restart: "no" restart: "no"
build: build:
context: .. context: ..
args:
TARGETOS: linux
TARGETARCH: amd64
cache_from: cache_from:
- itzg/minecraft-server:latest - itzg/minecraft-server:latest
environment: environment: