diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..a85e0e9ed --- /dev/null +++ b/.dockerignore @@ -0,0 +1,30 @@ +# Local volumes +/config +/data +/db + +# Updated through volumes +Server/data +Server/worldprops + +# Env files containing secrets +/.env +/*.env + +# Log files +logs +*.log + +# Git files +.git +.gitattributes +.gitignore + +# Basic stuff +*.md +LICENSE +.gitlab-ci.yml + +# Docker files +docker-compose.yml +Dockerfile diff --git a/.gitignore b/.gitignore index e1cc944e2..6ecd66985 100644 --- a/.gitignore +++ b/.gitignore @@ -18,7 +18,8 @@ Server/data/global_kill_stats.json Server/ge_test.db Server/latestdump.txt Management-Server/managementprops/ -Server/worldprops/ +Server/worldprops/* +!Server/worldprops/default.conf **/.idea/workspace.xml **/.idea/tasks.xml @@ -32,3 +33,12 @@ gradle build/kotlin/sessions/ **/*.iml Server/hasRan.txt + +# Local volumes +/config +/data +/db + +# Env files containing secrets +/.env +/*.env diff --git a/Dockerfile b/Dockerfile index 7078b8c93..5195e5bf4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,14 +4,8 @@ FROM maven:3-openjdk-11-slim # Set working directory to /app WORKDIR /app -# Update apt; install git and git-lfs -RUN apt-get update && apt-get -qq -y install git git-lfs - -# Clone the 2009scape repository -RUN git clone --depth=1 https://gitlab.com/2009scape/2009scape.git - -# Fake it til you make it - let's go home -WORKDIR /app/2009scape +# Copy all sources etc +COPY . . # Make sure ./run has permissions RUN chmod +x run diff --git a/README.md b/README.md index caf98bfe5..e986e4311 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,78 @@ Start the game server with the included run script. Use `./run -h` for more info Start the game server with `run-server.bat` +#### Docker + +Make sure [Docker Engine](https://docs.docker.com/engine/install/) & [Docker Compose](https://docs.docker.com/compose/install/) plugin are installed first: + +Go to the project root where the git repository is cloned into: + +```bash +cd /path/to/project-dir +``` + +To configure the database, copy the mysql env file template to a env file in the project root: + +```bash +cp mysql.env.example mysql.env +``` + +Customize the env file however necessary. + +Create a new directory called 'config' into the project root. + +```bash +mkdir config +``` + +Copy the server config file template in the config directory: + +```bash +cp Server/worldprops/default.conf config/default.conf +``` + +Edit the server configuration file as per needed. + +Go to the project root directory and execute: + +```bash +docker compose up --build +``` + +Which will build the docker image using the local Dockerfile and starts the server and database containers. + +The previous up command should be run every time the server sources are modified to propagate the changes to the container. + +For the first time, the server compilation process takes a long time. Grab some coffee in the meanwhile. + +You can check (and follow) the containers logs by running the following in the project root directory (-f for follow and Ctrl+C to stop): + +```bash +docker compose logs -f +``` + +Any compilation or runtime errors will be logged here. + +If you have already compiled the server and made no changes to the sources, you can simply run without the build option (however it will be cached anyways): + +```bash +docker compose up +``` + +To later restart the server to apply simple configuration changes, in the project root directory run: + +```bash +docker compose restart server +``` + +To shut down / take down the server, in the project root directory run: + +```bash +docker compose up --build +``` + +The database files, build cache and config files will be persisted on the host filesystem for easy backup management. + ### License We use the AGPL 3.0 license, which can be found [here](https://www.gnu.org/licenses/agpl-3.0.en.html). Please be sure to read and understand the license. Failure to follow the guidelines outlined in the license will result in legal action. If you know or hear of anyone breaking this license, please send a report, with proof, to Red Bracket#8151, ceikry#2724, or woahscam#8535 on discord or email woahscam@hotmail.com. **We WILL NOT change the license to fit your needs.** diff --git a/build b/build index 86471b26f..43f08b78b 100755 --- a/build +++ b/build @@ -2,139 +2,90 @@ SCRIPT_DIR=$(cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P) -BUILD_MS=0 +CLEAN=0 BUILD_GS=0 -CLEAN_MS=0 -CLEAN_GS=0 SKIPTEST="" GS_SRC=$SCRIPT_DIR/Server -MS_SRC=$SCRIPT_DIR/Management-Server -CLEANOPT="" _JAR_DIR="$SCRIPT_DIR/builddir" help() { - echo "Usage: $0 [-h] <-m | -g> [-c ] [-o ]"; + echo "Usage: $0 [-h] [-q] <-g|-c> [-o ]"; echo " -h: Display this message."; - echo " -m: Build the management server."; echo " -g: Build the game server."; - echo " -c: Clean: m: management, g: gameserver. " - echo " Can specify both. Need at least one if present."; - echo " -o: Specify jar-file directory." + echo " -c: Clean previous build."; + echo " -o: Specify jar-file directory."; echo " -q: Quick build - will skip tests."; } error() { - echo $1; - exit -1; -} - -clean_ms() -{ - cd $MS_SRC - - if [[ "$CLEANOPT" == *"m"* ]]; then - echo "Cleaning the management server." - sh mvnw clean || error "Failed to clean the MS." - fi + echo "$1"; + exit 1; } clean_gs() { - cd $GS_SRC; - if [[ "$CLEANOPT" == *"g"* ]]; then + cd $GS_SRC || error "Could not change dir to game server directory." echo "Cleaning the game server." - sh mvnw clean || error "Failed to clean the game server. Giving up." - fi -} - -build_ms() -{ - cd $MS_SRC - - sh mvnw package $SKIPTEST || \ - error "Failed to build the management server. Giving up"; + sh mvnw clean || error "Failed to clean the game server. Giving up." } build_gs() { - cd $GS_SRC; + cd "$GS_SRC" || error "ERROR: Could not chdir to server src. Abort." sh mvnw package $SKIPTEST || \ error "Failed to build the game server. Giving up." } -while getopts "hqmgc:o:d" arg; do +while getopts "hqgc:o:d" arg; do case $arg in h) help exit 0 ;; - m) - BUILD_MS=1 - ;; g) BUILD_GS=1 ;; c) - CLEANOPT=${OPTARG} + CLEAN=1 ;; o) _JAR_DIR=${OPTARG} ;; d) - echo "BUILD_MS=$BUILD_MS" - echo "BUILD_GS=$BUILD_GS" - echo "CLEANOPT=$CLEANOPT" echo "_JAR_DIR=$_JAR_DIR" ;; q) SKIPTEST="-DskipTests" ;; + *) + error "Argument -$arg is not a known or valid argument." + ;; esac done -if [[ $CLEANOPT != "m" ]] \ - && [[ $CLEANOPT != "g" ]] \ - && [[ $CLEANOPT != "mg" ]] \ - && [[ $CLEANOPT != "" ]]; -then - error "Invalid cleaning option '$CLEANOPT'. Valid options are 'm', 'g', 'mg' or none." +if [ $BUILD_GS -eq 0 ] && [ $CLEAN -eq 0 ]; then + error "Need to either build or clean at least. See -h for details." fi -if [ $BUILD_MS -eq 0 ] && [ $BUILD_GS -eq 0 ] && [[ $CLEANOPT == "" ]]; then - error "Need to build or clean at least one of the modules. See -h for details." -fi +# Inside func is cd so mgmt prob fails if no condition +(( CLEAN )) && clean_gs -# Conditionals inside the functions. -clean_gs -clean_ms # ----------- -if [ -d $_JAR_DIR ]; then - rm -r $_JAR_DIR +if [ -d "$_JAR_DIR" ]; then + rm -r "$_JAR_DIR" fi -if [ $BUILD_MS -ne 1 ] && [ $BUILD_GS -ne 1 ]; then - echo "No build options specified. Stop." - exit 0 -fi - -mkdir -p $_JAR_DIR || error "Failed to create build directory."; - -if [ $BUILD_MS -eq 1 ]; then - build_ms - - # Will never execute if build_ms fails because it quits upon failure. - mv -v $MS_SRC/target/*-with-dependencies.jar $_JAR_DIR/ms.jar -fi +mkdir -p "$_JAR_DIR" || error "Failed to create build directory."; if [ $BUILD_GS -eq 1 ]; then build_gs # Will never execute if build_gs fails because it quits upon failure. - mv -v $GS_SRC/target/*-with-dependencies.jar $_JAR_DIR/server.jar + mv -v "$GS_SRC"/target/*-with-dependencies.jar "$_JAR_DIR"/server.jar fi diff --git a/docker-compose.yml b/docker-compose.yml index 02614f351..3c192f791 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,29 +1,33 @@ -version: '3.3' services: - app: + server: build: . - container_name: "2009scape_app" depends_on: - - database - restart: unless-stopped - volumes: - - "2009scape_app:/app" - ports: - - "43595:43595" - - database: - image: mysql:5.7 - container_name: "2009scape_db" + - db restart: always - ports: - - "3306:3306" volumes: - - "2009scape_db:/var/lib/mysql" + - "bcache:/app/Server/target" + - "mcache:/root/.m2" + - "./Server/data:/app/Server/data" + - "./config:/app/Server/worldprops" + ports: + - "43594-43600:43594-43600" + + db: + # current LTS (Long-Term Support) version + image: mariadb:11.4-noble + healthcheck: + test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] + start_period: 30s + interval: 60s + timeout: 10s + retries: 3 + restart: always + volumes: + - "./db:/var/lib/mysql" - "./Server/db_exports/global.sql:/docker-entrypoint-initdb.d/global.sql" - environment: - MYSQL_ALLOW_EMPTY_PASSWORD: "yes" - MYSQL_ROOT_PASSWORD: "" - MYSQL_ROOT_USER: "root" + env_file: + - mysql.env + volumes: - 2009scape_app: - 2009scape_db: + bcache: + mcache: diff --git a/mysql.env.example b/mysql.env.example new file mode 100644 index 000000000..8772412d4 --- /dev/null +++ b/mysql.env.example @@ -0,0 +1,20 @@ +# Prefer no and generating a strong password for the root (+ special) user +MYSQL_ALLOW_EMPTY_PASSWORD="no" + +# You can change the db name also for obscurity. +# Has to be changed in the default.conf and in the global.sql init file then also. +MYSQL_DATABASE="global" + +# Beware: if not using root user, the database 'global' requires granting permissions for that user +# Root user is created automatically so dont provide it here. +#MYSQL_USER="dbuser" +#MYSQL_PASSWORD="CHANGEMEIFNOTUSINGROOTANDINGLOBALCONF" + +# Comment this out if you are using random root pw (below). +MYSQL_ROOT_PASSWORD="ALWAYSCHANGEMEHEREANDINGLOBALCONFIFUSINGROOT" + +# Or you can use a special non-root db user and generate a random pw for the root user instead. +# To improve security +# However, either initial root user access +# or editing Server/db_exports/global.sql to add grants for 'global' to the special user above. +MYSQL_RANDOM_ROOT_PASSWORD="no" diff --git a/run b/run index e1c4fdc10..a854c3200 100755 --- a/run +++ b/run @@ -3,15 +3,11 @@ SCRIPT_DIR=$(cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P) LOG_DIR=$SCRIPT_DIR/logs BUILD_DIR=$SCRIPT_DIR/builddir GS_SRC=$SCRIPT_DIR/Server -MS_SRC=$SCRIPT_DIR/Management-Server FORCE_REBUILD=0 REFRESH_BUILD=1 -GAMESERVER_ONLY=1 - GS_EXEC="cd $GS_SRC && java -Dnashorn.args=--no-deprecation-warning -jar $BUILD_DIR/server.jar" -MS_EXEC="cd $MS_SRC && java -Dnashorn.args=--no-deprecation-warning -jar $BUILD_DIR/ms.jar" # 0: parallel # 1: fancy tmux @@ -20,13 +16,12 @@ RUN_MODE=0 help() { - echo "Usage: $0 [-h] [-q] [-r] [-t] [-x] [-g] [-e ] [-o ]" + echo "Usage: $0 [-h] [-q] [-r] [-t] [-x] [-e ] [-o ]" echo " -h: Display this message." echo " -q: Don't perform the incremental build." echo " -r: Force clean rebuild." echo " -t: Only run tests, not the JARs." echo " -x: Run in a fancy tmux session." - echo " -g: Build + run only the game server (no management server)." echo " -e: Write STDERR to 'logs/filename' as well as the terminal."; echo " -o: Write STDOUT to 'logs/filename' as well as the terminal." } @@ -39,31 +34,17 @@ error() rebuild_project() { - if [ $GAMESERVER_ONLY ]; then - $SCRIPT_DIR/build -qgcg - else - $SCRIPT_DIR/build -qmgcmg - fi + "$SCRIPT_DIR/build" -qgc } refresh_project() { - if [ $GAMESERVER_ONLY ]; then - $SCRIPT_DIR/build -qg - else - $SCRIPT_DIR/build -qmg - fi + "$SCRIPT_DIR/build" -qg } verify_binaries_exist() { - if ! [ $GAMESERVER_ONLY ]; then - if [ ! -f $SCRIPT_DIR/builddir/ms.jar ]; then - error "Management server binary does not exist."; - fi - fi - - if [ ! -f $SCRIPT_DIR/build/server.jar ]; then + if [ ! -f "$SCRIPT_DIR/build/server.jar" ]; then error "Game server binary does not exist."; fi } @@ -76,11 +57,7 @@ run_server_parallel() echo "Running in parallel. All logs redirected to proper files." - if [ $GAMESERVER_ONLY ]; then - sh -c "$GS_EXEC" & wait - else - sh -c "$MS_EXEC > $LOG_DIR/ms_stdout.log 2> $LOG_DIR/ms_stderr.log & $GS_EXEC" & wait - fi + sh -c "$GS_EXEC" & wait } run_server_tmux() @@ -89,21 +66,16 @@ run_server_tmux() error "tmux is not installed. Install tmux or don't use this option." fi - if [ $GAMESERVER_ONLY ]; then - tmux new-session "$GS_EXEC" - else - tmux new-session "$MS_EXEC" \; \ - split-window -h "$GS_EXEC" - fi + tmux new-session "$GS_EXEC" } run_server_tests() { - cd "$GS_SRC" || error "Could not change to GameServer source directory." + cd "$GS_SRC" || error "Could not change to game server source directory." sh mvnw test } -while getopts ":ghqrtxe:o:" arg; do +while getopts ":hqrtxe:o:" arg; do case $arg in h) help @@ -127,9 +99,6 @@ while getopts ":ghqrtxe:o:" arg; do x) RUN_MODE=1 ;; - g) - GAMESERVER_ONLY=0 - ;; *) error "Argument -$arg is not a known or valid argument." ;; diff --git a/run-ms.bat b/run-ms.bat deleted file mode 100644 index 494ccb692..000000000 --- a/run-ms.bat +++ /dev/null @@ -1,8 +0,0 @@ -@echo off -cd Management-Server - -if NOT exist DoNotCreateThisFile.txt ( - .\mvnw.cmd package -DskipTests - xcopy /Y target\*-with-dependencies.jar ms.jar* - java -jar ms.jar -) \ No newline at end of file