ansible: retire Minecraft Fossils
The Fabric server holds 8.8 GB of asxpio-services' 15 GB of RAM, more than everything else on the host together, and the XMPP server moves here next. Save the world, remove its containers and the daily restart timer. The world stays in /opt/minecraft-fossils/data, and in the restic backups, until it is deleted by hand. Assisted-by: Claude:opus-5-5
This commit is contained in:
parent
59b5b4468a
commit
f2aa6375fd
7 changed files with 34 additions and 155 deletions
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
minecraft_fossils_owner: asxpi
|
|
||||||
minecraft_fossils_rcon_password: "{{ vault_minecraft_fossils_rcon_password }}"
|
|
||||||
minecraft_fossils_cf_api_key: "{{ vault_minecraft_fossils_cf_api_key }}"
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
services:
|
|
||||||
minecraft-fossils:
|
|
||||||
image: itzg/minecraft-server:java21
|
|
||||||
container_name: minecraft-fossils
|
|
||||||
restart: unless-stopped
|
|
||||||
stop_grace_period: 2m
|
|
||||||
stdin_open: true
|
|
||||||
tty: true
|
|
||||||
ports:
|
|
||||||
- "25566:25565"
|
|
||||||
env_file:
|
|
||||||
- secrets.env
|
|
||||||
environment:
|
|
||||||
EULA: "TRUE"
|
|
||||||
TYPE: FABRIC
|
|
||||||
VERSION: "1.20.1"
|
|
||||||
FABRIC_LOADER_VERSION: "0.18.4"
|
|
||||||
MEMORY: "8G"
|
|
||||||
ONLINE_MODE: "FALSE"
|
|
||||||
ENFORCE_WHITELIST: "TRUE"
|
|
||||||
ENFORCE_SECURE_PROFILE: "FALSE"
|
|
||||||
WHITELIST_FILE: /data/whitelist.json
|
|
||||||
OPS_FILE: /data/ops.json
|
|
||||||
ENABLE_RCON: "TRUE"
|
|
||||||
MOTD: "[mc.czsk.dev] Fossils Archaeology Revival: Genesis"
|
|
||||||
USE_AIKAR_FLAGS: "TRUE"
|
|
||||||
volumes:
|
|
||||||
- /opt/minecraft-fossils/data:/data
|
|
||||||
networks:
|
|
||||||
- fossils
|
|
||||||
|
|
||||||
whitelist-sync:
|
|
||||||
image: alpine:3
|
|
||||||
container_name: minecraft-fossils-wlsync
|
|
||||||
restart: unless-stopped
|
|
||||||
depends_on:
|
|
||||||
- minecraft-fossils
|
|
||||||
volumes:
|
|
||||||
- /opt/minecraft:/src:ro
|
|
||||||
- /opt/minecraft-fossils/data:/dst
|
|
||||||
env_file:
|
|
||||||
- secrets.env
|
|
||||||
environment:
|
|
||||||
RCON_HOST: minecraft-fossils
|
|
||||||
INTERVAL: "15"
|
|
||||||
command:
|
|
||||||
- sh
|
|
||||||
- -c
|
|
||||||
- |
|
|
||||||
apk add --no-cache python3 >/dev/null
|
|
||||||
cat > /rcon.py <<'PY'
|
|
||||||
import socket, struct, sys, os
|
|
||||||
host, port, pw, cmd = os.environ["RCON_HOST"], 25575, os.environ["RCON_PASSWORD"], sys.argv[1]
|
|
||||||
def pkt(i, t, b): p = struct.pack("<ii", i, t) + b.encode() + b"\x00\x00"; return struct.pack("<i", len(p)) + p
|
|
||||||
def recv(s):
|
|
||||||
ln = struct.unpack("<i", s.recv(4))[0]; d = b""
|
|
||||||
while len(d) < ln: d += s.recv(ln - len(d))
|
|
||||||
return struct.unpack("<ii", d[:8])[0], d[8:-2].decode(errors="replace")
|
|
||||||
s = socket.create_connection((host, port), timeout=5)
|
|
||||||
s.send(pkt(1, 3, pw))
|
|
||||||
rid, _ = recv(s)
|
|
||||||
if rid == -1: print("auth failed"); sys.exit(1)
|
|
||||||
s.send(pkt(2, 2, cmd))
|
|
||||||
_, out = recv(s); print(out)
|
|
||||||
PY
|
|
||||||
echo "[wlsync] started, interval=$${INTERVAL}s"
|
|
||||||
while true; do
|
|
||||||
for f in whitelist.json ops.json banned-players.json banned-ips.json; do
|
|
||||||
if [ -f /src/$$f ] && ! cmp -s /src/$$f /dst/$$f 2>/dev/null; then
|
|
||||||
cp /src/$$f /dst/$$f
|
|
||||||
echo "[wlsync] copied $$f"
|
|
||||||
case $$f in
|
|
||||||
whitelist.json) CMD="whitelist reload" ;;
|
|
||||||
ops.json) CMD="reload" ;;
|
|
||||||
banned-players.json|banned-ips.json) CMD="kick @a Ban list updated" ;;
|
|
||||||
esac
|
|
||||||
python3 /rcon.py "$$CMD" 2>&1 | sed 's/^/[wlsync] rcon: /' || echo "[wlsync] rcon failed"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
sleep $$INTERVAL
|
|
||||||
done
|
|
||||||
networks:
|
|
||||||
- fossils
|
|
||||||
|
|
||||||
networks:
|
|
||||||
fossils:
|
|
||||||
driver: bridge
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=Daily restart of minecraft-fossils container
|
|
||||||
Requires=docker.service
|
|
||||||
After=docker.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=oneshot
|
|
||||||
ExecStart=/usr/bin/docker restart minecraft-fossils
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=Restart minecraft-fossils daily at 08:00 Europe/Tallinn
|
|
||||||
|
|
||||||
[Timer]
|
|
||||||
OnCalendar=*-*-* 08:00:00 Europe/Tallinn
|
|
||||||
Persistent=true
|
|
||||||
Unit=minecraft-fossils-restart.service
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=timers.target
|
|
||||||
|
|
@ -1,49 +1,39 @@
|
||||||
---
|
---
|
||||||
# Fabric server plus a sidecar that mirrors the whitelist, ops and ban
|
# Retired: the Fabric server is stopped for good to free its 8 GB of
|
||||||
# lists from the Paper server. World data in /opt/minecraft-fossils/data
|
# RAM. The world stays in /opt/minecraft-fossils/data (and in the restic
|
||||||
# is not managed here. A compose change recreates the container, so it
|
# backups) until it is deleted by hand.
|
||||||
# is saved and stopped with time to finish first.
|
- name: Check for the old deployment
|
||||||
- name: Deploy Minecraft Fossils
|
ansible.builtin.stat:
|
||||||
ansible.builtin.include_role:
|
path: /opt/minecraft-fossils/docker-compose.yml
|
||||||
name: docker_service
|
register: fossils_compose
|
||||||
vars:
|
|
||||||
service_name: "minecraft-fossils"
|
|
||||||
service_base_path: "{{ services_base_path }}/minecraft-fossils"
|
|
||||||
service_templates:
|
|
||||||
- src: "secrets.env.j2"
|
|
||||||
dest: "secrets.env"
|
|
||||||
owner: "{{ minecraft_fossils_owner }}"
|
|
||||||
group: "{{ minecraft_fossils_owner }}"
|
|
||||||
mode: "0600"
|
|
||||||
service_files:
|
|
||||||
- src: "docker-compose.yml"
|
|
||||||
dest: "docker-compose.yml"
|
|
||||||
owner: "{{ minecraft_fossils_owner }}"
|
|
||||||
group: "{{ minecraft_fossils_owner }}"
|
|
||||||
# secrets.env only matters at container start; never restart the
|
|
||||||
# game server as a side effect of a deploy
|
|
||||||
service_restart_on_change: false
|
|
||||||
service_graceful_stop:
|
|
||||||
- container: minecraft-fossils
|
|
||||||
timeout: 120
|
|
||||||
pre_stop: docker exec minecraft-fossils rcon-cli save-all flush
|
|
||||||
health_check_enabled: false
|
|
||||||
|
|
||||||
- name: Install the daily restart units
|
- name: Save the world
|
||||||
ansible.builtin.copy:
|
ansible.builtin.command: docker exec minecraft-fossils rcon-cli save-all flush
|
||||||
src: "{{ item }}"
|
when: fossils_compose.stat.exists
|
||||||
dest: "/etc/systemd/system/{{ item }}"
|
register: fossils_save
|
||||||
mode: "0644"
|
changed_when: fossils_save.rc == 0
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Stop and remove the containers (data stays)
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
project_src: /opt/minecraft-fossils
|
||||||
|
project_name: minecraft-fossils
|
||||||
|
state: absent
|
||||||
|
timeout: 120
|
||||||
|
when: fossils_compose.stat.exists
|
||||||
|
|
||||||
|
- name: Disable the daily restart timer
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: minecraft-fossils-restart.timer
|
||||||
|
enabled: false
|
||||||
|
state: stopped
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Remove the restart units
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "/etc/systemd/system/{{ item }}"
|
||||||
|
state: absent
|
||||||
loop:
|
loop:
|
||||||
- minecraft-fossils-restart.service
|
- minecraft-fossils-restart.service
|
||||||
- minecraft-fossils-restart.timer
|
- minecraft-fossils-restart.timer
|
||||||
notify: Reload systemd
|
notify: Reload systemd
|
||||||
|
|
||||||
- name: Flush handlers
|
|
||||||
ansible.builtin.meta: flush_handlers
|
|
||||||
|
|
||||||
- name: Enable the daily restart timer
|
|
||||||
ansible.builtin.systemd:
|
|
||||||
name: minecraft-fossils-restart.timer
|
|
||||||
enabled: true
|
|
||||||
state: started
|
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
RCON_PASSWORD={{ minecraft_fossils_rcon_password }}
|
|
||||||
CF_API_KEY={{ minecraft_fossils_cf_api_key }}
|
|
||||||
|
|
@ -27,7 +27,7 @@
|
||||||
roles:
|
roles:
|
||||||
- { role: sillytavern, tags: [sillytavern] }
|
- { role: sillytavern, tags: [sillytavern] }
|
||||||
- { role: minecraft, tags: [minecraft] }
|
- { role: minecraft, tags: [minecraft] }
|
||||||
- { role: minecraft_fossils, tags: [minecraft_fossils] }
|
- { role: minecraft_fossils, tags: [minecraft_fossils] } # retired: stops it
|
||||||
|
|
||||||
# Late: restarting Forgejo briefly cuts the runner off from its job log
|
# Late: restarting Forgejo briefly cuts the runner off from its job log
|
||||||
- name: Forgejo
|
- name: Forgejo
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue