diff --git a/playbooks/gameservers.yml b/playbooks/gameservers.yml index 26ed91f..24ec9f6 100644 --- a/playbooks/gameservers.yml +++ b/playbooks/gameservers.yml @@ -15,15 +15,27 @@ gitweb_url: "thefuck.how" gitweb_webroot: "/var/www/thefuck.how" tags: [ web, webroot ] - - role: minecraft-forge + - role: minecraft vars: - mcname: valhelsia - mczip: "https://media.forgecdn.net/files/3110/654/Valhelsia_SERVER-pre5-3.1.0.zip" - mcmotd: "Brett's new serber, modded edition" - mcforge: 1.16.3-34.1.42 - mcheapmax: 5120 - mcport: 25566 - mcviewdist: 10 + minecraft_name: valhelsia + minecraft_version: 1.16.3 + minecraft_jre_xmx: 5G + minecraft_server_properties: + - opt: difficulty + value: hard + - opt: motd + value: "Brett's new serber, modded edition" + - opt: server-port + value: 25566 + - opt: view-distance + value: 10 + minecraft_forge_install: yes + minecraft_forge_version: 34.1.42 + minecraft_forge_packurl: "https://media.forgecdn.net/files/3110/654/Valhelsia_SERVER-pre5-3.1.0.zip" + minecraft_forge_mods: + - "https://media.forgecdn.net/files/3091/862/ftb-gui-library-1603.1.1.25.jar" + - "https://media.forgecdn.net/files/3105/153/ftb-chunks-1603.2.0.43.jar" + become: yes tags: [ gameserver, minecraft, forge, valhelsia ] - role: minecraft-paper vars: diff --git a/roles/minecraft-forge/defaults/main.yml b/roles/minecraft-forge/defaults/main.yml deleted file mode 100644 index 04cc59e..0000000 --- a/roles/minecraft-forge/defaults/main.yml +++ /dev/null @@ -1,10 +0,0 @@ -# vim:ft=ansible: -mcname: "default" -mcport: "25565" -mcmotd: "An Ansible-deployed Minecraft server" -mcleveltype: "default" -mcgensettings: "" -mcgamemode: 0 -mcheapmax: 4096 -mcheapmin: 1024 -mcviewdist: 12 diff --git a/roles/minecraft-forge/files/eula.txt b/roles/minecraft-forge/files/eula.txt deleted file mode 100644 index 9fa0066..0000000 --- a/roles/minecraft-forge/files/eula.txt +++ /dev/null @@ -1,2 +0,0 @@ -# Yes, we accept the EULA -eula=true diff --git a/roles/minecraft-forge/meta/main.yml b/roles/minecraft-forge/meta/main.yml deleted file mode 100644 index 0959eab..0000000 --- a/roles/minecraft-forge/meta/main.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -allow_duplicates: yes -dependencies: - - role: awscreds diff --git a/roles/minecraft-forge/tasks/main.yml b/roles/minecraft-forge/tasks/main.yml deleted file mode 100644 index 0af30d5..0000000 --- a/roles/minecraft-forge/tasks/main.yml +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/bin/ansible-playbook -# vim:ft=ansible: ---- -- name: Set up Minecraft user - block: - - name: Install required packages - apt: - name: "{{ packages }}" - vars: - packages: - - openjdk-8-jre - - screen - - unzip - - name: Assure minecraft admin group - group: - name: minecraft - - name: Assure server user - user: - name: minecraft - group: minecraft - system: yes - home: /var/minecraft - - name: Assure var directory - file: - path: /var/minecraft - state: directory - owner: root - group: minecraft - # Sticky, SetGID - mode: "3770" - - name: Assure systemd unit - template: - src: "minecraft@.service" - dest: "/etc/systemd/system/minecraft@.service" - - name: Reload available daemons - systemd: - daemon_reload: yes - become: yes -- name: Set up Minecraft server - block: - - name: Create server directory - file: - path: "/var/minecraft/{{ mcname }}" - state: directory - - name: Download zip - get_url: - dest: "/var/minecraft/{{ mcname }}/modpack.zip" - url: "{{ mczip }}" - register: get_mcpack - - name: Template out scripts - template: - src: "{{ item.src }}" - dest: "/var/minecraft/{{ mcname }}/{{ item.dest }}" - mode: "{{ item.mode }}" - loop: - - { src: "install.sh", dest: "install.sh", mode: "0755" } - - { src: "recover.sh", dest: "recover.sh", mode: "0755" } - - name: Install modpack - block: - - name: Disable service - systemd: - name: "minecraft@{{ mcname }}" - state: stopped - become: yes - become_user: root - - name: Remove remnants of old pack - file: - path: "{{ item }}" - state: absent - loop: - - "/var/minecraft/{{ mcname }}/config" - - "/var/minecraft/{{ mcname }}/coremods" - - "/var/minecraft/{{ mcname }}/local" - - "/var/minecraft/{{ mcname }}/mods" - - "/var/minecraft/{{ mcname }}/scripts" - - "/var/minecraft/{{ mcname }}/server.jar" - - name: Unpack zip - unarchive: - src: "/var/minecraft/{{ mcname }}/modpack.zip" - remote_src: yes - dest: "/var/minecraft/{{ mcname }}" - notify: "restart minecraft {{ mcname }}" - - name: Run install script - command: - chdir: "/var/minecraft/{{ mcname }}" - argv: - - bash - - "./install.sh" - notify: "restart minecraft {{ mcname }}" - when: get_mcpack is changed - - name: Check for Forge - stat: - path: "/var/minecraft/{{ mcname }}/server.jar" - register: stat_mcroot_forgejar - - name: Install Forge - block: - - name: Download Forge - get_url: - dest: "/var/minecraft/{{ mcname }}/installer.jar" - # Accurate as of 2020-02-23 - url: "https://files.minecraftforge.net/maven/net/minecraftforge/forge/{{ mcforge }}/forge-{{ mcforge }}-installer.jar" - register: get_forge - - name: Install Forge - # Note: This also installs a Minecraft server, thankfully - command: - chdir: "/var/minecraft/{{ mcname }}" - argv: - - /usr/bin/java - - "-jar" - - "/var/minecraft/{{ mcname }}/installer.jar" - - "--installServer" - args: - creates: "/var/minecraft/{{ mcname }}/forge-{{ mcforge }}-universal.jar" - - name: Find classic jar name - stat: - path: "/var/minecraft/{{ mcname }}/forge-{{ mcforge }}-universal.jar" - register: stat_mcroot_newjar - - name: Link old-style server jar - file: - path: "/var/minecraft/{{ mcname }}/server.jar" - src: "/var/minecraft/{{ mcname }}/forge-{{ mcforge }}-universal.jar" - state: link - when: stat_mcroot_newjar.stat.exists - - name: Link new-style server jar - file: - path: "/var/minecraft/{{ mcname }}/server.jar" - src: "/var/minecraft/{{ mcname }}/forge-{{ mcforge }}.jar" - state: link - when: not stat_mcroot_newjar.stat.exists - when: not stat_mcroot_forgejar.stat.exists - - name: Check for world - stat: - path: "/var/minecraft/{{ mcname }}/world" - register: stat_mcroot_world - - name: Recover world, if available - block: - - name: Stop server - systemd: - name: "minecraft@{{ mcname }}" - state: stopped - - name: Run recover script - command: - chdir: "/var/minecraft/{{ mcname }}" - argv: - - bash - - "./recover.sh" - notify: "restart minecraft {{ mcname }}" - become: yes - become_user: root - - name: Change permissions of world - file: - path: "/var/minecraft/{{ mcname }}/world" - state: directory - owner: minecraft - group: minecraft - when: not stat_mcroot_world.stat.exists - - name: Configure server - block: - - name: Template out server.properties - template: - src: server.properties - dest: "/var/minecraft/{{ mcname }}/server.properties" - - name: Accept EULA - copy: - src: "eula.txt" - dest: "/var/minecraft/{{ mcname }}/eula.txt" - become: yes - become_user: minecraft -- name: Set up system - block: - - name: Enable service - systemd: - name: "minecraft@{{ mcname }}" - enabled: yes - state: started - - name: Template out backup module - template: - src: "backup.sh" - dest: "/opt/backups/modules/minecraft-{{ mcname }}.sh" - mode: "0600" - become: yes diff --git a/roles/minecraft-forge/templates/install.sh b/roles/minecraft-forge/templates/install.sh deleted file mode 100644 index 5d33b55..0000000 --- a/roles/minecraft-forge/templates/install.sh +++ /dev/null @@ -1,33 +0,0 @@ -#! /bin/sh -# -# install.sh -# Because writing this logic in Ansible is kinda dumb -# Copyright (C) 2020 Vintage Salt -# -# Distributed under terms of the MIT license. -# - -set -e - -# Get to our magic dir -export MINECRAFT_DIR="/var/minecraft/{{ mcname }}" -cd "$MINECRAFT_DIR" || exit 50 - -# If the mods and config directories exist, we don't need to do anything -# We make the inference here because the previous step of the playbook removed them -if [ -d "mods" ]; then - exit 0 -fi - -# MultiMC packs are organized as such: -# ./Pack Name/.minecraft/{mods,configs,etc.} -# ./Pack Name/minecraft/{mods,configs,etc.} -# I'm going to elect not to support the latter just for the sake of my sanity -packdir="$(find -type d -iname ".minecraft" | head -n 1)" -if ! [ -d "$packdir" ]; then - exit 51 -fi -# Just move the shit out 4head -mv -f "$packdir"/* . -exit 0 - diff --git a/roles/minecraft-forge/templates/recover.sh b/roles/minecraft-forge/templates/recover.sh deleted file mode 100644 index 5728191..0000000 --- a/roles/minecraft-forge/templates/recover.sh +++ /dev/null @@ -1,57 +0,0 @@ -#! /bin/sh -# -# recover.sh -# Recover a Minecraft world save from our S3 bucket -# Copyright (C) 2020 Vintage Salt -# -# Distributed under terms of the MIT license. -# - -set -e - -# Get to our magic dir -export MINECRAFT_DIR="/var/minecraft/{{ mcname }}" -cd "$MINECRAFT_DIR" || exit 50 - -# Make sure we have a backup -if ! aws s3 ls "s3://{{ aws.backup_bucket }}/{{ mcname }}/" > /dev/null 2>&1; then - echo "No backups available" - exit 0 -fi -# If the world directory exists, we need to ensure that we don't clobber it -if [ -d "world" ]; then - echo "Backing up current world" - tar czf "recover-world-$(date -Iseconds).tar.gz" world --remove-files --force-local -fi -# If it STILL exists, then we have a problem -if [ -d "world" ]; then - echo "World was found to exist after tarring; bailing" - exit 51 -fi - -# Get our latest good backup -backup="$(aws s3 ls "s3://{{ aws.backup_bucket }}/{{ mcname }}/" | tail -n 1 | awk '{print $4}')" -echo "Restoring backup: $backup" -aws s3 cp "s3://{{ aws.backup_bucket }}/{{ mcname }}/$backup" world.tgz -# Decompress it -tar xzf world.tgz -# Find the world -worlddir="$(find ./var -type d -name "world" | head -n 1)" -# Move it in place -mv "$worlddir" . -# Verify our work -if [ -f "world/level.dat" ]; then - echo "Recovered from backup: $backup" -else - echo "Failed to recover from backup: $backup" -fi -# Remove the var dir, if it exists, because that's what it ends up being named -if [ -d "var" ]; then - # Never use relative paths with rm in a script - # That's heresy - rm -rf "/var/minecraft/{{ mcname }}/var" -fi -# Remove our old world.tgz -if [ -f "world.tgz" ]; then - rm "/var/minecraft/{{ mcname }}/world.tgz" -fi diff --git a/roles/minecraft-forge/templates/server.properties b/roles/minecraft-forge/templates/server.properties deleted file mode 100644 index d825054..0000000 --- a/roles/minecraft-forge/templates/server.properties +++ /dev/null @@ -1,38 +0,0 @@ -# Minecraft server properties -allow-flight=true -allow-nether=true -difficulty=3 -enable-command-block=true -enable-query=false -enable-rcon=false -force-gamemode=false -gamemode={{ mcgamemode }} -generate-structures=true -generator-settings={{ mcgensettings }} -hardcore=false -level-name=world -level-seed= -level-type={{ mcleveltype }} -max-build-height=256 -max-players=8 -max-tick-time=60000 -max-world-size=29999984 -motd={{ mcmotd }} -network-compression-threshold=256 -online-mode=true -op-permission-level=4 -player-idle-timeout=0 -prevent-proxy-connections=false -pvp=true -resource-pack= -resource-pack-sha1= -server-ip= -server-port={{ mcport }} -snooper-enabled=false -spawn-animals=true -spawn-monsters=true -spawn-npcs=true -spawn-protection=0 -use-native-transport=true -view-distance={{ mcviewdist }} -white-list=false diff --git a/roles/minecraft/defaults/main.yml b/roles/minecraft/defaults/main.yml new file mode 100644 index 0000000..77c7f5b --- /dev/null +++ b/roles/minecraft/defaults/main.yml @@ -0,0 +1,41 @@ +# vim:ft=ansible: +minecraft_name: default +minecraft_version: 1.16.3 +# minecraft_forge_version: You tell me + +# Packages +# Put any extra dependencies (for mods, etc.) in _extra +minecraft_packages: + - openjdk-8-jre + - screen +minecraft_packages_extra: [] + +# Addon configuration +# You'll probably want to enable one of these +minecraft_paper_install: no +minecraft_paper_downloadurl: "https://papermc.io/api/v1/paper/{{ minecraft_version }}/latest/download" +minecraft_forge_install: no +minecraft_forge_downloadurl: "https://files.minecraftforge.net/maven/net/minecraftforge/forge/{{ minecraft_version }}-{{ minecraft_forge_version }}/forge-{{ minecraft_version }}-{{ minecraft_forge_version }}-installer.jar" +# Define this if you already have a modpack zipped up and ready to go +#minecraft_forge_packurl: https://path.to.your/modpack.zip +# Define THIS if you want to download a bunch of mods by JAR URL: +minecraft_forge_mods: [] +minecraft_vanilla_install: no +minecraft_vanilla_downloadurl: "https://launcher.mojang.com/v1/objects/35139deedbd5182953cf1caa23835da59ca3d7cd/server.jar" + +# Service configuration +minecraft_home: /opt/minecraft +minecraft_stop_message: "Server is going down for maintenance" + +# Java configuration +minecraft_jre_xms: 2048m +minecraft_jre_xmx: 4096m + +# Minecraft configuration +# Contains key-value pairs that will be lineinfile'd into server.properties +# Example: +# minecraft_server_properties: +# - { opt: allow-flight, value: "false" } +# - opt: gamemode +# value: 0 +minecraft_server_properties: {} diff --git a/roles/minecraft-forge/handlers/main.yml b/roles/minecraft/handlers/main.yml similarity index 51% rename from roles/minecraft-forge/handlers/main.yml rename to roles/minecraft/handlers/main.yml index b3fa49a..a9003dc 100644 --- a/roles/minecraft-forge/handlers/main.yml +++ b/roles/minecraft/handlers/main.yml @@ -1,8 +1,8 @@ #!/usr/bin/ansible-playbook # vim:ft=ansible: --- -- name: "restart minecraft {{ mcname }}" +- name: "restart minecraft {{ minecraft_name }}" systemd: - name: "minecraft@{{ mcname }}" + name: "minecraft@{{ minecraft_name }}" state: restarted become: yes diff --git a/roles/minecraft/tasks/main.yml b/roles/minecraft/tasks/main.yml new file mode 100644 index 0000000..ade7d7f --- /dev/null +++ b/roles/minecraft/tasks/main.yml @@ -0,0 +1,75 @@ +#!/usr/bin/ansible-playbook +# vim:ft=ansible: +--- +- name: set up system + block: + - name: install required packages + apt: name="{{ minecraft_packages + minecraft_packages_extra }}" + - name: assure server user + user: name=minecraft system=yes home={{ minecraft_home }} + - name: assure operational directory + file: path={{ minecraft_home }} state=directory owner=minecraft group=minecraft mode="3775" + - name: assure backup script + template: src=backup.sh dest=/opt/backups/modules/minecraft-{{ minecraft_name }}.sh + - name: assure systemd unit + template: src=minecraft@.service dest=/etc/systemd/system/minecraft@.service + notify: "restart minecraft {{ minecraft_name }}" +- name: set up minecraft + block: + - name: assure server directory + file: path={{ minecraft_home }}/{{ minecraft_name }} state=directory + - name: accept eula + template: src=eula.txt dest={{ minecraft_home }}/{{ minecraft_name }}/eula.txt + - name: configure server properties + lineinfile: + dest: "{{ minecraft_home }}/{{ minecraft_name }}/server.properties" + line: "{{ item.opt }}={{ item.value }}" + regex: "^{{ item.opt }}=.*" + create: yes + loop: "{{ minecraft_server_properties }}" + notify: "restart minecraft {{ minecraft_name }}" + become: yes + become_user: minecraft +- name: set up forge + block: + - name: template out modpack installer + template: src=install-modpack.sh dest={{ minecraft_home }}/{{ minecraft_name }}/install-modpack.sh mode="0755" + - name: download forge + get_url: dest={{ minecraft_home }}/{{ minecraft_name }}/installer.jar url={{ minecraft_forge_downloadurl }} + register: download_forge + - name: install forge + command: + chdir: "{{ minecraft_home }}/{{ minecraft_name }}" + argv: [ "/usr/bin/java", "-jar", "./installer.jar", "--installServer" ] + notify: restart minecraft {{ minecraft_name }} + when: download_forge is changed + - name: link to forge jar + file: path={{ minecraft_home }}/{{ minecraft_name }}/server.jar src=forge-{{ minecraft_version }}-{{ minecraft_forge_version }}.jar state=link + - name: install modpack + block: + - name: download modpack + get_url: dest={{ minecraft_home }}/{{ minecraft_name }}/modpack.zip url={{ minecraft_forge_packurl }} + register: download_modpack + - name: install modpack + block: + - name: assure modpack unzip directory + file: path={{ minecraft_home }}/{{ minecraft_name }}/modpack state=directory + - name: unpack zip + unarchive: src={{ minecraft_home }}/{{ minecraft_name }}/modpack.zip dest={{ minecraft_home }}/{{ minecraft_name }}/modpack remote_src=yes + - name: run installer + command: + chdir: "{{ minecraft_home }}/{{ minecraft_name }}" + argv: [ "bash", "./install-modpack.sh" ] + notify: "restart minecraft {{ minecraft_name }}" + when: download_modpack is changed + when: minecraft_forge_packurl is defined + - name: install mods + get_url: dest="{{ minecraft_home }}/{{ minecraft_name }}/mods" url={{ item }} + loop: "{{ minecraft_forge_mods }}" + notify: restart minecraft {{ minecraft_name }} + when: minecraft_forge_mods is iterable and minecraft_forge_mods != None + become: yes + become_user: minecraft + when: minecraft_forge_install and minecraft_forge_version is defined +- name: enable service + systemd: name=minecraft@{{ minecraft_name }}.service enabled=yes state=started diff --git a/roles/minecraft-forge/templates/backup.sh b/roles/minecraft/templates/backup.sh similarity index 50% rename from roles/minecraft-forge/templates/backup.sh rename to roles/minecraft/templates/backup.sh index 55530ef..1fd1932 100644 --- a/roles/minecraft-forge/templates/backup.sh +++ b/roles/minecraft/templates/backup.sh @@ -1,6 +1,6 @@ #! /bin/bash # -# minecraft.sh +# minecraft-{{ minecraft_name }}.sh # Backup script for Minecraft. Meant to be sourced by our main backup script # Copyright (C) 2020 Vintage Salt # @@ -9,8 +9,7 @@ set -e -export OUTDIR="$BACKUPSDIR/{{ mcname }}" -retention=7 # 7-day retention period +export OUTDIR="$BACKUPSDIR/{{ minecraft_name }}" # Sanity checks if [ -z "$BACKUPSDIR" ]; then @@ -24,15 +23,10 @@ if ! [ -d "$OUTDIR" ]; then fi fi -# Purge oldest backup if we need to -currentbackupcount="$(ls -1 "$OUTDIR" | wc -l)" -if (( currentbackupcount >= retention )); then - lastbackup="$(find "$OUTDIR" -name \*.tar.gz 2>/dev/null | sort | head -n 1)" - if [ -f "$lastbackup" ]; then - log "Removing old backup: $lastbackup" - rm "$lastbackup" - fi -fi # WE MAKE BACKUP NOW SERGEI -tar czf "$OUTDIR/{{ mcname }}-$(date -Iseconds)-world.tar.gz" "/var/minecraft/{{ mcname }}/world" +tar czf "$OUTDIR/{{ minecraft_name }}-$(date -Iseconds)-full.tar.gz" \ + --exclude "{{ minecraft_home }}/{{ minecraft_name }}/backups" \ + --exclude "{{ minecraft_home }}/{{ minecraft_name }}/crash-reports" \ + --exclude "{{ minecraft_home }}/{{ minecraft_name }}/logs" \ + "/{{ minecraft_home }}/{{ minecraft_name }}/" diff --git a/roles/minecraft/templates/eula.txt b/roles/minecraft/templates/eula.txt new file mode 100644 index 0000000..b0cf95f --- /dev/null +++ b/roles/minecraft/templates/eula.txt @@ -0,0 +1,2 @@ +# Tacos best food yadda yadda +eula=true diff --git a/roles/minecraft/templates/install-modpack.sh b/roles/minecraft/templates/install-modpack.sh new file mode 100644 index 0000000..8c56734 --- /dev/null +++ b/roles/minecraft/templates/install-modpack.sh @@ -0,0 +1,15 @@ +#! /bin/sh + +# Find out where our modpack lives +# +# This assumes that we have no directories adjacent to the actual pack dir +# that contain a directory called "mods" +# +# If that's not the case, the onus is on you to fix your shit and/or repack +# the server zip +# +directory="$(find modpack/ -type d -iname "mods" -execdir pwd \; | head -n 1)" +echo "Syncing from $directory/" + +# Now we rsync everything from that directory here, which should set us up +rsync -av "$directory"/ ./ diff --git a/roles/minecraft-forge/templates/minecraft@.service b/roles/minecraft/templates/minecraft@.service similarity index 88% rename from roles/minecraft-forge/templates/minecraft@.service rename to roles/minecraft/templates/minecraft@.service index 7b4da21..c13de59 100644 --- a/roles/minecraft-forge/templates/minecraft@.service +++ b/roles/minecraft/templates/minecraft@.service @@ -11,7 +11,7 @@ After=network.target [Service] User=minecraft Group=minecraft -WorkingDirectory=/var/minecraft/%i +WorkingDirectory={{ minecraft_home }}/%i PrivateUsers=true ProtectSystem=full ProtectHome=true @@ -22,7 +22,7 @@ ProtectKernelModules=true # Implies MountAPIVFS=yes ProtectControlGroups=true -ExecStart=/bin/sh -c '/usr/bin/screen -DmS %i /usr/bin/java -Xms{{ mcheapmin }}M -Xmx{{ mcheapmax }}M -jar server.jar nogui' +ExecStart=/bin/sh -c '/usr/bin/screen -DmS %i /usr/bin/java -Xms{{ minecraft_jre_xms }} -Xmx{{ minecraft_jre_xmx }} -jar server.jar nogui' ExecReload=/usr/bin/screen -p 0 -S %i -X eval 'stuff "reload"\\015'