mirror of
https://github.com/itzg/docker-minecraft-server.git
synced 2026-02-17 15:13:55 +00:00
Compare commits
138 Commits
1.0.0
...
1.12.0-ado
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f515e1927 | ||
|
|
d40bbdc3a5 | ||
|
|
61c291ae4e | ||
|
|
0be8968e7e | ||
|
|
f613228619 | ||
|
|
a5e756c86f | ||
|
|
ca9f883352 | ||
|
|
9d68fa3b88 | ||
|
|
d3a5885d95 | ||
|
|
c1db13c1f6 | ||
|
|
31b0f711b8 | ||
|
|
59ca1ce3a6 | ||
|
|
0f7bd5f4fd | ||
|
|
957d11655b | ||
|
|
a368f4cf57 | ||
|
|
08a4bde6c1 | ||
|
|
f68e979229 | ||
|
|
544b1f243d | ||
|
|
391e807c78 | ||
|
|
4099cde737 | ||
|
|
e56a74dc81 | ||
|
|
31b8535854 | ||
|
|
ed1bb73c22 | ||
|
|
b7ac28e902 | ||
|
|
3cb72797b6 | ||
|
|
6f1f8d7806 | ||
|
|
b06f1115d4 | ||
|
|
777ad31de0 | ||
|
|
8b977f8786 | ||
|
|
7c3139226c | ||
|
|
0ddabf3089 | ||
|
|
6cfc7e45ef | ||
|
|
9ea675bc89 | ||
|
|
42f90c8806 | ||
|
|
c8b6eac8fe | ||
|
|
d78272c1fa | ||
|
|
48ccdf128f | ||
|
|
2322dffd49 | ||
|
|
8a5e5bf01e | ||
|
|
99ed83022e | ||
|
|
07185534fb | ||
|
|
50c22ac469 | ||
|
|
4fe55b5a28 | ||
|
|
bd503f224d | ||
|
|
b5c91647ca | ||
|
|
c359a0f2ac | ||
|
|
49d9f4a89d | ||
|
|
aebe35c9d4 | ||
|
|
a26361c79f | ||
|
|
81e1cd8cfd | ||
|
|
a486458a08 | ||
|
|
82b8401414 | ||
|
|
8b6ee91ec1 | ||
|
|
06cffd9e15 | ||
|
|
beaccbcf3b | ||
|
|
21ee5e2401 | ||
|
|
8387e9bd26 | ||
|
|
747c188824 | ||
|
|
692087dd25 | ||
|
|
6fe13e8654 | ||
|
|
3b2b98b9fe | ||
|
|
796f2fe14a | ||
|
|
4fef391b64 | ||
|
|
83f6cebd0b | ||
|
|
90183ae823 | ||
|
|
3c9df03584 | ||
|
|
367c6cfd92 | ||
|
|
5e75410e7c | ||
|
|
38028f7d0c | ||
|
|
4afdb289c0 | ||
|
|
a07ae685e2 | ||
|
|
fe637353d8 | ||
|
|
092b530537 | ||
|
|
cf691499a1 | ||
|
|
0bb9cccdc6 | ||
|
|
4cb12f6cae | ||
|
|
ecbdeb2096 | ||
|
|
9a7a532f7b | ||
|
|
825833c859 | ||
|
|
c4c3613874 | ||
|
|
9160501f0a | ||
|
|
3a03156cb3 | ||
|
|
b3780186f8 | ||
|
|
c4654e44d8 | ||
|
|
9c6047e3fc | ||
|
|
260cc7d180 | ||
|
|
bbe930e552 | ||
|
|
a655fe860e | ||
|
|
ddf36aa879 | ||
|
|
34c31c561d | ||
|
|
3cc7d00d71 | ||
|
|
ed214b1382 | ||
|
|
f8405e298c | ||
|
|
539159ba50 | ||
|
|
f2c9d2f905 | ||
|
|
1b11331881 | ||
|
|
b71afff29f | ||
|
|
b4c6950f95 | ||
|
|
6eba5062ec | ||
|
|
ec0329efb1 | ||
|
|
477caa12c3 | ||
|
|
8f82ff9b1d | ||
|
|
7d97fdcbec | ||
|
|
5ee0150154 | ||
|
|
1bcacfc474 | ||
|
|
34603184a4 | ||
|
|
fc96723db1 | ||
|
|
2ee5a25c91 | ||
|
|
60ef1b8867 | ||
|
|
3eaf756aa2 | ||
|
|
bc318fa185 | ||
|
|
f93c42a23f | ||
|
|
f5dde77efe | ||
|
|
2b7f923865 | ||
|
|
80099ad63d | ||
|
|
b273bf2947 | ||
|
|
2241ba8819 | ||
|
|
3cf58e3caf | ||
|
|
450442a916 | ||
|
|
8c866bd17d | ||
|
|
8deaf1850b | ||
|
|
6da2aca975 | ||
|
|
11989d17e3 | ||
|
|
5aa6e5c2a9 | ||
|
|
825398f4d4 | ||
|
|
ccac249c01 | ||
|
|
f2806d9335 | ||
|
|
b11806e341 | ||
|
|
71a7afab17 | ||
|
|
8d3e461b4c | ||
|
|
fd73417411 | ||
|
|
1207b9a685 | ||
|
|
e6259bfd9d | ||
|
|
b5e7b952e4 | ||
|
|
ac5b960182 | ||
|
|
3299dec733 | ||
|
|
578f06087f | ||
|
|
fb364e8301 |
@@ -1,22 +0,0 @@
|
||||
version: 2
|
||||
jobs:
|
||||
minecraft_server:
|
||||
docker:
|
||||
- image: circleci/buildpack-deps:19.10
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker
|
||||
- run:
|
||||
name: Build image
|
||||
command: docker build -t mc:$CIRCLE_BUILD_NUM .
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build:
|
||||
jobs:
|
||||
- minecraft_server:
|
||||
filters:
|
||||
branches:
|
||||
ignore:
|
||||
- armv7
|
||||
- multiarch
|
||||
@@ -1,5 +1,6 @@
|
||||
data
|
||||
testdata
|
||||
examples
|
||||
k8s-examples
|
||||
.idea
|
||||
.git
|
||||
.git
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
[start-*]
|
||||
indent_size = 2
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
end_of_line = lf
|
||||
|
||||
51
.github/workflows/main.yml
vendored
Normal file
51
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Build and Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- openj9
|
||||
- openj9-nightly
|
||||
- adopt11
|
||||
- adopt13
|
||||
- adopt14
|
||||
- adopt15
|
||||
tags:
|
||||
- "[0-9]+.[0-9]+.[0-9]+"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-openj9"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-openj9-nightly"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-adopt11"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-adopt13"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-adopt14"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-adopt15"
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
tests/test.sh
|
||||
build:
|
||||
needs:
|
||||
- test
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Build and push Docker images
|
||||
uses: docker/build-push-action@v1.1.0
|
||||
with:
|
||||
repository: itzg/minecraft-server
|
||||
username: ${{ secrets.DOCKER_USER }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
tag_with_ref: true
|
||||
tag_with_sha: false
|
||||
cache_froms: itzg/minecraft-server:latest
|
||||
add_git_labels: true
|
||||
labels: org.opencontainers.image.url=https://github.com/itzg/docker-minecraft-server,org.opencontainers.image.documentation=https://github.com/itzg/docker-minecraft-server
|
||||
push: true
|
||||
16
.github/workflows/pr.yml
vendored
Normal file
16
.github/workflows/pr.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
name: Validate PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
tests/test.sh
|
||||
74
DEVELOPMENT.md
Normal file
74
DEVELOPMENT.md
Normal file
@@ -0,0 +1,74 @@
|
||||
## Adding a server type
|
||||
|
||||
Adding a new server `TYPE` can vary due to the complexity of obtaining and configuring each type; however, the addition of any server type includes at least the following steps:
|
||||
|
||||
1. Copy an existing "start-deploy*" script, such as [start-deployMohist](start-deployMohist) and rename it accordingly making sure to retain the "start-deploy" prefix
|
||||
2. Modify the type-specific behavior between the "start-utils" preamble and the hand-off to `start-finalSetupWorld` at the end of the script
|
||||
3. Develop and test the changes using the [iterative process described below](#iterative-script-development)
|
||||
4. Add a case-entry to the `case "${TYPE^^}"` in [start-configuration](start-configuration)
|
||||
5. Add a section to the [README](README.md). It is recommended to copy-modify an existing section to retain a similar wording and level of detail
|
||||
6. [Submit a pull request](https://github.com/itzg/docker-minecraft-server/pulls)
|
||||
|
||||
## Iterative script development
|
||||
|
||||
Individual scripts can be iteratively developed, debugged, and tested using the following procedure.
|
||||
|
||||
First, build a baseline of the image to include the packages needed by existing or new scripts:
|
||||
|
||||
```shell script
|
||||
docker build -t mc-dev .
|
||||
```
|
||||
|
||||
Using the baseline image, an interactive container can be started to iteratively run the scripts to be developed. By attaching the current workspace directory, you can use the local editor of your choice to iteratively modify scripts while using the container to run them.
|
||||
|
||||
```shell script
|
||||
docker run -it --rm -v ${PWD}:/scripts -e SCRIPTS=/scripts/ --entrypoint bash mc-dev
|
||||
```
|
||||
|
||||
From within the container you can run individual scripts via the attached `/scripts/` path; however, be sure to set any environment variables expected by the scripts by either `export`ing them manually:
|
||||
|
||||
```shell script
|
||||
export VANILLA_VERSION=1.12.2
|
||||
/scripts/start-magma
|
||||
```
|
||||
|
||||
...or pre-pending script execution:
|
||||
|
||||
```shell script
|
||||
VANILLA_VERSION=1.12.2 /scripts/start-magma
|
||||
```
|
||||
|
||||
> NOTE: You may want to temporarily add an `exit` statement near the end of your script to isolate execution to just the script you're developing.
|
||||
|
||||
## Multi-base-image variants
|
||||
|
||||
Several base-image variants are maintained in order to offer choices in JDK provider and version. The variants are maintained in their respective branches:
|
||||
- openj9
|
||||
- openj9-nightly
|
||||
- adopt11
|
||||
- adopt13
|
||||
- multiarch
|
||||
|
||||
The [docker-versions-create.sh](docker-versions-create.sh) script is configured with the branches to maintain and is used to merge changes from the master branch into the mulit-base variant branches. The script also manages git tagging the master branch along with the merged branches. So a typical use of the script would be like:
|
||||
|
||||
```shell script
|
||||
./docker-versions-create.sh -s -t 1.2.0
|
||||
```
|
||||
|
||||
> Most often the major version will be bumped unless a bug or hotfix needs to be published in which case the patch version should be incremented.
|
||||
|
||||
> The build and publishing of those branches and their tags is currently performed within Docker Hub.
|
||||
|
||||
## multiarch support
|
||||
|
||||
The [multiarch branch](https://github.com/itzg/docker-minecraft-server/tree/multiarch) supports running the image on amd64, arm64, and armv7 (aka RaspberryPi). Unlike the mainline branches, it is based on Ubuntu 18.04 since the openjdk package provided by Ubuntu includes full JIT support on all of the processor types.
|
||||
|
||||
The multiarch images are built and published by [a Github action](https://github.com/itzg/docker-minecraft-server/actions?query=workflow%3A%22Build+and+publish+multiarch%22), which [is configured in that branch](https://github.com/itzg/docker-minecraft-server/blob/multiarch/.github/workflows/build-multiarch.yml).
|
||||
|
||||
## Generating release notes
|
||||
|
||||
The following git command can be used to provide the bulk of release notes content:
|
||||
|
||||
```shell script
|
||||
git log --invert-grep --grep "^ci:" --grep "^misc:" --grep "^docs:" --pretty="- %s" 1.1.0..1.2.0
|
||||
```
|
||||
32
Dockerfile
32
Dockerfile
@@ -1,6 +1,9 @@
|
||||
FROM openjdk:8u212-jre-alpine
|
||||
FROM adoptopenjdk/openjdk13:alpine-jre
|
||||
|
||||
LABEL maintainer "itzg"
|
||||
LABEL org.opencontainers.image.authors="Geoff Bourne <itzgeoff@gmail.com>"
|
||||
|
||||
# upgrade all packages since alpine jre8 base image tops out at 8u212
|
||||
RUN apk -U --no-cache upgrade
|
||||
|
||||
RUN apk add --no-cache -U \
|
||||
openssl \
|
||||
@@ -15,15 +18,18 @@ RUN apk add --no-cache -U \
|
||||
mysql-client \
|
||||
tzdata \
|
||||
rsync \
|
||||
nano
|
||||
|
||||
HEALTHCHECK --start-period=1m CMD mc-monitor status --host localhost --port $SERVER_PORT
|
||||
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
|
||||
|
||||
EXPOSE 25565 25575
|
||||
|
||||
# hook into docker BuildKit --platform support
|
||||
@@ -49,7 +55,7 @@ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
|
||||
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
|
||||
|
||||
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
|
||||
--var version=1.4.3 --var app=mc-server-runner --file {{.app}} \
|
||||
--var version=1.5.0 --var app=mc-server-runner --file {{.app}} \
|
||||
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
|
||||
|
||||
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
|
||||
@@ -63,14 +69,20 @@ COPY server.properties /tmp/server.properties
|
||||
COPY log4j2.xml /tmp/log4j2.xml
|
||||
WORKDIR /data
|
||||
|
||||
ENTRYPOINT [ "/start" ]
|
||||
|
||||
ENV UID=1000 GID=1000 \
|
||||
JVM_XX_OPTS="-XX:+UseG1GC" MEMORY="1G" \
|
||||
MEMORY="1G" \
|
||||
TYPE=VANILLA VERSION=LATEST FORGEVERSION=RECOMMENDED SPONGEBRANCH=STABLE SPONGEVERSION= FABRICVERSION=LATEST LEVEL=world \
|
||||
PVP=true DIFFICULTY=easy ENABLE_RCON=true RCON_PORT=25575 RCON_PASSWORD=minecraft \
|
||||
LEVEL_TYPE=DEFAULT SERVER_PORT=25565 ONLINE_MODE=TRUE SERVER_NAME="Dedicated Server" \
|
||||
REPLACE_ENV_VARIABLES="FALSE" ENV_VARIABLE_PREFIX="CFG_"
|
||||
ENABLE_AUTOPAUSE=false AUTOPAUSE_TIMEOUT_EST=3600 AUTOPAUSE_TIMEOUT_KN=120 AUTOPAUSE_TIMEOUT_INIT=600 AUTOPAUSE_PERIOD=10
|
||||
|
||||
COPY start* /
|
||||
COPY health.sh /
|
||||
ADD files/autopause /autopause
|
||||
|
||||
RUN dos2unix /start* && chmod +x /start*
|
||||
RUN dos2unix /health.sh && chmod +x /health.sh
|
||||
RUN dos2unix /autopause/* && chmod +x /autopause/*.sh
|
||||
|
||||
ENTRYPOINT [ "/start" ]
|
||||
HEALTHCHECK --start-period=1m CMD /health.sh
|
||||
|
||||
406
README.md
406
README.md
@@ -1,20 +1,17 @@
|
||||
[](https://hub.docker.com/r/itzg/minecraft-server/)
|
||||
[](https://hub.docker.com/r/itzg/minecraft-server/)
|
||||
[](https://github.com/itzg/docker-minecraft-server/issues)
|
||||
[](https://discord.gg/DXfKpjB)
|
||||
[](https://discord.gg/DXfKpjB)
|
||||
[](https://github.com/itzg/docker-minecraft-server/actions)
|
||||
[](https://www.buymeacoffee.com/itzg)
|
||||
|
||||
This docker image provides a Minecraft Server that will automatically download the latest stable
|
||||
version at startup. You can also run/upgrade to any specific version or the
|
||||
latest snapshot. See the _Versions_ section below for more information.
|
||||
|
||||
[](https://github.com/itzg/docker-minecraft-server/blob/master/README.md)
|
||||
|
||||
[Full docs available in Github](https://github.com/itzg/docker-minecraft-server/blob/master/README.md)
|
||||
|
||||
To simply use the latest stable version, run
|
||||
|
||||
docker run -d -p 25565:25565 --name mc itzg/minecraft-server
|
||||
docker run -d -p 25565:25565 --name mc -e EULA=TRUE itzg/minecraft-server
|
||||
|
||||
where the standard server port, 25565, will be exposed on your host machine.
|
||||
|
||||
@@ -38,6 +35,7 @@ With that you can easily view the logs, stop, or re-start the container:
|
||||
docker stop mc
|
||||
|
||||
docker start mc
|
||||
*Be sure to always include `-e EULA=TRUE` in your commands, as Mojang/Microsoft requires EULA acceptance.*
|
||||
|
||||
## Looking for a Bedrock Dedicated Server
|
||||
|
||||
@@ -149,6 +147,7 @@ To use a different version of Java, please use a docker tag to run your Minecraf
|
||||
| Tag name | Description | Linux |
|
||||
| -------------- | ------------------------------------------- | ------------ |
|
||||
| latest | **Default**. Uses Java version 8 update 212 | Alpine Linux |
|
||||
| adopt14 | Uses Java version 14 latest update | Alpine Linux |
|
||||
| adopt13 | Uses Java version 13 latest update | Alpine Linux |
|
||||
| adopt11 | Uses Java version 11 latest update | Alpine Linux |
|
||||
| openj9 | Uses Eclipse OpenJ9 JVM | Alpine Linux |
|
||||
@@ -179,6 +178,44 @@ You can also query the container's health in a script friendly way:
|
||||
healthy
|
||||
```
|
||||
|
||||
Some orchestration systems, such as Portainer, don't allow for disabling the default `HEALTHCHECK` declared by this image. In those cases you can approximate the disabling of healthchecks by setting the environment variable `DISABLE_HEALTHCHECK` to `true`.
|
||||
|
||||
## Autopause (experimental)
|
||||
|
||||
### Description
|
||||
|
||||
> EXPERIMENTAL: this feature only works with default bridge networking using official Docker distributions. Host networking and container management software, such as Portainer, and NAS solutions do not seem to provide compatible networking.
|
||||
|
||||
There are various bug reports on [Mojang](https://bugs.mojang.com) about high CPU usage of servers with newer versions, even with few or no clients connected (e.g. [this one](https://bugs.mojang.com/browse/MC-149018), in fact the functionality is based on [this comment in the thread](https://bugs.mojang.com/browse/MC-149018?focusedCommentId=593606&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-593606)).
|
||||
|
||||
An autopause functionality has been added to this image to monitor whether clients are connected to the server. If for a specified time no client is connected, the Java process is stopped. When knocking on the server port (e.g. by the ingame Multiplayer server overview), the process is resumed. The experience for the client does not change.
|
||||
|
||||
Of course, even loaded chunks are not ticked when the process is stopped.
|
||||
|
||||
From the server's point of view, the pausing causes a single tick to take as long as the process is stopped, so the server watchdog might intervene after the process is continued, possibly forcing a container restart. To prevent this, ensure that the `max-tick-time` in the `server.properties` file is set correctly.
|
||||
|
||||
On startup the `server.properties` file is checked and, if applicable, a warning is printed to the terminal. When the server is created (no data available in the persistent directory), the properties file is created with the Watchdog disabled.
|
||||
|
||||
A starting, example compose file has been provided in [examples/docker-compose-autopause.yml](examples/docker-compose-autopause.yml).
|
||||
|
||||
### Enabling Autopause
|
||||
|
||||
Enable the Autopause functionality by setting:
|
||||
|
||||
```
|
||||
-e ENABLE_AUTOPAUSE=TRUE
|
||||
```
|
||||
|
||||
There are 4 more environment variables that define the behaviour:
|
||||
* `AUTOPAUSE_TIMEOUT_EST`, default `3600` (seconds)
|
||||
describes the time between the last client disconnect and the pausing of the process (read as timeout established)
|
||||
* `AUTOPAUSE_TIMEOUT_INIT`, default `600` (seconds)
|
||||
describes the time between server start and the pausing of the process, when no client connects inbetween (read as timeout initialized)
|
||||
* `AUTOPAUSE_TIMEOUT_KN`, default `120` (seconds)
|
||||
describes the time between knocking of the port (e.g. by the main menu ping) and the pausing of the process, when no client connects inbetween (read as timeout knocked)
|
||||
* `AUTOPAUSE_PERIOD`, default `10` (seconds)
|
||||
describes period of the daemonized state machine, that handles the pausing of the process (resuming is done independently)
|
||||
|
||||
## Deployment Templates and Examples
|
||||
|
||||
### Helm Charts
|
||||
@@ -190,13 +227,17 @@ healthy
|
||||
|
||||
The [examples directory](https://github.com/itzg/docker-minecraft-server/tree/master/examples) also provides examples of deploying the [itzg/minecraft-server](https://hub.docker.com/r/itzg/minecraft-server/) Docker image.
|
||||
|
||||
### Amazon Web Services (AWS) Deployment
|
||||
|
||||
If you're looking for a simple way to deploy this to the Amazon Web Services Cloud, check out the [Minecraft Server Deployment (CloudFormation) repository](https://github.com/vatertime/minecraft-spot-pricing). This repository contains a CloudFormation template that will get you up and running in AWS in a matter of minutes. Optionally it uses Spot Pricing so the server is very cheap, and you can easily turn it off when not in use.
|
||||
|
||||
## Running a Forge Server
|
||||
|
||||
Enable Forge server mode by adding a `-e TYPE=FORGE` to your command-line.
|
||||
By default the container will run the `RECOMMENDED` version of [Forge server](http://www.minecraftforge.net/wiki/)
|
||||
but you can also choose to run a specific version with `-e FORGEVERSION=10.13.4.1448`.
|
||||
|
||||
$ docker run -d -v /path/on/host:/data -e VERSION=1.7.10 \
|
||||
$ docker run -d -v /path/on/host:/data \
|
||||
-e TYPE=FORGE -e FORGEVERSION=10.13.4.1448 \
|
||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
||||
|
||||
@@ -234,10 +275,20 @@ the `/path/on/host` folder contents look like:
|
||||
├── ops.json
|
||||
├── server.properties
|
||||
├── whitelist.json
|
||||
├── worlds
|
||||
│ └── ... PLACE MAPS IN THEIR OWN FOLDERS HERE ...
|
||||
└── ...
|
||||
```
|
||||
|
||||
If you add mods while the container is running, you'll need to restart it to pick those
|
||||
Providing a presistent `/data` mount is a good idea, both to persist the game world and to allow for the manual configuration which is sometimes needed.
|
||||
|
||||
For instance, imagine a scenario when the initial launch has completed, but you now want to change the worldmap for your server.
|
||||
|
||||
Assuming you have a shared directory to your container, you can then (after first launch) drag and drop your premade maps or worlds into the `\worlds\` directory. **Note:** each world should be placed in its own folder under the `\worlds\` directory.
|
||||
|
||||
Once your maps are in the proper path, you can then specify which map the server uses by changing the `level-name` value in `server.properties` to match the name of your map.
|
||||
|
||||
If you add mods or make changes to `server.properties` while the container is running, you'll need to restart it to pick those
|
||||
up:
|
||||
|
||||
docker stop mc
|
||||
@@ -250,12 +301,18 @@ or downloading a world with the `WORLD` option.
|
||||
|
||||
There are two additional volumes that can be mounted; `/mods` and `/config`.
|
||||
Any files in either of these filesystems will be copied over to the main
|
||||
`/data` filesystem before starting Minecraft.
|
||||
`/data` filesystem before starting Minecraft. If you want old mods to be removed as the `/mods` content is updated, then add `-e REMOVE_OLD_MODS=TRUE`. If you are running a `BUKKIT` distribution this will affect all files inside the `plugins/` directory. You can fine tune the removal process by specifing the `REMOVE_OLD_MODS_INCLUDE` and `REMOVE_OLD_MODS_EXCLUDE` variables. By default everything will be removed. You can also specify the `REMOVE_OLD_MODS_DEPTH` (default 16) variable to only delete files up to a certain level.
|
||||
|
||||
> For example: `-e REMOVE_OLD_MODS=TRUE -e REMOVE_OLD_MODS_INCLUDE="*.jar" -e REMOVE_OLD_MODS_DEPTH=1` will remove all old jar files that are directly inside the `plugins/` or `mods/` directory.
|
||||
|
||||
This works well if you want to have a common set of modules in a separate
|
||||
location, but still have multiple worlds with different server requirements
|
||||
in either persistent volumes or a downloadable archive.
|
||||
|
||||
You can specify the destination of the configs that are located inside the `/config` mount by setting the `COPY_CONFIG_DEST` variable. The configs are copied recursivly to the `/data/config` directory by default. If a file was updated directly inside the `/data/*` directoy and is newer than the file in the `/config/*` mount it will not be overriden.
|
||||
|
||||
> For example: `-v ./config:/config -e COPY_CONFIG_DEST=/data` will allow you to copy over your `bukkit.yml` and so on directly into the server directory.
|
||||
|
||||
### Replacing variables inside configs
|
||||
|
||||
Sometimes you have mods or plugins that require configuration information that is only available at runtime.
|
||||
@@ -273,7 +330,7 @@ defined environment variables. Variables that you want to replace need to be wra
|
||||
inside `${YOUR_VARIABLE}` curly brackets and prefixed with a dollar sign. This is the regular
|
||||
syntax for enviromment variables inside strings or config files.
|
||||
|
||||
Optionally you can also define a prefix to only match predefined enviroment variables.
|
||||
Optionally you can also define a prefix to only match predefined environment variables.
|
||||
|
||||
`ENV_VARIABLE_PREFIX="CFG_"` <-- this is the default prefix
|
||||
|
||||
@@ -289,6 +346,14 @@ There are some limitations to what characters you can use.
|
||||
Variables will be replaced in files with the following extensions:
|
||||
`.yml`, `.yaml`, `.txt`, `.cfg`, `.conf`, `.properties`.
|
||||
|
||||
Specific files can be excluded by listing their name (without path) in the variable `REPLACE_ENV_VARIABLES_EXCLUDES`.
|
||||
|
||||
Paths can be excluded by listing them in the variable `REPLACE_ENV_VARIABLES_EXCLUDE_PATHS`. Path
|
||||
excludes are recursive. Here is an example:
|
||||
```
|
||||
REPLACE_ENV_VARIABLES_EXCLUDE_PATHS="/data/plugins/Essentials/userdata /data/plugins/MyPlugin"
|
||||
```
|
||||
|
||||
Here is a full example where we want to replace values inside a `database.yml`.
|
||||
|
||||
```yml
|
||||
@@ -347,13 +412,13 @@ secrets:
|
||||
The content of `db_password`:
|
||||
|
||||
ug23u3bg39o-ogADSs
|
||||
|
||||
|
||||
## Running a Bukkit/Spigot server
|
||||
|
||||
Enable Bukkit/Spigot server mode by adding a `-e TYPE=BUKKIT -e VERSION=1.8` or `-e TYPE=SPIGOT -e VERSION=1.8` to your command-line.
|
||||
Enable Bukkit/Spigot server mode by adding a `-e TYPE=BUKKIT` or `-e TYPE=SPIGOT` to your command-line.
|
||||
|
||||
docker run -d -v /path/on/host:/data \
|
||||
-e TYPE=SPIGOT -e VERSION=1.8 \
|
||||
-e TYPE=SPIGOT \
|
||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
||||
|
||||
If you are hosting your own copy of Bukkit/Spigot you can override the download URLs with:
|
||||
@@ -363,117 +428,27 @@ If you are hosting your own copy of Bukkit/Spigot you can override the download
|
||||
|
||||
You can build spigot from source by adding `-e BUILD_FROM_SOURCE=true`
|
||||
|
||||
**NOTE: to avoid pegging the CPU when running Spigot,** you will need to
|
||||
pass `--noconsole` at the very end of the command line and not use `-it`. For example,
|
||||
If you have attached a host directory to the `/data` volume, then you can install plugins within the `plugins` subdirectory. You can also [attach a `/plugins` volume](#deploying-plugins-from-attached-volume). If you add plugins while the container is running, you'll need to restart it to pick those up.
|
||||
|
||||
docker run -d -v /path/on/host:/data \
|
||||
-e TYPE=SPIGOT -e VERSION=1.8 \
|
||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server --noconsole
|
||||
## Running a Paper server
|
||||
|
||||
You can install Bukkit plugins in two ways...
|
||||
|
||||
### Using the /data volume
|
||||
|
||||
This is the easiest way if you are using a persistent `/data` mount.
|
||||
|
||||
To do this, you will need to attach the container's `/data` directory
|
||||
(see "Attaching data directory to host filesystem”).
|
||||
Then, you can add plugins to the `/path/on/host/plugins` folder you chose. From the example above,
|
||||
the `/path/on/host` folder contents look like:
|
||||
|
||||
```
|
||||
/path/on/host
|
||||
├── plugins
|
||||
│ └── ... INSTALL PLUGINS HERE ...
|
||||
├── ops.json
|
||||
├── server.properties
|
||||
├── whitelist.json
|
||||
└── ...
|
||||
```
|
||||
|
||||
If you add plugins while the container is running, you'll need to restart it to pick those
|
||||
up:
|
||||
|
||||
docker stop mc
|
||||
docker start mc
|
||||
|
||||
### Using separate mounts
|
||||
|
||||
This is the easiest way if you are using an ephemeral `/data` filesystem,
|
||||
or downloading a world with the `WORLD` option.
|
||||
|
||||
There is one additional volume that can be mounted; `/plugins`.
|
||||
Any files in this filesystem will be copied over to the main
|
||||
`/data/plugins` filesystem before starting Minecraft.
|
||||
|
||||
This works well if you want to have a common set of plugins in a separate
|
||||
location, but still have multiple worlds with different server requirements
|
||||
in either persistent volumes or a downloadable archive.
|
||||
|
||||
## Running a PaperSpigot server
|
||||
|
||||
Enable PaperSpigot server mode by adding a `-e TYPE=PAPER -e VERSION=1.9.4` to your command-line.
|
||||
Enable Paper server mode by adding a `-e TYPE=PAPER` to your command-line.
|
||||
|
||||
By default the container will run the latest build of [Paper server](https://papermc.io/downloads)
|
||||
but you can also choose to run a specific build with `-e PAPERBUILD=205`.
|
||||
|
||||
docker run -d -v /path/on/host:/data \
|
||||
-e TYPE=PAPER -e VERSION=1.9.4 \
|
||||
-e TYPE=PAPER \
|
||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
||||
|
||||
**NOTE: to avoid pegging the CPU when running PaperSpigot,** you will need to
|
||||
pass `--noconsole` at the very end of the command line and not use `-it`. For example,
|
||||
|
||||
docker run -d -v /path/on/host:/data \
|
||||
-e TYPE=PAPER -e VERSION=1.9.4 \
|
||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server --noconsole
|
||||
|
||||
If you are hosting your own copy of PaperSpigot you can override the download URL with:
|
||||
If you are hosting your own copy of Paper you can override the download URL with:
|
||||
|
||||
- -e PAPER_DOWNLOAD_URL=<url>
|
||||
|
||||
You can install Bukkit plugins in two ways...
|
||||
|
||||
An example compose file is provided at
|
||||
[examples/docker-compose-paper.yml](examples/docker-compose-paper.yml).
|
||||
|
||||
### Using the /data volume
|
||||
|
||||
This is the easiest way if you are using a persistent `/data` mount.
|
||||
|
||||
To do this, you will need to attach the container's `/data` directory
|
||||
(see "Attaching data directory to host filesystem”).
|
||||
Then, you can add plugins to the `/path/on/host/plugins` folder you chose. From the example above,
|
||||
the `/path/on/host` folder contents look like:
|
||||
|
||||
```
|
||||
/path/on/host
|
||||
├── plugins
|
||||
│ └── ... INSTALL PLUGINS HERE ...
|
||||
├── ops.json
|
||||
├── server.properties
|
||||
├── whitelist.json
|
||||
└── ...
|
||||
```
|
||||
|
||||
If you add plugins while the container is running, you'll need to restart it to pick those
|
||||
up:
|
||||
|
||||
docker stop mc
|
||||
docker start mc
|
||||
|
||||
### Using separate mounts
|
||||
|
||||
This is the easiest way if you are using an ephemeral `/data` filesystem,
|
||||
or downloading a world with the `WORLD` option.
|
||||
|
||||
There is one additional volume that can be mounted; `/plugins`.
|
||||
Any files in this filesystem will be copied over to the main
|
||||
`/data/plugins` filesystem before starting Minecraft.
|
||||
|
||||
This works well if you want to have a common set of plugins in a separate
|
||||
location, but still have multiple worlds with different server requirements
|
||||
in either persistent volumes or a downloadable archive.
|
||||
If you have attached a host directory to the `/data` volume, then you can install plugins via the `plugins` subdirectory. You can also [attach a `/plugins` volume](#deploying-plugins-from-attached-volume). If you add plugins while the container is running, you'll need to restart it to pick those up.
|
||||
|
||||
## Running a Tuinity server
|
||||
|
||||
@@ -491,20 +466,64 @@ A [Magma](https://magmafoundation.org/) server, which is a combination of Forge
|
||||
|
||||
> **NOTE** there are limited base versions supported, so you will also need to set `VERSION`, such as "1.12.2"
|
||||
|
||||
## Running a Server with a Feed-The-Beast (FTB) / CurseForge modpack
|
||||
|
||||
Enable this server mode by adding a `-e TYPE=FTB` or `-e TYPE=CURSEFORGE` to your command-line,
|
||||
## Running a Mohist server
|
||||
|
||||
A [Mohist](https://github.com/Mohist-Community/Mohist) server can be used with
|
||||
|
||||
-e TYPE=MOHIST
|
||||
|
||||
> **NOTE** there are limited base versions supported, so you will also need to set `VERSION`, such as "1.12.2"
|
||||
|
||||
|
||||
## Running a Catserver type server
|
||||
|
||||
A [Catserver](http://catserver.moe/) type server can be used with
|
||||
|
||||
-e TYPE=CATSERVER
|
||||
|
||||
> **NOTE** Catserver only provides a single release stream, so `VERSION` is ignored
|
||||
|
||||
## Running a server with a Feed the Beast modpack
|
||||
|
||||
> **NOTE** requires `itzg/minecraft-server:multiarch` image
|
||||
|
||||
[Feed the Beast application](https://www.feed-the-beast.com/) modpacks are supported by using `-e TYPE=FTBA` (**note** the "A" at the end of the type). This server type will automatically take care of downloading and installing the modpack and appropriate version of Forge, so the `VERSION` does not need to be specified.
|
||||
|
||||
### Environment Variables:
|
||||
- `FTB_MODPACK_ID`: **required**, the numerical ID of the modpack to install. The ID can be located by [finding the modpack](https://www.feed-the-beast.com/modpack) and using the "ID" displayed next to the name
|
||||
- `FTB_MODPACK_VERSION_ID`: optional, the numerical Id of the version to install. If not specified, the latest version will be installed. The "Version ID" can be obtained by drilling into the Versions tab and clicking a specific version.
|
||||
|
||||
### Upgrading
|
||||
|
||||
If a specific `FTB_MODPACK_VERSION_ID` was not specified, simply restart the container to pick up the newest modpack version. If using a specific version ID, recreate the container with the new version ID.
|
||||
|
||||
### Example
|
||||
|
||||
The following example runs the latest version of [FTB Presents Direwolf20 1.12](https://ftb.neptunepowered.org/pack/ftb-presents-direwolf20-1-12/):
|
||||
|
||||
```
|
||||
docker run -d --name mc-ftb -e EULA=TRUE \
|
||||
-e TYPE=FTBA -e FTB_MODPACK_ID=31 \
|
||||
-p 25565:25565 \
|
||||
itzg/minecraft-server:multiarch
|
||||
```
|
||||
|
||||
> Normally you will also add `-v` volume for `/data` since the mods and config are installed there along with world data.
|
||||
|
||||
## Running a server with a CurseForge modpack
|
||||
|
||||
Enable this server mode by adding `-e TYPE=CURSEFORGE` to your command-line,
|
||||
but note the following additional steps needed...
|
||||
|
||||
You need to specify a modpack to run, using the `FTB_SERVER_MOD` or `CF_SERVER_MOD` environment
|
||||
variable. An FTB/CurseForge server modpack is available together with its respective
|
||||
client modpack on <https://www.feed-the-beast.com> under "Additional Files." Similar you can
|
||||
locate the modpacks for CurseForge at <https://www.curseforge.com/minecraft/modpacks> .
|
||||
You need to specify a modpack to run, using the `CF_SERVER_MOD` environment
|
||||
variable. A CurseForge server modpack is available together with its respective
|
||||
client modpack at <https://www.curseforge.com/minecraft/modpacks> .
|
||||
|
||||
Now you can add a `-e FTB_SERVER_MOD=name_of_modpack.zip` to your command-line.
|
||||
Now you can add a `-e CF_SERVER_MOD=name_of_modpack.zip` to your command-line.
|
||||
|
||||
docker run -d -v /path/on/host:/data -e TYPE=FTB \
|
||||
-e FTB_SERVER_MOD=FTBPresentsSkyfactory3Server_3.0.6.zip \
|
||||
docker run -d -v /path/on/host:/data -e TYPE=CURSEFORGE \
|
||||
-e CF_SERVER_MOD=SkyFactory_4_Server_4.1.0.zip \
|
||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
||||
|
||||
If you want to keep the pre-download modpacks separate from your data directory,
|
||||
@@ -512,10 +531,14 @@ then you can attach another volume at a path of your choosing and reference that
|
||||
The following example uses `/modpacks` as the container path as the pre-download area:
|
||||
|
||||
docker run -d -v /path/on/host:/data -v /path/to/modpacks:/modpacks \
|
||||
-e TYPE=FTB \
|
||||
-e FTB_SERVER_MOD=/modpacks/FTBPresentsSkyfactory3Server_3.0.6.zip \
|
||||
-e TYPE=CURSEFORGE \
|
||||
-e CF_SERVER_MOD=/modpacks/SkyFactory_4_Server_4.1.0.zip \
|
||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
||||
|
||||
#### Buggy start scripts
|
||||
|
||||
Some modpacks have buggy or overly complex start scripts. You can avoid using the bundled start script and use this image's standard server-starting logic by adding `-e USE_MODPACK_START_SCRIPT=false`.
|
||||
|
||||
### Fixing "unable to launch forgemodloader"
|
||||
|
||||
If your server's modpack fails to load with an error [like this](https://support.feed-the-beast.com/t/cant-start-crashlanding-server-unable-to-launch-forgemodloader/6028/2):
|
||||
@@ -526,42 +549,6 @@ then you apply a workaround by adding this to the run invocation:
|
||||
|
||||
-e FTB_LEGACYJAVAFIXER=true
|
||||
|
||||
### Using a client-made curseforge modpack
|
||||
|
||||
If you use something like CurseForge, you may end up creating/using modpacks that do not
|
||||
contain server mod jars. Instead, the CurseForge setup has `manifest.json` files, which
|
||||
will show up under `/data/FeedTheBeast/manifest.json`.
|
||||
|
||||
To use these packs you will need to:
|
||||
|
||||
- Specify the manifest location with env var `MANIFEST=/data/FeedTheBeast/manifest`
|
||||
- Pick a relevant ServerStart.sh and potentially settings.cfg and put them in `/data/FeedTheBeast`
|
||||
|
||||
An example of the latter would be to use <https://github.com/AllTheMods/Server-Scripts>
|
||||
There, you'll find that all you have to do is put `ServerStart.sh` and `settings.cfg` into
|
||||
`/data/FeedTheBeast`, taking care to update `settings.cfg` to specify your desired version
|
||||
of minecraft and forge. You can do this in the cli with something like:
|
||||
|
||||
```
|
||||
$ wget https://raw.githubusercontent.com/AllTheMods/Server-Scripts/master/ServerStart.sh
|
||||
$ wget https://raw.githubusercontent.com/AllTheMods/Server-Scripts/master/settings.cfg
|
||||
$ vim settings.cfg #update the forge version to the one you want. Your manifest.json will have it
|
||||
$ chmod +x ServerStart.sh
|
||||
$ docker run -itd --name derpcraft \
|
||||
-e MANIFEST=/data/FeedTheBeast/manifest.json \
|
||||
-v $PWD/ServerStart.sh:/data/FeedTheBeast/ServerStart.sh \
|
||||
-v $PWD/settings.cfg:/data/FeedTheBeast/settings.cfg \
|
||||
-e VERSION=1.12.2\
|
||||
-e TYPE=CURSEFORGE\
|
||||
-e CF_SERVER_MOD=https://minecraft.curseforge.com/projects/your_amazing_modpack/files/2670435/download\
|
||||
-p 25565:25565\
|
||||
-e EULA=TRUE\
|
||||
--restart=always\
|
||||
itzg/minecraft-server
|
||||
```
|
||||
|
||||
Note the `CF_SERVER_MOD` env var should match the server version of the modpack you are targeting.
|
||||
|
||||
## Running a SpongeVanilla server
|
||||
|
||||
Enable SpongeVanilla server mode by adding a `-e TYPE=SPONGEVANILLA` to your command-line.
|
||||
@@ -579,29 +566,31 @@ Just change it with `SPONGEBRANCH`, such as:
|
||||
|
||||
## Running a Fabric Server
|
||||
|
||||
Enable Fabric server mode by adding a `-e TYPE=FABRIC` to your command-line.
|
||||
By default the container will run the latest version of [Fabric server](http://fabricmc.net/use/)
|
||||
but you can also choose to run a specific version with `-e FABRICVERSION=0.5.0.32`.
|
||||
Enable [Fabric server](http://fabricmc.net/use/) mode by adding a `-e TYPE=FABRIC` to your command-line. By default, the container will run the latest version, but you can also choose to run a specific version with `VERSION`.
|
||||
|
||||
$ docker run -d -v /path/on/host:/data -e VERSION=1.14.3 \
|
||||
-e TYPE=FABRIC -e FABRICVERSION=0.5.0.32 \
|
||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
||||
```
|
||||
docker run -d -v /path/on/host:/data \
|
||||
-e TYPE=FABRIC \
|
||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
||||
```
|
||||
|
||||
To use a pre-downloaded Fabric installer, place it in the attached `/data` directory and
|
||||
specify the name of the installer file with `FABRIC_INSTALLER`, such as:
|
||||
A specific installer version can be requested using `FABRIC_INSTALLER_VERSION`.
|
||||
|
||||
$ docker run -d -v /path/on/host:/data ... \
|
||||
-e FABRIC_INSTALLER=fabric-installer-0.5.0.32.jar ...
|
||||
To use a pre-downloaded Fabric installer, place it in a directory attached into the container, such as the `/data` volume and specify the name of the installer file with `FABRIC_INSTALLER`, such as:
|
||||
|
||||
To download a Fabric installer from a custom location, such as your own file repository, specify
|
||||
the URL with `FABRIC_INSTALLER_URL`, such as:
|
||||
```
|
||||
docker run -d -v /path/on/host:/data ... \
|
||||
-e FABRIC_INSTALLER=fabric-installer-0.5.0.32.jar ...
|
||||
```
|
||||
|
||||
$ docker run -d -v /path/on/host:/data ... \
|
||||
-e FORGE_INSTALLER_URL=http://HOST/fabric-installer-0.5.0.32.jar ...
|
||||
To download a Fabric installer from a custom location, such as your own file repository, specify the URL with `FABRIC_INSTALLER_URL`, such as:
|
||||
|
||||
In both of the cases above, there is no need for the `VERSION` or `FABRICVERSION` variables.
|
||||
```
|
||||
docker run -d -v /path/on/host:/data ... \
|
||||
-e FABRIC_INSTALLER_URL=http://HOST/fabric-installer-0.5.0.32.jar ...
|
||||
```
|
||||
|
||||
In order to add mods, you have two options.
|
||||
In order to add mods, you have two options:
|
||||
|
||||
### Using the /data volume
|
||||
|
||||
@@ -643,6 +632,12 @@ This works well if you want to have a common set of modules in a separate
|
||||
location, but still have multiple worlds with different server requirements
|
||||
in either persistent volumes or a downloadable archive.
|
||||
|
||||
## Deploying plugins from attached volume
|
||||
|
||||
There is one additional volume that can be mounted; `/plugins`. Any files in this filesystem will be copied over to the main `/data/plugins` filesystem before starting Minecraft. Set `PLUGINS_SYNC_UPDATE=false` if you want files from `/plugins` to take precedence over newer files in `/data/plugins`.
|
||||
|
||||
This works well if you want to have a common set of plugins in a separate location, but still have multiple worlds with different server requirements in either persistent volumes or a downloadable archive.
|
||||
|
||||
## Running with a custom server JAR
|
||||
|
||||
If you would like to run a custom server JAR, set `-e TYPE=CUSTOM` and pass the custom server
|
||||
@@ -662,7 +657,7 @@ For example, with PaperSpigot, it would look something like this:
|
||||
|
||||
```
|
||||
docker run -d -v /path/on/host:/data \
|
||||
-e TYPE=PAPER -e VERSION=1.14.1 -e FORCE_REDOWNLOAD=true \
|
||||
-e TYPE=PAPER -e FORCE_REDOWNLOAD=true \
|
||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
||||
```
|
||||
|
||||
@@ -720,9 +715,13 @@ The server name (e.g. for bungeecord) can be set like:
|
||||
|
||||
### Server port
|
||||
|
||||
The server port can be set like:
|
||||
> **WARNING:** only change this value if you know what you're doing. It is only needed when using host networking and it is rare that host networking should be used. Use `-p` port mappings instead.
|
||||
|
||||
docker run -d -e SERVER_PORT=25565 ...
|
||||
If you must, the server port can be set like:
|
||||
|
||||
docker run -d -e SERVER_PORT=25566 ...
|
||||
|
||||
**however**, be sure to change your port mapping accordingly and be prepared for some features to break.
|
||||
|
||||
### Difficulty
|
||||
|
||||
@@ -944,7 +943,7 @@ For example (just the `-e` bits):
|
||||
|
||||
You can set a link to a custom resource pack and set it's checksum using the `RESOURCE_PACK` and `RESOURCE_PACK_SHA1` options respectively, the default is blank:
|
||||
|
||||
docker run -d -e 'RESROUCE_PACK=http\://link.com/to/pack.zip?\=1' -e 'RESOURCE_PACK_SHA1=d5db29cd03a2ed055086cef9c31c252b4587d6d0'
|
||||
docker run -d -e 'RESOURCE_PACK=http\://link.com/to/pack.zip?\=1' -e 'RESOURCE_PACK_SHA1=d5db29cd03a2ed055086cef9c31c252b4587d6d0'
|
||||
|
||||
**NOTE:** `:` and `=` must be escaped using `\`. The checksum plain-text hexadecimal.
|
||||
|
||||
@@ -960,30 +959,19 @@ where the default is "world":
|
||||
|
||||
### Downloadable world
|
||||
|
||||
Instead of mounting the `/data` volume, you can instead specify the URL of
|
||||
a ZIP file containing an archived world. This will be downloaded, and
|
||||
unpacked in the `/data` directory; if it does not contain a subdirectory
|
||||
called `world/` then it will be searched for a file `level.dat` and the
|
||||
containing subdirectory renamed to `world`. This means that most of the
|
||||
archived Minecraft worlds downloadable from the Internet will already be in
|
||||
the correct format.
|
||||
|
||||
The ZIP file may also contain a `server.properties` file and `modules`
|
||||
directory, if required.
|
||||
Instead of mounting the `/data` volume, you can instead specify the URL of a ZIP file containing an archived world. It will be searched for a file `level.dat` and the containing subdirectory moved to the directory named by `$LEVEL`. This means that most of the archived Minecraft worlds downloadable from the Internet will already be in the correct format.
|
||||
|
||||
docker run -d -e WORLD=http://www.example.com/worlds/MySave.zip ...
|
||||
|
||||
**NOTE:** Unless you also mount `/data` as an external volume, this world
|
||||
will be deleted when the container is deleted.
|
||||
|
||||
**NOTE:** This URL must be accessible from inside the container. Therefore,
|
||||
you should use an IP address or a globally resolveable FQDN, or else the
|
||||
you should use an IP address or a globally resolvable FQDN, or else the
|
||||
name of a linked container.
|
||||
|
||||
**NOTE:** If the archive contains more than one `level.dat`, then the one to select can be picked with `WORLD_INDEX`, which defaults to 1.
|
||||
|
||||
### Cloning world from a container path
|
||||
|
||||
The `WORLD` option can also be used to reference a directory that will be used
|
||||
as a source to clone the world directory.
|
||||
The `WORLD` option can also be used to reference a directory or zip file that will be used as a source to clone or unzip the world directory.
|
||||
|
||||
For example, the following would initially clone the world's content
|
||||
from `/worlds/basic`. Also notice in the example that you can use a
|
||||
@@ -993,6 +981,9 @@ read-only volume attachment to ensure the clone source remains pristine.
|
||||
docker run ... -v $HOME/worlds:/worlds:ro -e WORLD=/worlds/basic
|
||||
```
|
||||
|
||||
### Overwrite world on start
|
||||
The world will only be downloaded or copied if it doesn't exist already. Set `FORCE_WORLD_COPY=TRUE` to force overwrite the world on every server start.
|
||||
|
||||
### Downloadable mod/plugin pack for Forge, Bukkit, and Spigot Servers
|
||||
|
||||
Like the `WORLD` option above, you can specify the URL of a "mod pack"
|
||||
@@ -1036,9 +1027,21 @@ Allows users to use flight on your server while in Survival mode, if they have a
|
||||
|
||||
### Other server property mappings
|
||||
|
||||
Environment Variable | Server Property
|
||||
---------------------|-----------------
|
||||
PLAYER_IDLE_TIMEOUT | player-idle-timeout
|
||||
| Environment Variable | Server Property |
|
||||
| --------------------------------- | --------------------------------- |
|
||||
| PLAYER_IDLE_TIMEOUT | player-idle-timeout |
|
||||
| BROADCAST_CONSOLE_TO_OPS | broadcast-console-to-ops |
|
||||
| BROADCAST_RCON_TO_OPS | broadcast-rcon-to-ops |
|
||||
| ENABLE_JMX | enable-jmx-monitoring |
|
||||
| SYNC_CHUNK_WRITES | sync-chunk-writes |
|
||||
| ENABLE_STATUS | enable-status |
|
||||
| ENTITY_BROADCAST_RANGE_PERCENTAGE | entity-broadcast-range-percentage |
|
||||
| FUNCTION_PERMISSION_LEVEL | function-permission-level |
|
||||
| NETWORK_COMPRESSION_THRESHOLD | network-compression-threshold |
|
||||
| OP_PERMISSION_LEVEL | op-permission-level |
|
||||
| PREVENT_PROXY_CONNECTIONS | prevent-proxy-connections |
|
||||
| USE_NATIVE_TRANSPORT | use-native-transport |
|
||||
| ENFORCE_WHITELIST | enforce-whitelist |
|
||||
|
||||
## Miscellaneous Options
|
||||
|
||||
@@ -1098,25 +1101,28 @@ Large page support can also be enabled by adding
|
||||
### HTTP Proxy
|
||||
|
||||
You may configure the use of an HTTP/HTTPS proxy by passing the proxy's URL via the `PROXY`
|
||||
environment variable. In [the example compose file](docker-compose-proxied.yml) it references
|
||||
environment variable. In [the example compose file](examples/docker-compose-proxied.yml) it references
|
||||
a companion squid proxy by setting the equivalent of
|
||||
|
||||
-e PROXY=proxy:3128
|
||||
|
||||
### Using "noconsole" option
|
||||
|
||||
Some older versions of Spigot required `--noconsole` to be passed when detaching stdin. You can
|
||||
pass that at the end of `docker run` after the image name or set `-e CONSOLE=FALSE`.
|
||||
Some older versions (pre-1.14) of Spigot required `--noconsole` to be passed when detaching stdin, which can be done by setting `-e CONSOLE=FALSE`.
|
||||
|
||||
### Explicitly disable GUI
|
||||
|
||||
Some older servers get confused and think that the GUI interface is enabled. You can explicitly
|
||||
disable that by passing `-e GUI=FALSE`.
|
||||
|
||||
### Stop Duration
|
||||
|
||||
When the container is signalled to stop, the Minecraft process wrapper will attempt to send a "stop" command via RCON or console and waits for the process to gracefully finish. By defaul it waits 60 seconds, but that duration can be configured by setting the environment variable `STOP_DURATION` to the number of seconds.
|
||||
|
||||
## Running on RaspberryPi
|
||||
|
||||
To run this image on a RaspberryPi 3 B+, 4, or newer, use the image tag
|
||||
|
||||
itzg/minecraft-server:armv7
|
||||
itzg/minecraft-server:multiarch
|
||||
|
||||
> NOTE: you may need to lower the memory allocation, such as `-e MEMORY=750m`
|
||||
> NOTE: you may need to lower the memory allocation, such as `-e MEMORY=750m`
|
||||
@@ -1,34 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# manually purge any pre-existing manifest list
|
||||
# since docker manifest command lacks a "remove" operation
|
||||
rm -rf ~/.docker/manifests/docker.io_itzg_minecraft-server-multiarch
|
||||
|
||||
export DOCKER_BUILDKIT=1
|
||||
|
||||
docker build --platform linux/arm64 -t itzg/minecraft-server:arm64 .
|
||||
docker push itzg/minecraft-server:arm64
|
||||
|
||||
armv7tag=armv7-buildkit
|
||||
armv7workDir=/tmp/armv7-$$
|
||||
git worktree add $armv7workDir armv7
|
||||
# sub-shell for build of armv7
|
||||
(
|
||||
cd $armv7workDir
|
||||
docker build --platform linux/arm/v7 -t itzg/minecraft-server:$armv7tag .
|
||||
docker push itzg/minecraft-server:$armv7tag
|
||||
)
|
||||
git worktree remove $armv7workDir
|
||||
|
||||
docker pull itzg/minecraft-server
|
||||
# use the rpi build one for now since armv7-buildkit is giving ABI mismatch on curl
|
||||
docker pull itzg/minecraft-server:armv7
|
||||
|
||||
docker manifest create itzg/minecraft-server:multiarch \
|
||||
itzg/minecraft-server \
|
||||
itzg/minecraft-server:armv7 \
|
||||
itzg/minecraft-server:arm64
|
||||
|
||||
docker manifest inspect itzg/minecraft-server:multiarch
|
||||
|
||||
docker manifest push -p itzg/minecraft-server:multiarch
|
||||
@@ -1,18 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
manifest="itzg/minecraft-server:multiarch"
|
||||
|
||||
for t in latest rpi3 aarch64; do
|
||||
docker pull itzg/minecraft-server:$t
|
||||
done
|
||||
|
||||
docker manifest create --amend ${manifest} \
|
||||
itzg/minecraft-server:aarch64 \
|
||||
itzg/minecraft-server:latest \
|
||||
itzg/minecraft-server:rpi3
|
||||
|
||||
docker manifest annotate --os linux --arch amd64 ${manifest} itzg/minecraft-server:latest
|
||||
docker manifest annotate --os linux --arch arm64 ${manifest} itzg/minecraft-server:aarch64
|
||||
docker manifest annotate --os linux --arch arm --variant v7 ${manifest} itzg/minecraft-server:rpi3
|
||||
|
||||
docker manifest push ${manifest}
|
||||
@@ -10,19 +10,7 @@ services:
|
||||
- "mc:/data"
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
CONSOLE: "false"
|
||||
ENABLE_RCON: "true"
|
||||
RCON_PASSWORD: "testing"
|
||||
RCON_PORT: 28016
|
||||
restart: always
|
||||
rcon:
|
||||
image: itzg/rcon
|
||||
ports:
|
||||
- "4326:4326"
|
||||
- "4327:4327"
|
||||
volumes:
|
||||
- "rcon:/opt/rcon-web-admin/db"
|
||||
|
||||
volumes:
|
||||
mc:
|
||||
rcon:
|
||||
mc: {}
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
#set -x
|
||||
# Use this variable to indicate a list of branches that docker hub is watching
|
||||
branches_list=('openj9' 'openj9-nightly' 'adopt11' 'adopt13' 'multiarch' 'armv7')
|
||||
branches_list=('openj9' 'openj9-nightly' 'adopt11' 'adopt13' 'adopt14' 'adopt15' 'multiarch' 'multiarch-latest')
|
||||
|
||||
function TrapExit {
|
||||
echo "Checking out back in master"
|
||||
@@ -10,12 +10,32 @@ function TrapExit {
|
||||
|
||||
batchMode=false
|
||||
|
||||
while getopts "b" arg
|
||||
while getopts "hbt:s" arg
|
||||
do
|
||||
case $arg in
|
||||
b)
|
||||
batchMode=true
|
||||
;;
|
||||
t)
|
||||
tag=${OPTARG}
|
||||
;;
|
||||
s)
|
||||
tagArgs="-s -m 'Signed during docker-versions-create"
|
||||
;;
|
||||
h)
|
||||
echo "
|
||||
Usage $0 [options]
|
||||
|
||||
Options:
|
||||
-b enable batch mode, which avoids interactive prompts and causes script to fail immediately
|
||||
when any merge fails
|
||||
-t TAG tag and push the current revision on master with the given tag
|
||||
and apply respective tags to each branch
|
||||
-s enable signed tags
|
||||
-h display this help and exit
|
||||
"
|
||||
exit
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported arg $arg"
|
||||
exit 2
|
||||
@@ -34,6 +54,10 @@ test -d ./.git || { echo ".git folder was not found. Please start this script fr
|
||||
git checkout master
|
||||
git pull --all || { echo "Can't pull the repo!"; \
|
||||
exit 1; }
|
||||
if [[ $tag ]]; then
|
||||
git tag $tag
|
||||
git push origin $tag
|
||||
fi
|
||||
|
||||
git_branches=$(git branch -a)
|
||||
|
||||
@@ -57,6 +81,10 @@ for branch in "${branches_list[@]}"; do
|
||||
git commit -m "Auto merge branch with master" -a
|
||||
# push may fail if remote doesn't have this branch yet. In this case - sending branch
|
||||
git push || git push -u origin "$branch" || { echo "Can't push changes to the origin."; exit 1; }
|
||||
if [[ $tag ]]; then
|
||||
git tag "$tag-$branch"
|
||||
git push origin "$tag-$branch"
|
||||
fi
|
||||
elif ${batchMode}; then
|
||||
status=$?
|
||||
echo "Git merge failed in batch mode"
|
||||
|
||||
BIN
docs/start-script-flow.drawio.png
Normal file
BIN
docs/start-script-flow.drawio.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
18
examples/docker-compose-autopause.yml
Normal file
18
examples/docker-compose-autopause.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
minecraft:
|
||||
image: itzg/minecraft-server
|
||||
ports:
|
||||
- "25565:25565"
|
||||
volumes:
|
||||
- "mc:/data"
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
ENABLE_AUTOPAUSE: "TRUE"
|
||||
OVERRIDE_SERVER_PROPERTIES: "TRUE"
|
||||
MAX_TICK_TIME: "-1"
|
||||
restart: always
|
||||
|
||||
volumes:
|
||||
mc: {}
|
||||
@@ -3,9 +3,11 @@ version: '3.2'
|
||||
services:
|
||||
mc:
|
||||
image: itzg/minecraft-server
|
||||
volumes:
|
||||
- ./modpacks:/modpacks:ro
|
||||
environment:
|
||||
EULA: "true"
|
||||
TYPE: FTB
|
||||
FTB_SERVER_MOD: https://minecraft.curseforge.com/projects/all-the-mods-expert-remastered/files/2493900/download
|
||||
TYPE: CURSEFORGE
|
||||
CF_SERVER_MOD: /modpacks/SkyFactory_4_Server_4.1.0.zip
|
||||
ports:
|
||||
- 25565:25565
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
version: '3.2'
|
||||
|
||||
services:
|
||||
mc:
|
||||
image: itzg/minecraft-server
|
||||
environment:
|
||||
EULA: "true"
|
||||
TYPE: FTB
|
||||
FTB_SERVER_MOD: https://www.feed-the-beast.com/projects/ftb-presents-skyfactory-3/files/2481284
|
||||
ports:
|
||||
- 25565:25565
|
||||
volumes:
|
||||
- mc-ftb:/data
|
||||
|
||||
volumes:
|
||||
mc-ftb:
|
||||
23
examples/docker-compose-ftba.yml
Normal file
23
examples/docker-compose-ftba.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
version: "3.7"
|
||||
|
||||
services:
|
||||
mc:
|
||||
# FTBA support is only available in multiarch image tag
|
||||
image: itzg/minecraft-server:multiarch
|
||||
ports:
|
||||
# expose the Minecraft server port outside of container
|
||||
- 25565:25565
|
||||
environment:
|
||||
# REQUIRED for all types
|
||||
EULA: "TRUE"
|
||||
# Set server type (vs the default of vanilla)
|
||||
TYPE: FTBA
|
||||
# Use Pack ID from https://ftb.neptunepowered.org/pack/ftb-presents-direwolf20-1-12/
|
||||
FTB_MODPACK_ID: "31"
|
||||
volumes:
|
||||
# use a named, managed volume for data volume
|
||||
- mc_ftb:/data
|
||||
|
||||
volumes:
|
||||
# declared the named volume, but use default/local storage engine
|
||||
mc_ftb: {}
|
||||
@@ -7,11 +7,12 @@ services:
|
||||
EULA: "true"
|
||||
TYPE: PAPER
|
||||
VERSION: 1.9.4
|
||||
command: --noconsole
|
||||
# needed for Paper versions before 1.14
|
||||
CONSOLE: "false"
|
||||
ports:
|
||||
- 25565:25565
|
||||
volumes:
|
||||
- mc-paper:/data
|
||||
|
||||
volumes:
|
||||
mc-paper:
|
||||
mc-paper:
|
||||
|
||||
11
examples/docker-compose-world-download.yml
Normal file
11
examples/docker-compose-world-download.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: "3.7"
|
||||
|
||||
services:
|
||||
mc:
|
||||
image: itzg/minecraft-server
|
||||
ports:
|
||||
- 25565:25565
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
VERSION: 1.7.2
|
||||
WORLD: https://www.minecraftmaps.com/survival-maps/cube-survival/download
|
||||
1
examples/modpacks/.gitignore
vendored
Normal file
1
examples/modpacks/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.zip
|
||||
3
examples/modpacks/README.md
Normal file
3
examples/modpacks/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Please server [modpacks downloaded from CurseForge](https://www.curseforge.com/minecraft/modpacks) in this directory.
|
||||
|
||||
The example [`docker-compose-curseforge.yml`](../docker-compose-curseforge.yml) references a modpack downloaded from <https://www.curseforge.com/minecraft/modpacks/skyfactory-4/files/2787018>.
|
||||
97
files/autopause/autopause-daemon.sh
Normal file
97
files/autopause/autopause-daemon.sh
Normal file
@@ -0,0 +1,97 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /autopause/autopause-fcns.sh
|
||||
|
||||
. /start-utils
|
||||
|
||||
sudo /usr/sbin/knockd -c /tmp/knockd-config.cfg -d
|
||||
if [ $? -ne 0 ] ; then
|
||||
while :
|
||||
do
|
||||
if [[ -n $(ps -o comm | grep java) ]] ; then
|
||||
break
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
logAutopause "Failed to start knockd daemon."
|
||||
logAutopause "Possible cause: docker's host network mode."
|
||||
logAutopause "Recreate without host mode or disable autopause functionality."
|
||||
logAutopause "Stopping server."
|
||||
killall -SIGTERM java
|
||||
exit 1
|
||||
fi
|
||||
|
||||
STATE=INIT
|
||||
|
||||
while :
|
||||
do
|
||||
case X$STATE in
|
||||
XINIT)
|
||||
# Server startup
|
||||
if mc_server_listening ; then
|
||||
TIME_THRESH=$(($(current_uptime)+$AUTOPAUSE_TIMEOUT_INIT))
|
||||
logAutopause "MC Server listening for connections - stopping in $AUTOPAUSE_TIMEOUT_INIT seconds"
|
||||
STATE=K
|
||||
fi
|
||||
;;
|
||||
XK)
|
||||
# Knocked
|
||||
if java_clients_connected ; then
|
||||
logAutopause "Client connected - waiting for disconnect"
|
||||
STATE=E
|
||||
else
|
||||
if [[ $(current_uptime) -ge $TIME_THRESH ]] ; then
|
||||
logAutopause "No client connected since startup / knocked - stopping"
|
||||
/autopause/pause.sh
|
||||
STATE=S
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
XE)
|
||||
# Established
|
||||
if ! java_clients_connected ; then
|
||||
TIME_THRESH=$(($(current_uptime)+$AUTOPAUSE_TIMEOUT_EST))
|
||||
logAutopause "All clients disconnected - stopping in $AUTOPAUSE_TIMEOUT_EST seconds"
|
||||
STATE=I
|
||||
fi
|
||||
;;
|
||||
XI)
|
||||
# Idle
|
||||
if java_clients_connected ; then
|
||||
logAutopause "Client reconnected - waiting for disconnect"
|
||||
STATE=E
|
||||
else
|
||||
if [[ $(current_uptime) -ge $TIME_THRESH ]] ; then
|
||||
logAutopause "No client reconnected - stopping"
|
||||
/autopause/pause.sh
|
||||
STATE=S
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
XS)
|
||||
# Stopped
|
||||
if rcon_client_exists ; then
|
||||
/autopause/resume.sh
|
||||
fi
|
||||
if java_running ; then
|
||||
if java_clients_connected ; then
|
||||
logAutopause "Client connected - waiting for disconnect"
|
||||
STATE=E
|
||||
else
|
||||
TIME_THRESH=$(($(current_uptime)+$AUTOPAUSE_TIMEOUT_KN))
|
||||
logAutopause "Server was knocked - waiting for clients or timeout"
|
||||
STATE=K
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
logAutopause "Error: invalid state: $STATE"
|
||||
;;
|
||||
esac
|
||||
if [[ "$STATE" == "S" ]] ; then
|
||||
# before rcon times out
|
||||
sleep 2
|
||||
else
|
||||
sleep $AUTOPAUSE_PERIOD
|
||||
fi
|
||||
done
|
||||
38
files/autopause/autopause-fcns.sh
Normal file
38
files/autopause/autopause-fcns.sh
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
current_uptime() {
|
||||
echo $(awk '{print $1}' /proc/uptime | cut -d . -f 1)
|
||||
}
|
||||
|
||||
java_running() {
|
||||
[[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]]
|
||||
}
|
||||
|
||||
rcon_client_exists() {
|
||||
[[ -n "$(ps -a -o comm | grep 'rcon-cli')" ]]
|
||||
}
|
||||
|
||||
mc_server_listening() {
|
||||
[[ -n $(netstat -tln | grep -e "0.0.0.0:$SERVER_PORT" -e ":::$SERVER_PORT" | grep LISTEN) ]]
|
||||
}
|
||||
|
||||
java_clients_connected() {
|
||||
local connections
|
||||
connections=$(netstat -tn | grep ":$SERVER_PORT" | grep ESTABLISHED)
|
||||
if [[ -z "$connections" ]] ; then
|
||||
return 1
|
||||
fi
|
||||
IFS=$'\n'
|
||||
connections=($connections)
|
||||
unset IFS
|
||||
# check that at least one external address is not localhost
|
||||
# remember, that the host network mode does not work with autopause because of the knockd utility
|
||||
for (( i=0; i<${#connections[@]}; i++ ))
|
||||
do
|
||||
if [[ ! $(echo "${connections[$i]}" | awk '{print $5}') =~ ^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$ ]] ; then
|
||||
# not localhost
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
12
files/autopause/knockd-config.cfg
Normal file
12
files/autopause/knockd-config.cfg
Normal file
@@ -0,0 +1,12 @@
|
||||
[options]
|
||||
logfile = /dev/null
|
||||
[unpauseMCServer-server]
|
||||
sequence = 25565
|
||||
seq_timeout = 1
|
||||
command = /sbin/su-exec minecraft:minecraft /autopause/resume.sh
|
||||
tcpflags = syn
|
||||
[unpauseMCServer-rcon]
|
||||
sequence = 25575
|
||||
seq_timeout = 1
|
||||
command = /sbin/su-exec minecraft:minecraft /autopause/resume.sh
|
||||
tcpflags = syn
|
||||
21
files/autopause/pause.sh
Executable file
21
files/autopause/pause.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
|
||||
if [[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]] ; then
|
||||
# save world
|
||||
rcon-cli save-all >/dev/null
|
||||
|
||||
# wait until mc-monitor is no longer connected to the server
|
||||
while :
|
||||
do
|
||||
if [[ -z "$(netstat -nt | grep "127.0.0.1:$SERVER_PORT" | grep 'ESTABLISHED')" ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
# finally pause the process
|
||||
logAutopauseAction "Pausing Java process"
|
||||
killall -q -STOP java
|
||||
fi
|
||||
8
files/autopause/resume.sh
Executable file
8
files/autopause/resume.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
|
||||
if [[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^T.*$ ]] ; then
|
||||
logAutopauseAction "Knocked, resuming Java process"
|
||||
killall -q -CONT java
|
||||
fi
|
||||
2
files/sudoers-mc
Normal file
2
files/sudoers-mc
Normal file
@@ -0,0 +1,2 @@
|
||||
%minecraft ALL=(ALL) NOPASSWD:/usr/bin/killall
|
||||
%minecraft ALL=(ALL) NOPASSWD:/usr/sbin/knockd
|
||||
14
health.sh
Normal file
14
health.sh
Normal file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
if isTrue "${DISABLE_HEALTHCHECK}"; then
|
||||
echo "Healthcheck disabled"
|
||||
exit 0
|
||||
elif isTrue "${ENABLE_AUTOPAUSE}" && [[ "$( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }')" =~ ^T.*$ ]]; then
|
||||
echo "Java process suspended by Autopause function"
|
||||
exit 0
|
||||
else
|
||||
mc-monitor status --host localhost --port $SERVER_PORT
|
||||
exit $?
|
||||
fi
|
||||
@@ -37,3 +37,15 @@ motd=A Minecraft Server powered by Docker
|
||||
generator-settings=
|
||||
rcon.password=
|
||||
max-world-size=29999984
|
||||
broadcast-console-to-ops=true
|
||||
broadcast-rcon-to-ops=true
|
||||
enable-jmx-monitoring=false
|
||||
sync-chunk-writes=true
|
||||
enable-status=true
|
||||
entity-broadcast-range-percentage=100
|
||||
function-permission-level=2
|
||||
network-compression-threshold=256
|
||||
op-permission-level=4
|
||||
prevent-proxy-connections=false
|
||||
use-native-transport=true
|
||||
enforce-whitelist=false
|
||||
|
||||
6
start
6
start
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
umask 0002
|
||||
chmod g+w /data
|
||||
@@ -40,7 +40,7 @@ if [ $(id -u) = 0 ]; then
|
||||
echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||
fi
|
||||
|
||||
exec su-exec ${runAsUser}:${runAsGroup} /start-configuration $@
|
||||
exec su-exec ${runAsUser}:${runAsGroup} ${SCRIPTS:-/}start-configuration $@
|
||||
else
|
||||
exec /start-configuration $@
|
||||
exec ${SCRIPTS:-/}start-configuration $@
|
||||
fi
|
||||
|
||||
62
start-autopause
Executable file
62
start-autopause
Executable file
@@ -0,0 +1,62 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
log "Autopause functionality enabled"
|
||||
|
||||
cp /autopause/knockd-config.cfg /tmp/knockd-config.cfg
|
||||
|
||||
# update server port to listen to
|
||||
regseq="^\s*sequence\s*=\s*$SERVER_PORT\s*$"
|
||||
linenum=$(grep -nm1 sequence /tmp/knockd-config.cfg | cut -d : -f 1 | tail -n1)
|
||||
if ! [[ $(awk "NR==$linenum" /tmp/knockd-config.cfg) =~ $regseq ]]; then
|
||||
sed -i "${linenum}s/sequence.*/sequence = $SERVER_PORT/" /tmp/knockd-config.cfg
|
||||
log "Updated server port in knockd config"
|
||||
fi
|
||||
# update rcon port to listen to
|
||||
regseq="^\s*sequence\s*=\s*$RCON_PORT\s*$"
|
||||
linenum=$(grep -nm2 sequence /tmp/knockd-config.cfg | cut -d : -f 1 | tail -n1)
|
||||
if ! [[ $(awk "NR==$linenum" /tmp/knockd-config.cfg) =~ $regseq ]]; then
|
||||
sed -i "${linenum}s/sequence.*/sequence = $RCON_PORT/" /tmp/knockd-config.cfg
|
||||
log "Updated rcon port in knockd config"
|
||||
fi
|
||||
|
||||
if ! [[ $AUTOPAUSE_PERIOD =~ ^[0-9]+$ ]]; then
|
||||
AUTOPAUSE_PERIOD=10
|
||||
export AUTOPAUSE_PERIOD
|
||||
log "Warning: AUTOPAUSE_PERIOD is not numeric, set to 10 (seconds)"
|
||||
fi
|
||||
if [ "$AUTOPAUSE_PERIOD" -eq "0" ] ; then
|
||||
AUTOPAUSE_PERIOD=10
|
||||
export AUTOPAUSE_PERIOD
|
||||
log "Warning: AUTOPAUSE_PERIOD must not be 0, set to 10 (seconds)"
|
||||
fi
|
||||
if ! [[ $AUTOPAUSE_TIMEOUT_KN =~ ^[0-9]+$ ]] ; then
|
||||
AUTOPAUSE_TIMEOUT_KN=120
|
||||
export AUTOPAUSE_TIMEOUT_KN
|
||||
log "Warning: AUTOPAUSE_TIMEOUT_KN is not numeric, set to 120 (seconds)"
|
||||
fi
|
||||
if ! [[ $AUTOPAUSE_TIMEOUT_EST =~ ^[0-9]+$ ]] ; then
|
||||
AUTOPAUSE_TIMEOUT_EST=3600
|
||||
export AUTOPAUSE_TIMEOUT_EST
|
||||
log "Warning: AUTOPAUSE_TIMEOUT_EST is not numeric, set to 3600 (seconds)"
|
||||
fi
|
||||
if ! [[ $AUTOPAUSE_TIMEOUT_INIT =~ ^[0-9]+$ ]] ; then
|
||||
AUTOPAUSE_TIMEOUT_INIT=600
|
||||
export AUTOPAUSE_TIMEOUT_INIT
|
||||
log "Warning: AUTOPAUSE_TIMEOUT_INIT is not numeric, set to 600 (seconds)"
|
||||
fi
|
||||
|
||||
if [[ -n $MAX_TICK_TIME ]] ; then
|
||||
log "Warning: MAX_TICK_TIME is non-default, for autopause to work properly, this check should be disabled (-1 for versions >= 1.8.1)"
|
||||
else
|
||||
if versionLessThan 1.8.1; then
|
||||
# 10 years
|
||||
MAX_TICK_TIME=315360000000
|
||||
else
|
||||
MAX_TICK_TIME=-1
|
||||
fi
|
||||
export MAX_TICK_TIME
|
||||
fi
|
||||
|
||||
/autopause/autopause-daemon.sh &
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
@@ -8,8 +8,7 @@ shopt -s nullglob
|
||||
export HOME=/data
|
||||
|
||||
if [ ! -e /data/eula.txt ]; then
|
||||
EULA="${EULA,,}"
|
||||
if [ "$EULA" != "true" ]; then
|
||||
if ! isTrue "$EULA"; then
|
||||
log ""
|
||||
log "Please accept the Minecraft EULA at"
|
||||
log " https://account.mojang.com/documents/minecraft_eula"
|
||||
@@ -19,12 +18,7 @@ if [ ! -e /data/eula.txt ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "# Generated via Docker on $(date)" > /data/eula.txt
|
||||
|
||||
if ! echo "eula=$EULA" >> /data/eula.txt; then
|
||||
log "ERROR: unable to write eula to /data. Please make sure attached directory is writable by uid=${UID}"
|
||||
exit 2
|
||||
fi
|
||||
writeEula
|
||||
fi
|
||||
|
||||
|
||||
@@ -40,10 +34,27 @@ rm /data/.verify_access || true
|
||||
if [[ $PROXY ]]; then
|
||||
export http_proxy="$PROXY"
|
||||
export https_proxy="$PROXY"
|
||||
export JAVA_TOOL_OPTIONS+="-Djava.net.useSystemProxies=true"
|
||||
log "INFO: Giving proxy time to startup..."
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
if [[ $RCON_PASSWORD_FILE ]]; then
|
||||
log ""
|
||||
if [ ! -e ${RCON_PASSWORD_FILE} ]; then
|
||||
log "Initial RCON password file ${RCON_PASSWORD_FILE} does not seems to exist."
|
||||
log "Please ensure your configuration."
|
||||
log "If you are using Docker Secrets feature, please check this for further information: "
|
||||
log " https://docs.docker.com/engine/swarm/secrets"
|
||||
log ""
|
||||
exit 1
|
||||
else
|
||||
RCON_PASSWORD=$(cat ${RCON_PASSWORD_FILE})
|
||||
export RCON_PASSWORD
|
||||
fi
|
||||
log ""
|
||||
fi
|
||||
|
||||
export SERVER_PROPERTIES=/data/server.properties
|
||||
export VERSIONS_JSON=https://launchermeta.mojang.com/mc/game/version_manifest.json
|
||||
|
||||
@@ -54,11 +65,8 @@ case "X$VERSION" in
|
||||
XSNAPSHOT|Xsnapshot)
|
||||
VANILLA_VERSION=$(curl -fsSL $VERSIONS_JSON | jq -r '.latest.snapshot')
|
||||
;;
|
||||
X[1-9]*)
|
||||
VANILLA_VERSION=$VERSION
|
||||
;;
|
||||
*)
|
||||
VANILLA_VERSION=$(curl -fsSL $VERSIONS_JSON | jq -r '.latest.release')
|
||||
VANILLA_VERSION=$VERSION
|
||||
;;
|
||||
esac
|
||||
export VANILLA_VERSION
|
||||
@@ -68,55 +76,69 @@ cd /data || exit 1
|
||||
|
||||
export ORIGINAL_TYPE=${TYPE^^}
|
||||
|
||||
if isTrue "${ENABLE_AUTOPAUSE}"; then
|
||||
${SCRIPTS:-/}start-autopause
|
||||
fi
|
||||
|
||||
log "Resolving type given ${TYPE}"
|
||||
case "${TYPE^^}" in
|
||||
*BUKKIT|SPIGOT)
|
||||
exec /start-deployBukkitSpigot "$@"
|
||||
exec ${SCRIPTS:-/}start-deployBukkitSpigot "$@"
|
||||
;;
|
||||
|
||||
PAPER)
|
||||
exec /start-deployPaper "$@"
|
||||
exec ${SCRIPTS:-/}start-deployPaper "$@"
|
||||
;;
|
||||
|
||||
TUINITY)
|
||||
exec /start-deployTuinity "$@"
|
||||
exec ${SCRIPTS:-/}start-deployTuinity "$@"
|
||||
;;
|
||||
|
||||
FORGE)
|
||||
exec /start-deployForge "$@"
|
||||
exec ${SCRIPTS:-/}start-deployForge "$@"
|
||||
;;
|
||||
|
||||
FABRIC)
|
||||
exec /start-deployFabric "$@"
|
||||
exec ${SCRIPTS:-/}start-deployFabric "$@"
|
||||
;;
|
||||
|
||||
FTB|CURSEFORGE)
|
||||
exec /start-deployFTB "$@"
|
||||
exec ${SCRIPTS:-/}start-deployCF "$@"
|
||||
;;
|
||||
|
||||
VANILLA)
|
||||
exec /start-deployVanilla "$@"
|
||||
exec ${SCRIPTS:-/}start-deployVanilla "$@"
|
||||
;;
|
||||
|
||||
SPONGEVANILLA)
|
||||
exec /start-deploySpongeVanilla "$@"
|
||||
exec ${SCRIPTS:-/}start-deploySpongeVanilla "$@"
|
||||
;;
|
||||
|
||||
CUSTOM)
|
||||
exec /start-deployCustom "$@"
|
||||
exec ${SCRIPTS:-/}start-deployCustom "$@"
|
||||
;;
|
||||
|
||||
CURSE_INSTANCE)
|
||||
exec /start-validateCurseInstance "$@"
|
||||
exec ${SCRIPTS:-/}start-validateCurseInstance "$@"
|
||||
;;
|
||||
|
||||
MAGMA)
|
||||
exec /start-magma "$@"
|
||||
exec ${SCRIPTS:-/}start-deployMagma "$@"
|
||||
;;
|
||||
|
||||
MOHIST)
|
||||
exec ${SCRIPTS:-/}start-deployMohist "$@"
|
||||
;;
|
||||
|
||||
CATSERVER)
|
||||
exec ${SCRIPTS:-/}start-deployCatserver "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
log "Invalid type: '$TYPE'"
|
||||
log "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTB, CURSEFORGE, SPONGEVANILLA"
|
||||
log "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTBA (multiarch-only),"
|
||||
log " CURSE_INSTANCE, CURSEFORGE, SPONGEVANILLA,"
|
||||
log " CUSTOM, MAGMA, MOHIST, CATSERVER"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
|
||||
set -e
|
||||
|
||||
@@ -58,12 +59,24 @@ function downloadSpigot {
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ ${VERSION^^} = LATEST ]]; then
|
||||
VANILLA_VERSION=$(restify https://getbukkit.org/download/spigot --attribute='property=og:title' | jq -r '.[0] | .attributes | select(.property == "og:title") | .content | split(" ") | .[-1]')
|
||||
fi
|
||||
|
||||
if [[ -z $downloadUrl ]]; then
|
||||
downloadUrl="https://cdn.getbukkit.org/${getbukkitFlavor}/${getbukkitFlavor}-${VANILLA_VERSION}.jar"
|
||||
fi
|
||||
|
||||
setServerVar
|
||||
if [ -f $SERVER ]; then
|
||||
# tell curl to only download when newer
|
||||
curlArgs="-z $SERVER"
|
||||
fi
|
||||
if isDebugging; then
|
||||
curlArgs="$curlArgs -v"
|
||||
fi
|
||||
log "Downloading $match from $downloadUrl ..."
|
||||
curl -fsSL -o $SERVER "$downloadUrl"
|
||||
curl -fsSL -o $SERVER $curlArgs "$downloadUrl"
|
||||
if [[ $? != 0 || $(grep -c "DOCTYPE html" $SERVER) != 0 ]]; then
|
||||
cat <<EOF
|
||||
|
||||
@@ -72,6 +85,13 @@ ERROR: failed to download from $downloadUrl
|
||||
exact version, such as 1.4.6-R0.4-SNAPSHOT or 1.8-R0.1-SNAPSHOT-LATEST
|
||||
|
||||
EOF
|
||||
|
||||
if isDebugging && [[ $(grep -c "DOCTYPE html" $SERVER) != 0 ]]; then
|
||||
cat $SERVER
|
||||
fi
|
||||
|
||||
# remove invalid download
|
||||
rm $SERVER
|
||||
exit 3
|
||||
fi
|
||||
|
||||
@@ -79,22 +99,24 @@ EOF
|
||||
export JVM_OPTS
|
||||
}
|
||||
|
||||
function setServerVar {
|
||||
case "$TYPE" in
|
||||
*BUKKIT|*bukkit)
|
||||
export SERVER=craftbukkit_server-${VANILLA_VERSION}.jar
|
||||
;;
|
||||
*)
|
||||
export SERVER=spigot_server-${VANILLA_VERSION}.jar
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
case "$TYPE" in
|
||||
*BUKKIT|*bukkit)
|
||||
export SERVER=craftbukkit_server-${VANILLA_VERSION}.jar
|
||||
;;
|
||||
*)
|
||||
export SERVER=spigot_server-${VANILLA_VERSION}.jar
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ ! -f $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
if isTrue "$BUILD_SPIGOT_FROM_SOURCE" || isTrue "$BUILD_FROM_SOURCE"; then
|
||||
buildSpigotFromSource
|
||||
else
|
||||
downloadSpigot
|
||||
fi
|
||||
if isTrue "$BUILD_SPIGOT_FROM_SOURCE" || isTrue "$BUILD_FROM_SOURCE"; then
|
||||
setServerVar
|
||||
if [ ! -f $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
buildSpigotFromSource
|
||||
fi
|
||||
else
|
||||
downloadSpigot
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for operations below
|
||||
@@ -102,4 +124,4 @@ export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
# Continue to Final Setup
|
||||
exec /start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -1,22 +1,82 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
set -e
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
|
||||
export FTB_BASE_DIR=/data/FeedTheBeast
|
||||
legacyJavaFixerUrl=http://ftb.cursecdn.com/FTB2/maven/net/minecraftforge/lex/legacyjavafixer/1.0/legacyjavafixer-1.0.jar
|
||||
legacyJavaFixerUrl=https://ftb.forgecdn.net/FTB2/maven/net/minecraftforge/lex/legacyjavafixer/1.0/legacyjavafixer-1.0.jar
|
||||
export TYPE=FEED-THE-BEAST
|
||||
|
||||
FTB_SERVER_MOD=${FTB_SERVER_MOD:-$CF_SERVER_MOD}
|
||||
|
||||
log "Looking for Feed-The-Beast / CurseForge server modpack."
|
||||
if [[ -z $FTB_SERVER_MOD ]]; then
|
||||
log "Environment variable FTB_SERVER_MOD not set."
|
||||
log "Set FTB_SERVER_MOD to the file name of the FTB server modpack."
|
||||
log "(And place the modpack in the /data directory.)"
|
||||
requireVar FTB_SERVER_MOD
|
||||
|
||||
if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then
|
||||
if ! [ -f "${FTB_SERVER_MOD}" ]; then
|
||||
log "ERROR unable to find requested modpack file ${FTB_SERVER_MOD}"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
needsInstall=true
|
||||
installMarker=/data/.curseforge-installed
|
||||
if [ -f $installMarker ]; then
|
||||
if [ "$(cat $installMarker)" != "${FTB_SERVER_MOD}" ]; then
|
||||
log "Upgrading modpack"
|
||||
|
||||
serverJar=$(find ${FTB_BASE_DIR} -not -name "forge*installer.jar" -name "forge*.jar")
|
||||
if [[ "${serverJar}" ]]; then
|
||||
rm -rf $(dirname "${serverJar}")/{mods,*.jar,libraries,resources,scripts,config}
|
||||
fi
|
||||
else
|
||||
needsInstall=false
|
||||
fi
|
||||
fi
|
||||
|
||||
if $needsInstall; then
|
||||
log "Unpacking FTB server modpack ${FTB_SERVER_MOD} ..."
|
||||
mkdir -p ${FTB_BASE_DIR}
|
||||
unzip -o "${FTB_SERVER_MOD}" -d ${FTB_BASE_DIR} | awk '{printf "."} END {print ""}'
|
||||
|
||||
serverJar=$(find ${FTB_BASE_DIR} -path "*/libraries/*" -prune -type f -o -not -name "forge*installer.jar" -name "forge*.jar")
|
||||
if [[ -z "$serverJar" ]]; then
|
||||
forgeInstallerJar=$(find ${FTB_BASE_DIR} -name "forge*installer.jar")
|
||||
if [[ -z "${forgeInstallerJar}" ]]; then
|
||||
log "ERROR Unable to find forge installer in modpack."
|
||||
log " Make sure you downloaded the server files."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
log "Installing forge server"
|
||||
(cd $(dirname "${forgeInstallerJar}"); java -jar $(basename "${forgeInstallerJar}") --installServer) | awk '{printf "."} END {print ""}'
|
||||
fi
|
||||
|
||||
echo "${FTB_SERVER_MOD}" > $installMarker
|
||||
fi
|
||||
|
||||
export SERVER=$(find ${FTB_BASE_DIR} -path "*/libraries/*" -prune -type f -o -not -name "forge*installer.jar" -name "forge*.jar")
|
||||
if [[ -z "${SERVER}" || ! -f "${SERVER}" ]]; then
|
||||
log "ERROR unable to locate installed forge server jar"
|
||||
isDebugging && find ${FTB_BASE_DIR} -name "forge*.jar"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
export FTB_DIR=$(dirname "${SERVER}")
|
||||
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
fi
|
||||
|
||||
entryScriptExpr="-name ServerStart.sh -o -name ServerStartLinux.sh -o -name LaunchServer.sh"
|
||||
entryScriptExpr="
|
||||
-name ServerStart.sh
|
||||
-o -name serverstart.sh
|
||||
-o -name ServerStartLinux.sh
|
||||
-o -name LaunchServer.sh
|
||||
-o -name server-start.sh
|
||||
-o -name startserver.sh
|
||||
-o -name StartServer.sh
|
||||
"
|
||||
|
||||
if [[ -d ${FTB_BASE_DIR} ]]; then
|
||||
startScriptCount=$(find ${FTB_BASE_DIR} $entryScriptExpr |wc -l)
|
||||
@@ -33,7 +93,7 @@ fi
|
||||
# this allows saving just the world separate from the rest of the data directory
|
||||
if [[ $startScriptCount = 0 ]]; then
|
||||
srv_modpack=${FTB_SERVER_MOD}
|
||||
if isURL ${srv_modpack}; then
|
||||
if isURL "${srv_modpack}"; then
|
||||
case $srv_modpack in
|
||||
https://www.feed-the-beast.com/*/download|https://www.curseforge.com/minecraft/modpacks/*/download/*/file)
|
||||
;;
|
||||
@@ -51,19 +111,19 @@ if [[ $startScriptCount = 0 ]]; then
|
||||
fi
|
||||
srv_modpack=$downloaded
|
||||
fi
|
||||
if [[ ${srv_modpack:0:5} == "data/" ]]; then
|
||||
if [[ "${srv_modpack:0:5}" == "data/" ]]; then
|
||||
# Prepend with "/"
|
||||
srv_modpack=/${srv_modpack}
|
||||
srv_modpack="/${srv_modpack}"
|
||||
fi
|
||||
if [[ ! ${srv_modpack:0:1} == "/" ]]; then
|
||||
if [[ ! "${srv_modpack:0:1}" == "/" ]]; then
|
||||
# If not an absolute path, assume file is in "/data"
|
||||
srv_modpack=/data/${srv_modpack}
|
||||
fi
|
||||
if [[ ! -f ${srv_modpack} ]]; then
|
||||
if [[ ! -f "${srv_modpack}" ]]; then
|
||||
log "FTB server modpack ${srv_modpack} not found."
|
||||
exit 2
|
||||
fi
|
||||
if [[ ! ${srv_modpack: -4} == ".zip" ]]; then
|
||||
if [[ ! "${srv_modpack: -4}" == ".zip" ]]; then
|
||||
log "FTB server modpack ${srv_modpack} is not a zip archive."
|
||||
log "Please set FTB_SERVER_MOD to a file with a .zip extension."
|
||||
exit 2
|
||||
@@ -71,7 +131,7 @@ if [[ $startScriptCount = 0 ]]; then
|
||||
|
||||
log "Unpacking FTB server modpack ${srv_modpack} ..."
|
||||
mkdir -p ${FTB_BASE_DIR}
|
||||
unzip -o ${srv_modpack} -d ${FTB_BASE_DIR} | awk '{printf "."} END {print ""}'
|
||||
unzip -o "${srv_modpack}" -d ${FTB_BASE_DIR} | awk '{printf "."} END {print ""}'
|
||||
fi
|
||||
|
||||
if [[ $(find ${FTB_BASE_DIR} $entryScriptExpr | wc -l) = 0 ]]; then
|
||||
@@ -109,7 +169,7 @@ export FTB_SERVER_START=$(find "${FTB_BASE_DIR}" $entryScriptExpr)
|
||||
|
||||
export FTB_DIR=$(dirname "${FTB_SERVER_START}")
|
||||
chmod a+x "${FTB_SERVER_START}"
|
||||
grep fml.queryResult=confirm ${FTB_SERVER_START} > /dev/null || \
|
||||
grep fml.queryResult=confirm "${FTB_SERVER_START}" > /dev/null || \
|
||||
sed -i 's/-jar/-Dfml.queryResult=confirm -jar/' "${FTB_SERVER_START}"
|
||||
sed -i 's/.*read.*Restart now/#\0/' "${FTB_SERVER_START}"
|
||||
legacyJavaFixerPath="${FTB_DIR}/mods/legacyjavafixer.jar"
|
||||
@@ -130,4 +190,4 @@ elif [ -e "${FTB_DIR}/Install.sh" ]; then
|
||||
fi
|
||||
|
||||
# Continue to Final Setup
|
||||
exec /start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
32
start-deployCatserver
Normal file
32
start-deployCatserver
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
set -o pipefail
|
||||
set -e
|
||||
|
||||
latestAsset=$(
|
||||
curl -fsSL https://api.github.com/repos/Luohuayu/CatServer/releases/latest | \
|
||||
jq '.assets[] | select(.name | match(".*-universal.jar"))'
|
||||
)
|
||||
|
||||
if [[ -z "${latestAsset}" ]]; then
|
||||
log "ERROR: latest release of Catserver is missing universal.jar asset"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
isDebugging && log "Latest asset ${latestAsset}"
|
||||
latestJarName=$(echo ${latestAsset} | jq --raw-output '.name')
|
||||
latestJarId=$(echo ${latestAsset} | jq --raw-output '.id')
|
||||
|
||||
|
||||
export SERVER="/data/${latestJarName}"
|
||||
|
||||
if [ ! -f ${SERVER} ]; then
|
||||
log "Downloading ${latestJarName}"
|
||||
curl -H "Accept:application/octet-stream" -o "$SERVER" -fsSL https://api.github.com/repos/Luohuayu/CatServer/releases/assets/${latestJarId}
|
||||
fi
|
||||
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld "$@"
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
if isURL ${CUSTOM_SERVER}; then
|
||||
filename=$(basename ${CUSTOM_SERVER})
|
||||
@@ -28,4 +28,4 @@ fi
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
# Continue to Final Setup
|
||||
exec /start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -1,42 +1,40 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
export TYPE=FABRIC
|
||||
|
||||
FABRIC_INSTALLER=${FABRIC_INSTALLER:-}
|
||||
FABRIC_INSTALLER_URL=${FABRIC_INSTALLER_URL:-}
|
||||
FABRICVERSION=${FABRICVERSION:-LATEST}
|
||||
FABRIC_INSTALLER_VERSION=${FABRIC_INSTALLER_VERSION:-${FABRICVERSION:-LATEST}}
|
||||
if [[ -z $FABRIC_INSTALLER && -z $FABRIC_INSTALLER_URL ]]; then
|
||||
log "Checking Fabric version information."
|
||||
case $FABRICVERSION in
|
||||
case $FABRIC_INSTALLER_VERSION in
|
||||
LATEST)
|
||||
FABRIC_VERSION=$(maven-metadata-release https://maven.fabricmc.net/net/fabricmc/fabric-installer/maven-metadata.xml)
|
||||
;;
|
||||
|
||||
*)
|
||||
FABRIC_VERSION=$FABRICVERSION
|
||||
FABRIC_INSTALLER_VERSION=$(maven-metadata-release https://maven.fabricmc.net/net/fabricmc/fabric-installer/maven-metadata.xml)
|
||||
;;
|
||||
esac
|
||||
|
||||
FABRIC_INSTALLER="/tmp/fabric-installer-$FABRIC_VERSION.jar"
|
||||
FABRIC_INSTALLER="/tmp/fabric-installer-${FABRIC_INSTALLER_VERSION}.jar"
|
||||
markerVersion=$FABRIC_INSTALLER_VERSION
|
||||
|
||||
elif [[ -z $FABRIC_INSTALLER ]]; then
|
||||
FABRIC_INSTALLER="/tmp/fabric-installer.jar"
|
||||
markerVersion=custom
|
||||
elif [[ ! -e $FABRIC_INSTALLER ]]; then
|
||||
log "ERROR: the given Fabric installer doesn't exist : $FABRIC_INSTALLER"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
installMarker="/data/.fabric-installed-${VANILLA_VERSION}-${FABRIC_VERSION:-manual}"
|
||||
installMarker="/data/.fabric-installed-${VANILLA_VERSION}-${markerVersion}"
|
||||
|
||||
debug Checking for installMarker ${installMarker}
|
||||
if [[ ! -e $installMarker ]]; then
|
||||
if [[ ! -e $FABRIC_INSTALLER ]]; then
|
||||
if [[ -z $FABRIC_INSTALLER_URL ]]; then
|
||||
log "Downloading $FABRIC_VERSION"
|
||||
downloadUrl="https://maven.fabricmc.net/net/fabricmc/fabric-installer/$FABRIC_VERSION/fabric-installer-$FABRIC_VERSION.jar"
|
||||
log "Downloading installer version $FABRIC_INSTALLER_VERSION"
|
||||
downloadUrl="https://maven.fabricmc.net/net/fabricmc/fabric-installer/${FABRIC_INSTALLER_VERSION}/fabric-installer-${FABRIC_INSTALLER_VERSION}.jar"
|
||||
log "...trying $downloadUrl"
|
||||
curl -o $FABRIC_INSTALLER -fsSL $downloadUrl
|
||||
else
|
||||
@@ -49,9 +47,9 @@ if [[ ! -e $installMarker ]]; then
|
||||
fi
|
||||
|
||||
if isDebugging; then
|
||||
debug "Installing Fabric $FABRIC_VERSION using $FABRIC_INSTALLER with mcversion ${VANILLA_VERSION}"
|
||||
debug "Installing Fabric ${VANILLA_VERSION} using $FABRIC_INSTALLER"
|
||||
else
|
||||
log "Installing Fabric $FABRIC_VERSION using $FABRIC_INSTALLER"
|
||||
log "Installing Fabric using $FABRIC_INSTALLER"
|
||||
fi
|
||||
tries=3
|
||||
set +e
|
||||
@@ -75,4 +73,4 @@ else
|
||||
fi
|
||||
|
||||
# Contineut to Final Setup
|
||||
exec /start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
export TYPE=FORGE
|
||||
|
||||
@@ -113,4 +113,4 @@ else
|
||||
fi
|
||||
|
||||
# Continue to Final Setup
|
||||
exec /start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
4
start-magma → start-deployMagma
Executable file → Normal file
4
start-magma → start-deployMagma
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
export SERVER="/data/magma-server-${VANILLA_VERSION}.jar"
|
||||
|
||||
@@ -15,4 +15,4 @@ fi
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
# Continue to Final Setup
|
||||
exec /start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
43
start-deployMohist
Normal file
43
start-deployMohist
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
set -o pipefail
|
||||
set -e
|
||||
isDebugging && set -x
|
||||
|
||||
requireVar VANILLA_VERSION
|
||||
|
||||
mohistJobs=https://ci.codemc.io/job/Mohist-Community/job/
|
||||
mohistJob=${mohistJobs}Mohist-${VANILLA_VERSION}/
|
||||
|
||||
if ! curl -X HEAD -o /dev/null -fsSL "${mohistJob}"; then
|
||||
log "ERROR: mohist builds do not exist for ${VANILLA_VERSION}"
|
||||
log " check https://ci.codemc.io/job/Mohist-Community/ for available versions"
|
||||
log " and set VERSION accordingly"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
latestBuildRelPath=$(
|
||||
curl -fsSL "${mohistJob}lastSuccessfulBuild/api/json" |
|
||||
jq -r '.artifacts[0].relativePath'
|
||||
)
|
||||
|
||||
baseName=$(basename "${latestBuildRelPath}")
|
||||
if [[ ${baseName} != *-server.jar* ]]; then
|
||||
log "ERROR: mohist build for ${VANILLA_VERSION} is not a valid server jar, found ${baseName}"
|
||||
log " check https://ci.codemc.io/job/Mohist-Community/ for available versions"
|
||||
log " and set VERSION accordingly"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export SERVER="/data/${baseName}"
|
||||
|
||||
if [ ! -f ${SERVER} ]; then
|
||||
log "Downloading ${baseName}"
|
||||
curl -o "${SERVER}" -fsSL "${mohistJob}lastSuccessfulBuild/artifact/${latestBuildRelPath}"
|
||||
fi
|
||||
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld "$@"
|
||||
@@ -1,23 +1,74 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
set -o pipefail
|
||||
isDebugging && set -x
|
||||
|
||||
: ${PAPERBUILD:=latest}
|
||||
export SERVER=paper_server-${VANILLA_VERSION}-${PAPERBUILD}.jar
|
||||
if [[ $PAPER_DOWNLOAD_URL ]]; then
|
||||
export SERVER=$(getFilenameFromUrl "${PAPER_DOWNLOAD_URL}")
|
||||
|
||||
if [ ! -f "$SERVER" ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
downloadUrl=${PAPER_DOWNLOAD_URL:-https://papermc.io/api/v1/paper/${VANILLA_VERSION}/${PAPERBUILD}/download}
|
||||
log "Downloading Paper $VANILLA_VERSION (build $PAPERBUILD) from $downloadUrl ..."
|
||||
curl -fsSL -o "$SERVER" "$downloadUrl"
|
||||
if [ ! -f "$SERVER" ]; then
|
||||
log "ERROR: failed to download from $downloadUrl (status=$?)"
|
||||
exit 3
|
||||
fi
|
||||
if [ -f "$SERVER" ]; then
|
||||
zarg=(-z "$SERVER")
|
||||
fi
|
||||
|
||||
echo "Preparing custom PaperMC jar from $PAPER_DOWNLOAD_URL"
|
||||
|
||||
curl -fsSL -o "$SERVER" "${zarg[@]}" "${PAPER_DOWNLOAD_URL}"
|
||||
else
|
||||
# PaperMC API v2 docs : https://papermc.io/api/docs/swagger-ui/index.html?configUrl=/api/openapi/swagger-config
|
||||
|
||||
build=$(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 "Downloading PaperMC $VANILLA_VERSION (build $build) ..."
|
||||
curl -fsSL -o "$SERVER" "${zarg[@]}" \
|
||||
"https://papermc.io/api/v2/projects/paper/versions/${VANILLA_VERSION}/builds/${build}/downloads/${SERVER}" \
|
||||
-H "accept: application/java-archive"
|
||||
if [ $? != 0 ]; then
|
||||
echo "ERROR: failed to download PaperMC from version=${VANILLA_VERSION} build=${build} download=${SERVER}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for operations below
|
||||
# Normalize on Spigot for downstream operations
|
||||
export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
# Continue to Final Setup
|
||||
exec /start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
export TYPE=spongevanilla
|
||||
|
||||
@@ -36,4 +36,4 @@ if [ ! -e $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
fi
|
||||
|
||||
# Continue to Final Setup
|
||||
exec /start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
if [ "${VERSION}" != "LATEST" ]; then
|
||||
log "ERROR: Tunity server type only supports VERSION=LATEST"
|
||||
@@ -24,4 +24,4 @@ fi
|
||||
export TYPE=SPIGOT
|
||||
|
||||
# Continue to Final Setup
|
||||
exec /start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
set -o pipefail
|
||||
|
||||
export SERVER="minecraft_server.${VANILLA_VERSION// /_}.jar"
|
||||
@@ -25,6 +26,9 @@ if [ ! -e $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
if [ $result != 0 ]; then
|
||||
log "ERROR failed to obtain version manifest from $versionManifestUrl ($result)"
|
||||
exit 1
|
||||
elif [ $serverDownloadUrl = null ]; then
|
||||
log "ERROR version $VANILLA_VERSION does not provide a server download"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
debug "Downloading server from $serverDownloadUrl"
|
||||
@@ -39,5 +43,7 @@ if [ ! -e $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
isDebugging && ls -l
|
||||
|
||||
# Continue to Final Setup
|
||||
exec /start-finalSetup01World $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld $@
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
|
||||
if [ $TYPE = "FEED-THE-BEAST" ]; then
|
||||
worldDest=$FTB_BASE_DIR/$LEVEL
|
||||
else
|
||||
worldDest=/data/$LEVEL
|
||||
fi
|
||||
|
||||
# If no world exists and a URL for a world is supplied, download it and unpack
|
||||
if [[ "$WORLD" ]] && [ ! -d "$worldDest" ]; then
|
||||
case "X$WORLD" in
|
||||
X[Hh][Tt][Tt][Pp]*)
|
||||
log "Downloading world from $WORLD"
|
||||
curl -sSL -o - "$WORLD" > /data/world.zip
|
||||
log "Unzipping world"
|
||||
unzip -o -q /data/world.zip
|
||||
rm -f /data/world.zip
|
||||
if [ ! -d $worldDest ]; then
|
||||
log World directory not found
|
||||
for i in /data/*/level.dat; do
|
||||
if [ -f "$i" ]; then
|
||||
d=`dirname "$i"`
|
||||
log Renaming world directory from $d
|
||||
mv -f "$d" $worldDest
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
# Reorganise if a Spigot server
|
||||
log "Moving End and Nether maps to Spigot location"
|
||||
[ -d "$worldDest/DIM1" ] && mv -f "$worldDest/DIM1" "/data/${LEVEL}_the_end"
|
||||
[ -d "$worldDest/DIM-1" ] && mv -f "$worldDest/DIM-1" "/data/${LEVEL}_nether"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if [[ -d "$WORLD" ]]; then
|
||||
if [[ ! -d "$worldDest" ]]; then
|
||||
log "Cloning world directory from $WORLD ..."
|
||||
cp -r "$WORLD" "$worldDest"
|
||||
else
|
||||
log "Skipping clone from $WORLD since $worldDest exists"
|
||||
fi
|
||||
else
|
||||
log "World cloning source '$WORLD' doesn't seem to exist"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
exec /start-finalSetup02Modpack $@
|
||||
@@ -1,9 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
if [ "${REPLACE_ENV_VARIABLES^^}" = "TRUE" ]; then
|
||||
: ${ENV_VARIABLE_PREFIX:=CFG_}
|
||||
|
||||
if isTrue "${REPLACE_ENV_VARIABLES}"; then
|
||||
log "Replacing env variables in configs that match the prefix $ENV_VARIABLE_PREFIX..."
|
||||
|
||||
# File excludes
|
||||
fileExcludes=
|
||||
for f in ${REPLACE_ENV_VARIABLES_EXCLUDES}; do
|
||||
fileExcludes="${fileExcludes} -not -name $f"
|
||||
done
|
||||
|
||||
# Directory excludes (recursive)
|
||||
dirExcludes=$(join_by " -o -path " ${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS})
|
||||
if [[ $dirExcludes ]]; then
|
||||
dirExcludes=" -type d ( -path ${dirExcludes} ) -prune -o"
|
||||
fi
|
||||
|
||||
isDebugging && echo "Using find file exclusions: $fileExcludes"
|
||||
isDebugging && echo "Using find directory exclusions: $dirExcludes"
|
||||
|
||||
while IFS='=' read -r name value ; do
|
||||
# check if name of env variable matches the prefix
|
||||
# sanity check environment variables to avoid code injections
|
||||
@@ -17,12 +35,15 @@ if [ "${REPLACE_ENV_VARIABLES^^}" = "TRUE" ]; then
|
||||
fi
|
||||
|
||||
log "Replacing $name with $value ..."
|
||||
find /data/ -type f \
|
||||
find /data/ \
|
||||
$dirExcludes \
|
||||
-type f \
|
||||
\( -name "*.yml" -or -name "*.yaml" -or -name "*.txt" -or -name "*.cfg" \
|
||||
-or -name "*.conf" -or -name "*.properties" \) \
|
||||
$fileExcludes \
|
||||
-exec sed -i 's#${'"$name"'}#'"$value"'#g' {} \;
|
||||
fi
|
||||
done < <(env)
|
||||
fi
|
||||
|
||||
exec /start-minecraftFinalSetup $@
|
||||
exec ${SCRIPTS:-/}start-minecraftFinalSetup $@
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
# If supplied with a URL for a config (simple zip of configurations), download it and unpack
|
||||
if [[ "$MODCONFIG" ]]; then
|
||||
@@ -24,4 +24,4 @@ case "X$MODCONFIG" in
|
||||
esac
|
||||
fi
|
||||
|
||||
exec /start-finalSetup04ServerProperties $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupMounts $@
|
||||
@@ -1,80 +1,102 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -e -o pipefail
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
if isDebugging; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
# CURSE_URL_BASE used in manifest downloads below
|
||||
CURSE_URL_BASE=${CURSE_URL_BASE:-https://minecraft.curseforge.com/projects}
|
||||
|
||||
# Remove old mods/plugins
|
||||
if [ "$REMOVE_OLD_MODS" = "TRUE" ]; then
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
rm -rf /data/plugins/*
|
||||
if isTrue ${REMOVE_OLD_MODS}; then
|
||||
remove_mods_dest="/data/mods"
|
||||
case ${TYPE} in
|
||||
SPIGOT|BUKKIT|PAPER)
|
||||
remove_mods_dest="/data/plugins"
|
||||
;;
|
||||
esac
|
||||
|
||||
# only try to remove existing mods dir
|
||||
if [ -d "$remove_mods_dest" ]; then
|
||||
log "Removing old mods in $remove_mods_dest..."
|
||||
find $remove_mods_dest -mindepth 1 -maxdepth ${REMOVE_OLD_MODS_DEPTH:-16} -wholename "${REMOVE_OLD_MODS_INCLUDE:-*}" -not -wholename "${REMOVE_OLD_MODS_EXCLUDE}" -delete
|
||||
else
|
||||
rm -rf /data/mods/*
|
||||
log "Directory $remove_mods_dest does not exist; removing nothing."
|
||||
fi
|
||||
fi
|
||||
|
||||
# If supplied with a URL for a modpack (simple zip of jars), download it and unpack
|
||||
if [[ "$MODPACK" ]]; then
|
||||
EFFECTIVE_MODPACK_URL=$(curl -Ls -o /dev/null -w %{url_effective} $MODPACK)
|
||||
case "X$EFFECTIVE_MODPACK_URL" in
|
||||
X[Hh][Tt][Tt][Pp]*.zip)
|
||||
if isURL "${MODPACK}"; then
|
||||
if [[ "${MODPACK}" == *.zip ]]; then
|
||||
downloadUrl="${MODPACK}"
|
||||
else
|
||||
downloadUrl=$(curl -Ls -o /dev/null -w %{effective_url} $MODPACK)
|
||||
if ! [[ $downloadUrl == *.zip ]]; then
|
||||
log "ERROR Invalid URL given for MODPACK: $downloadUrl resolved from $MODPACK"
|
||||
log " Must be HTTP or HTTPS and a ZIP file"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
log "Downloading mod/plugin pack via HTTP"
|
||||
log " from $EFFECTIVE_MODPACK_URL ..."
|
||||
if ! curl -sSL -o /tmp/modpack.zip "$EFFECTIVE_MODPACK_URL"; then
|
||||
log "ERROR: failed to download from $EFFECTIVE_MODPACK_URL"
|
||||
log " from $downloadUrl ..."
|
||||
if ! curl -sSL -o /tmp/modpack.zip "$downloadUrl"; then
|
||||
log "ERROR: failed to download from $downloadUrl"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
mkdir -p /data/plugins
|
||||
if ! unzip -o -d /data/plugins /tmp/modpack.zip; then
|
||||
log "ERROR: failed to unzip the modpack from $EFFECTIVE_MODPACK_URL"
|
||||
log "ERROR: failed to unzip the modpack from $downloadUrl"
|
||||
fi
|
||||
else
|
||||
mkdir -p /data/mods
|
||||
if ! unzip -o -d /data/mods /tmp/modpack.zip; then
|
||||
log "ERROR: failed to unzip the modpack from $EFFECTIVE_MODPACK_URL"
|
||||
log "ERROR: failed to unzip the modpack from $downloadUrl"
|
||||
fi
|
||||
fi
|
||||
rm -f /tmp/modpack.zip
|
||||
;;
|
||||
*)
|
||||
log "Invalid URL given for modpack: Must be HTTP or HTTPS and a ZIP file"
|
||||
;;
|
||||
esac
|
||||
|
||||
else
|
||||
log "ERROR Invalid URL given for MODPACK: $MODPACK"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# If supplied with a URL for a plugin download it.
|
||||
if [[ "$MODS" ]]; then
|
||||
for i in ${MODS//,/ }
|
||||
do
|
||||
EFFECTIVE_MOD_URL=$(curl -Ls -o /dev/null -w %{url_effective} $i)
|
||||
case "X$EFFECTIVE_MOD_URL" in
|
||||
X[Hh][Tt][Tt][Pp]*.jar)
|
||||
log "Downloading mod/plugin via HTTP"
|
||||
log " from $EFFECTIVE_MOD_URL ..."
|
||||
if ! curl -sSL -o /tmp/${EFFECTIVE_MOD_URL##*/} $EFFECTIVE_MOD_URL; then
|
||||
log "ERROR: failed to download from $EFFECTIVE_MOD_URL to /tmp/${EFFECTIVE_MOD_URL##*/}"
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
out_dir=/data/plugins
|
||||
else
|
||||
out_dir=/data/mods
|
||||
fi
|
||||
mkdir -p "$out_dir"
|
||||
|
||||
for i in ${MODS//,/ }
|
||||
do
|
||||
if isURL $i; then
|
||||
log "Downloading mod/plugin $i ..."
|
||||
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
|
||||
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
mkdir -p /data/plugins
|
||||
mv /tmp/${EFFECTIVE_MOD_URL##*/} /data/plugins/${EFFECTIVE_MOD_URL##*/}
|
||||
else
|
||||
mkdir -p /data/mods
|
||||
mv /tmp/${EFFECTIVE_MOD_URL##*/} /data/mods/${EFFECTIVE_MOD_URL##*/}
|
||||
fi
|
||||
rm -f /tmp/${EFFECTIVE_MOD_URL##*/}
|
||||
;;
|
||||
*)
|
||||
log "Invalid URL given for modpack: Must be HTTP or HTTPS and a JAR file"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
log "ERROR Invalid URL given in MODS: $i"
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "$MANIFEST" ]]; then
|
||||
@@ -82,7 +104,7 @@ if [[ "$MANIFEST" ]]; then
|
||||
EFFECTIVE_MANIFEST_FILE=$MANIFEST
|
||||
elif isURL "$MANIFEST"; then
|
||||
EFFECTIVE_MANIFEST_FILE=/tmp/manifest.json
|
||||
EFFECTIVE_MANIFEST_URL=$(curl -Ls -o /dev/null -w %{url_effective} $MANIFEST)
|
||||
EFFECTIVE_MANIFEST_URL=$(curl -Ls -o /dev/null -w %{effective_url} $MANIFEST)
|
||||
curl -Ls -o $EFFECTIVE_MANIFEST_FILE "$EFFECTIVE_MANIFEST_URL"
|
||||
else
|
||||
log "MANIFEST='$MANIFEST' is not a valid manifest url or location"
|
||||
@@ -103,7 +125,7 @@ case "X$EFFECTIVE_MANIFEST_FILE" in
|
||||
do
|
||||
if [ ! -f $MOD_DIR/${p}_${f}.jar ]
|
||||
then
|
||||
redirect_url="$(curl -Ls -o /dev/null -w %{url_effective} ${CURSE_URL_BASE}/${p})"
|
||||
redirect_url="$(curl -Ls -o /dev/null -w %{effective_url} ${CURSE_URL_BASE}/${p})"
|
||||
url="$redirect_url/download/${f}/file"
|
||||
log Downloading curseforge mod $url
|
||||
# Manifest usually doesn't have mod names. Using id should be fine, tho
|
||||
@@ -122,10 +144,9 @@ fi
|
||||
|
||||
if [[ "${GENERIC_PACK}" ]]; then
|
||||
if isURL "${GENERIC_PACK}"; then
|
||||
generic_pack_url=${GENERIC_PACK}
|
||||
GENERIC_PACK=/tmp/$(basename ${generic_pack_url})
|
||||
log "Downloading generic pack from ${generic_pack_url} ..."
|
||||
curl -fsSL -o ${GENERIC_PACK} ${generic_pack_url}
|
||||
log "Downloading generic pack ..."
|
||||
curl -fsSL -o /tmp/generic_pack.zip "${GENERIC_PACK}"
|
||||
GENERIC_PACK=/tmp/generic_pack.zip
|
||||
fi
|
||||
|
||||
sum_file=/data/.generic_pack.sum
|
||||
@@ -154,4 +175,4 @@ if [[ "${GENERIC_PACK}" ]]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
exec /start-finalSetup03Modconfig $@
|
||||
exec ${SCRIPTS:-/}start-finalSetupModconfig $@
|
||||
38
start-finalSetupMounts
Executable file
38
start-finalSetupMounts
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
: ${PLUGINS_SYNC_UPDATE:=true}
|
||||
|
||||
isDebugging && set -x
|
||||
|
||||
if [ -d /plugins ]; then
|
||||
case ${TYPE} in
|
||||
SPIGOT|BUKKIT|PAPER|MAGMA)
|
||||
mkdir -p /data/plugins
|
||||
log "Copying plugins over..."
|
||||
if isTrue ${PLUGINS_SYNC_UPDATE}; then
|
||||
updateArg="--update"
|
||||
fi
|
||||
# Copy plugins over using rsync to allow deeply nested updates of plugins
|
||||
rsync -a --out-format="update:%f:Last Modified %M" --prune-empty-dirs $updateArg /plugins /data
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# If any modules have been provided, copy them over
|
||||
if [ -d /mods ]; then
|
||||
log "Copying any mods over..."
|
||||
mkdir -p /data/mods
|
||||
rsync -a --out-format="update:%f:Last Modified %M" "${rsyncArgs[@]}" --prune-empty-dirs --update /mods /data
|
||||
fi
|
||||
|
||||
: ${COPY_CONFIG_DEST:="/data/config"}
|
||||
|
||||
if [ -d /config ]; then
|
||||
log "Copying any configs from /config to $COPY_CONFIG_DEST"
|
||||
mkdir -p $COPY_CONFIG_DEST
|
||||
rsync -a --out-format="update:%f:Last Modified %M" "${rsyncArgs[@]}" --prune-empty-dirs --update /config/ $COPY_CONFIG_DEST
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-finalSetupServerProperties $@
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
# FUNCTIONS
|
||||
function setServerProp {
|
||||
@@ -77,6 +77,18 @@ function customizeServerProps {
|
||||
setServerProp "resource-pack" "$RESOURCE_PACK"
|
||||
setServerProp "resource-pack-sha1" "$RESOURCE_PACK_SHA1"
|
||||
setServerProp "player-idle-timeout" "$PLAYER_IDLE_TIMEOUT"
|
||||
setServerProp "broadcast-console-to-ops" "$BROADCAST_CONSOLE_TO_OPS"
|
||||
setServerProp "broadcast-rcon-to-ops" "$BROADCAST_RCON_TO_OPS"
|
||||
setServerProp "enable-jmx-monitoring" "$ENABLE_JMX"
|
||||
setServerProp "sync-chunk-writes" "$SYNC_CHUNK_WRITES"
|
||||
setServerProp "enable-status" "$ENABLE_STATUS"
|
||||
setServerProp "entity-broadcast-range-percentage" "$ENTITY_BROADCAST_RANGE_PERCENTAGE"
|
||||
setServerProp "function-permission-level" "$FUNCTION_PERMISSION_LEVEL"
|
||||
setServerProp "network-compression-threshold" "$NETWORK_COMPRESSION_THRESHOLD"
|
||||
setServerProp "op-permission-level" "$OP_PERMISSION_LEVEL"
|
||||
setServerProp "prevent-proxy-connections" "$PREVENT_PROXY_CONNECTIONS"
|
||||
setServerProp "use-native-transport" "$USE_NATIVE_TRANSPORT"
|
||||
setServerProp "enforce-whitelist" "$ENFORCE_WHITELIST"
|
||||
|
||||
if [ -n "$DIFFICULTY" ]; then
|
||||
case $DIFFICULTY in
|
||||
@@ -180,4 +192,18 @@ else
|
||||
log "server.properties already created, skipping"
|
||||
fi
|
||||
|
||||
exec /start-finalSetup05EnvVariables $@
|
||||
if isTrue "${ENABLE_AUTOPAUSE}"; then
|
||||
current_max_tick=$( grep 'max-tick-time' "$SERVER_PROPERTIES" | sed -r 's/( )+//g' | awk -F= '{print $2}' )
|
||||
if (( $current_max_tick > 0 && $current_max_tick < 86400000 )); then
|
||||
log "Warning: The server.properties for the server doesn't have the Server Watchdog (effectively) disabled."
|
||||
log "Warning (cont): Autopause functionality resuming the process might trigger the Watchdog and restart the server completely."
|
||||
log "Warning (cont): Set the max-tick-time property to a high value (or disable the Watchdog with value -1 for versions 1.8.1+)."
|
||||
fi
|
||||
fi
|
||||
|
||||
if isDebugging; then
|
||||
log "DEBUG Dumping server.properties"
|
||||
cat /data/server.properties
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-finalSetupEnvVariables $@
|
||||
64
start-finalSetupWorld
Normal file
64
start-finalSetupWorld
Normal file
@@ -0,0 +1,64 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
set -e
|
||||
isDebugging && set -x
|
||||
|
||||
if [ $TYPE = "FEED-THE-BEAST" ]; then
|
||||
worldDest=$FTB_DIR/$LEVEL
|
||||
else
|
||||
worldDest=/data/$LEVEL
|
||||
fi
|
||||
|
||||
if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] ); then
|
||||
if isURL $WORLD; then
|
||||
curl -fsSL "$WORLD" -o /tmp/world.zip
|
||||
zipSrc=/tmp/world.zip
|
||||
elif [[ "$WORLD" =~ .*\.zip ]]; then
|
||||
zipSrc="$WORLD"
|
||||
fi
|
||||
|
||||
if [[ "$zipSrc" ]]; then
|
||||
log "Unzipping world"
|
||||
|
||||
# Stage contents so that the correct subdirectory can be picked off
|
||||
mkdir -p /tmp/world-data
|
||||
(cd /tmp/world-data && unzip -o -q "$zipSrc")
|
||||
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
baseDirs=$(find /tmp/world-data -name "level.dat" -not -path "*_nether*" -not -path "*_the_end*" -exec dirname "{}" \;)
|
||||
else
|
||||
baseDirs=$(find /tmp/world-data -name "level.dat" -exec dirname "{}" \;)
|
||||
fi
|
||||
|
||||
count=$(echo "$baseDirs" | wc -l)
|
||||
if [[ $count -gt 1 ]]; then
|
||||
baseDir="$(echo "$baseDirs" | sed -n ${WORLD_INDEX:-1}p)"
|
||||
baseName=$(basename "$baseDir")
|
||||
log "WARN multiple levels found, picking: $baseName"
|
||||
elif [[ $count -gt 0 ]]; then
|
||||
baseDir="$baseDirs"
|
||||
else
|
||||
log "ERROR invalid world content"
|
||||
exit 1
|
||||
fi
|
||||
rsync --remove-source-files --recursive --delete "$baseDir/" "$worldDest"
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
log "Copying end and nether ..."
|
||||
[ -d "${baseDir}_nether" ] && rsync --remove-source-files --recursive --delete "${baseDir}_nether/" "${worldDest}_nether"
|
||||
[ -d "${baseDir}_the_end" ] && rsync --remove-source-files --recursive --delete "${baseDir}_the_end/" "${worldDest}_the_end"
|
||||
fi
|
||||
else
|
||||
log "Cloning world directory from $WORLD ..."
|
||||
rsync --recursive --delete "${WORLD%/}"/ "$worldDest"
|
||||
fi
|
||||
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
# Reorganise if a Spigot server
|
||||
log "Moving End and Nether maps to Spigot location"
|
||||
[ -d "$worldDest/DIM1" ] && mv -f "$worldDest/DIM1" "/data/${LEVEL}_the_end"
|
||||
[ -d "$worldDest/DIM-1" ] && mv -f "$worldDest/DIM-1" "/data/${LEVEL}_nether"
|
||||
fi
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-finalSetupModpack $@
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
if [ -n "$OPS" ]; then
|
||||
log "Setting/adding ops"
|
||||
@@ -49,35 +49,6 @@ for j in $JSON_FILES; do
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
# If any modules have been provided, copy them over
|
||||
if [ -d /mods ]; then
|
||||
log "Copying any mods over..."
|
||||
mkdir -p /data/mods
|
||||
rsync -a --out-format="update:%f:Last Modified %M" --prune-empty-dirs --update /mods /data
|
||||
fi
|
||||
|
||||
[ -d /data/config ] || mkdir /data/config
|
||||
for c in /config/*
|
||||
do
|
||||
if [ -f "$c" ]; then
|
||||
log Copying configuration $(basename "$c")
|
||||
cp -rf "$c" /data/config
|
||||
fi
|
||||
done
|
||||
|
||||
case ${TYPE} in
|
||||
SPIGOT|BUKKIT|PAPER)
|
||||
mkdir -p /data/plugins
|
||||
if [ -d /plugins ]; then
|
||||
log "Copying plugins over..."
|
||||
# Copy plugins over using rsync to allow deeply nested updates of plugins
|
||||
# only updates files if the source file is newer and print updated files
|
||||
rsync -a --out-format="update:%f:Last Modified %M" --prune-empty-dirs --update /plugins /data
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
EXTRA_ARGS=""
|
||||
# Optional disable console
|
||||
if versionLessThan 1.14 && [[ ${CONSOLE,,} = false ]]; then
|
||||
@@ -170,45 +141,60 @@ if isTrue "${DEBUG_MEMORY}"; then
|
||||
free -m
|
||||
fi
|
||||
|
||||
mcServerRunnerArgs="--stop-duration 60s"
|
||||
JVM_OPTS="-Xms${INIT_MEMORY} -Xmx${MAX_MEMORY} ${JVM_OPTS}"
|
||||
|
||||
function copyFilesForCurseForge() {
|
||||
# copy player modification files unconditionally since their
|
||||
# processing into json is additive anyway
|
||||
[ -f /data/ops.txt ] && cp -f /data/ops.txt ${FTB_DIR}/
|
||||
[ -f /data/white-list.txt ] && cp -f /data/white-list.txt ${FTB_DIR}/
|
||||
|
||||
if [ ! -e "${FTB_DIR}/server-icon.png" -a -e /data/server-icon.png ]; then
|
||||
cp -f /data/server-icon.png ${FTB_DIR}/
|
||||
fi
|
||||
|
||||
cp -f /data/eula.txt "${FTB_DIR}/"
|
||||
}
|
||||
|
||||
mcServerRunnerArgs="--stop-duration ${STOP_DURATION:-60}s"
|
||||
if [[ ${TYPE} == "CURSE_INSTANCE" ]]; then
|
||||
JVM_OPTS="-Xms${INIT_MEMORY} -Xmx${MAX_MEMORY} ${JVM_OPTS}"
|
||||
if isTrue ${DEBUG_EXEC}; then
|
||||
set -x
|
||||
fi
|
||||
exec mc-server-runner ${mcServerRunnerArgs} \
|
||||
--cf-instance-file "${CURSE_INSTANCE_JSON}" \
|
||||
java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar _SERVERJAR_ "$@" $EXTRA_ARGS
|
||||
elif [[ ${TYPE} == "FEED-THE-BEAST" && "${SERVER}" ]]; then
|
||||
copyFilesForCurseForge
|
||||
|
||||
cd "${FTB_DIR}"
|
||||
log "Starting CurseForge server in ${FTB_DIR}..."
|
||||
if isTrue ${DEBUG_EXEC}; then
|
||||
set -x
|
||||
fi
|
||||
exec mc-server-runner ${bootstrapArgs} ${mcServerRunnerArgs} java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar $(basename "${SERVER}") "$@" $EXTRA_ARGS
|
||||
elif [[ ${TYPE} == "FEED-THE-BEAST" ]]; then
|
||||
mcServerRunnerArgs="${mcServerRunnerArgs} --shell bash"
|
||||
mcServerRunnerArgs="${mcServerRunnerArgs} --shell bash"
|
||||
|
||||
if [ ! -e "${FTB_DIR}/ops.json" -a -e /data/ops.txt ]; then
|
||||
cp -f /data/ops.txt ${FTB_DIR}/
|
||||
fi
|
||||
copyFilesForCurseForge
|
||||
|
||||
if [ ! -e "${FTB_DIR}/whitelist.json" -a -e /data/white-list.txt ]; then
|
||||
cp -f /data/white-list.txt ${FTB_DIR}/
|
||||
fi
|
||||
|
||||
cp -f /data/eula.txt "${FTB_DIR}/"
|
||||
|
||||
cat > "${FTB_DIR}/settings-local.sh" <<EOF
|
||||
cat > "${FTB_DIR}/settings-local.sh" <<EOF
|
||||
export MIN_RAM="${INIT_MEMORY}"
|
||||
export MAX_RAM="${MAX_MEMORY}"
|
||||
export JAVA_PARAMETERS="${JVM_XX_OPTS} -Xms${INIT_MEMORY} ${JVM_OPTS} $expandedDOpts"
|
||||
EOF
|
||||
|
||||
# patch CurseForge cfg file, if present
|
||||
if [ -f "${FTB_DIR}/settings.cfg" ]; then
|
||||
sed -i "s/MAX_RAM=[^;]*/MAX_RAM=${MAX_MEMORY}/" "${FTB_DIR}/settings.cfg"
|
||||
fi
|
||||
# patch CurseForge cfg file, if present
|
||||
if [ -f "${FTB_DIR}/settings.cfg" ]; then
|
||||
sed -i "s/MAX_RAM=[^;]*/MAX_RAM=${MAX_MEMORY}/" "${FTB_DIR}/settings.cfg"
|
||||
fi
|
||||
|
||||
cd "${FTB_DIR}"
|
||||
log "Running FTB ${FTB_SERVER_START} in ${FTB_DIR} ..."
|
||||
if isTrue ${DEBUG_EXEC}; then
|
||||
set -x
|
||||
fi
|
||||
exec mc-server-runner ${mcServerRunnerArgs} "${FTB_SERVER_START}"
|
||||
cd "${FTB_DIR}"
|
||||
log "Running FTB ${FTB_SERVER_START} in ${FTB_DIR} ..."
|
||||
if isTrue ${DEBUG_EXEC}; then
|
||||
set -x
|
||||
fi
|
||||
exec mc-server-runner ${mcServerRunnerArgs} "${FTB_SERVER_START}"
|
||||
else
|
||||
# If we have a bootstrap.txt file... feed that in to the server stdin
|
||||
if [ -f /data/bootstrap.txt ]; then
|
||||
@@ -216,7 +202,6 @@ else
|
||||
fi
|
||||
|
||||
log "Starting the Minecraft server..."
|
||||
JVM_OPTS="-Xms${INIT_MEMORY} -Xmx${MAX_MEMORY} ${JVM_OPTS}"
|
||||
if isTrue ${DEBUG_EXEC}; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
140
start-utils
140
start-utils
@@ -1,6 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
function isURL {
|
||||
function join_by() {
|
||||
local d=$1
|
||||
shift
|
||||
echo -n "$1"
|
||||
shift
|
||||
printf "%s" "${@/#/$d}"
|
||||
}
|
||||
|
||||
function isURL() {
|
||||
local value=$1
|
||||
|
||||
if [[ ${value:0:8} == "https://" || ${value:0:7} == "http://" ]]; then
|
||||
@@ -10,75 +18,137 @@ function isURL {
|
||||
fi
|
||||
}
|
||||
|
||||
function isTrue {
|
||||
function isValidFileURL() {
|
||||
suffix=${1:?Missing required suffix arg}
|
||||
url=${2:?Missing required url arg}
|
||||
|
||||
[[ "$url" == http*://*.${suffix} || "$url" == http*://*.${suffix}\?* ]]
|
||||
}
|
||||
|
||||
function resolveEffectiveUrl() {
|
||||
url="${1:?Missing required url argument}"
|
||||
if ! curl -Ls -o /dev/null -w %{url_effective} "$url"; then
|
||||
log "ERROR failed to resolve effective URL from $url"
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
function getFilenameFromUrl() {
|
||||
url="${1:?Missing required url argument}"
|
||||
strippedOfQuery="${url%\?*}"
|
||||
basename "$strippedOfQuery"
|
||||
}
|
||||
|
||||
function isTrue() {
|
||||
local value=${1,,}
|
||||
|
||||
result=
|
||||
|
||||
case ${value} in
|
||||
true|on)
|
||||
result=0
|
||||
;;
|
||||
*)
|
||||
result=1
|
||||
;;
|
||||
true | on)
|
||||
result=0
|
||||
;;
|
||||
*)
|
||||
result=1
|
||||
;;
|
||||
esac
|
||||
|
||||
return ${result}
|
||||
}
|
||||
|
||||
function isDebugging {
|
||||
if [[ -v DEBUG ]] && [[ ${DEBUG^^} = TRUE ]]; then
|
||||
function isDebugging() {
|
||||
if [[ -v DEBUG ]] && [[ ${DEBUG^^} == TRUE ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function debug {
|
||||
function debug() {
|
||||
if isDebugging; then
|
||||
log "DEBUG: $*"
|
||||
fi
|
||||
}
|
||||
|
||||
function logn {
|
||||
function logn() {
|
||||
echo -n "[init] $*"
|
||||
}
|
||||
|
||||
function log {
|
||||
function log() {
|
||||
echo "[init] $*"
|
||||
}
|
||||
|
||||
function normalizeMemSize {
|
||||
local scale=1
|
||||
case ${1,,} in
|
||||
*k)
|
||||
scale=1024;;
|
||||
*m)
|
||||
scale=1048576;;
|
||||
*g)
|
||||
scale=1073741824;;
|
||||
esac
|
||||
|
||||
val=${1:0: -1}
|
||||
echo $(( val * scale ))
|
||||
function logAutopause() {
|
||||
echo "[Autopause loop] $*"
|
||||
}
|
||||
|
||||
function versionLessThan {
|
||||
function logAutopauseAction() {
|
||||
echo "[$(date -Iseconds)] [Autopause] $*"
|
||||
}
|
||||
|
||||
function normalizeMemSize() {
|
||||
local scale=1
|
||||
case ${1,,} in
|
||||
*k)
|
||||
scale=1024
|
||||
;;
|
||||
*m)
|
||||
scale=1048576
|
||||
;;
|
||||
*g)
|
||||
scale=1073741824
|
||||
;;
|
||||
esac
|
||||
|
||||
val=${1:0:-1}
|
||||
echo $((val * scale))
|
||||
}
|
||||
|
||||
function versionLessThan() {
|
||||
local activeParts
|
||||
IFS=. read -ra activeParts <<< "${VANILLA_VERSION}"
|
||||
IFS=. read -ra activeParts <<<"${VANILLA_VERSION}"
|
||||
|
||||
local givenParts
|
||||
IFS=. read -ra givenParts <<< "$1"
|
||||
IFS=. read -ra givenParts <<<"$1"
|
||||
|
||||
if (( ${#activeParts[@]} < 2 )); then
|
||||
if ((${#activeParts[@]} < 2)); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if (( activeParts[0] < givenParts[0] )) || \
|
||||
(( activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1] )); then
|
||||
return 0
|
||||
if ((${#activeParts[@]} == 2)); then
|
||||
if ((activeParts[0] < givenParts[0])) ||
|
||||
((activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1])); then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
return 1
|
||||
if ((activeParts[0] < givenParts[0])) ||
|
||||
((activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1])) ||
|
||||
((activeParts[0] == givenParts[0] && activeParts[1] == givenParts[1] && activeParts[2] < givenParts[2])); then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
}
|
||||
|
||||
requireVar() {
|
||||
if [ ! -v $1 ]; then
|
||||
log "ERROR: $1 is required to be set"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${!1}" ]; then
|
||||
log "ERROR: $1 is required to be set"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function writeEula() {
|
||||
if ! echo "# Generated via Docker on $(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
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
if ! [[ -v CURSE_INSTANCE_JSON ]]; then
|
||||
log "ERROR: CURSE_INSTANCE_JSON needs to be set"
|
||||
@@ -15,4 +15,4 @@ fi
|
||||
log "Resolved CURSE_INSTANCE_JSON as ${CURSE_INSTANCE_JSON}"
|
||||
|
||||
# Continue to Final Setup
|
||||
exec /start-finalSetup01World "$@"
|
||||
exec ${SCRIPTS:-/}start-finalSetupWorld "$@"
|
||||
|
||||
17
tests/docker-compose.test.yml
Normal file
17
tests/docker-compose.test.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
sut:
|
||||
depends_on:
|
||||
- mc
|
||||
image: itzg/mc-monitor:0.6.0
|
||||
command: status --host mc --retry-interval 1s --retry-limit 120
|
||||
mc:
|
||||
restart: "no"
|
||||
build:
|
||||
context: ..
|
||||
cache_from:
|
||||
- itzg/minecraft-server:latest
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
|
||||
17
tests/test.sh
Executable file
17
tests/test.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
cd $(dirname $0)
|
||||
|
||||
failed=false
|
||||
args="-f docker-compose.test.yml"
|
||||
docker-compose $args run sut || failed=true
|
||||
echo "
|
||||
Result: failed=$failed"
|
||||
|
||||
$failed && docker-compose $args logs mc
|
||||
docker-compose $args down -v
|
||||
|
||||
if $failed; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user