Production MC stack on exo — compose, scripts, configs. Session log in SESSIONS.md.
  • Shell 94.1%
  • Python 5.9%
Find a file
paul 0b163ce82e
Some checks failed
Validate commit policy / reason-line (push) Has been cancelled
creaclone: brand server mod name -> Folikaii
Reason: fork renamed Folikaii (Folia+kaii signature). Sets the F3/client
brand string. Applies at next creaclone restart.
2026-07-19 19:28:19 +02:00
.forgejo/workflows gitops: convert repo to source-of-truth with webhook-driven sync 2026-05-24 11:57:06 +02:00
compose Expose BlueMap webserver on minis LAN for map.ekaii.fr 2026-06-30 00:33:42 +00:00
config-snapshots creaclone: snapshot LuckPerms default-group perms (knowledge artifact) 2026-05-25 02:45:57 +02:00
docs gitops: track creaclone lophine_config + ekaii_config instances 2026-07-18 21:24:24 +02:00
plugins creaclone: add EkaiiTweaks 1.0.0 (per-player creative tweaks) 2026-07-19 00:44:16 +02:00
scripts gitops: track creaclone lophine_config + ekaii_config instances 2026-07-18 21:24:24 +02:00
secrets feat(audit): capture drift to a drift-captures branch on Forgejo 2026-05-24 12:29:51 +02:00
services creaclone: brand server mod name -> Folikaii 2026-07-19 19:28:19 +02:00
sessions sessions: 2026-05-25 audit Velocity (ban/wl gate) + compose split 2026-05-25 18:05:36 +02:00
systemd fix(creaclone,audit): swap corrupt AxiomPaper jar, resync drift, repair dead audit timer 2026-06-26 12:38:47 +02:00
templates gitops: track creaclone lophine_config + ekaii_config instances 2026-07-18 21:24:24 +02:00
.gitignore creaclone: untrack lophine_carpet_config (live-tunable in-game) 2026-07-19 00:30:52 +02:00
.gitmessage gitops: convert repo to source-of-truth with webhook-driven sync 2026-05-24 11:57:06 +02:00
README.md test: README footer to verify webhook → sync.sh end-to-end 2026-05-24 12:02:04 +02:00

ekaii-mc-stack — GitOps source of truth

This repo is the single source of truth for the Minecraft stack running on minis (LAN 192.168.50.61). Every config, plugin, and compose file is git-managed. A webhook fires on every push to main and a sync script applies the change to the live tree with a graceful restart of affected services.

TL;DR: edit a file → git commit with a Reason: line → git push → change is live in ~5 seconds. Direct edits on the server are detected and shamed.

Commit policy (mandatory)

Every commit body MUST contain a single line:

Reason: <one sentence operational motivation>

A pre-receive hook on forgejo.ekaii.fr rejects pushes that violate this. The .gitmessage template at the repo root will prompt you for it:

git config commit.template .gitmessage  # one-time after clone

Backends managed

Service Container Network port (LAN) WAN Compose World
velocity mc-velocity 25590 25590/tcp+udp (UDM NAT) compose/preprod-compose.yml
mc-ekaii mc-ekaii internal :25566 via velocity compose/preprod-compose.yml survie 26.1.2
mc-creaclone mc-creaclone internal :25568 via velocity Coolify-managed (ref in compose/) clone créatif
mc-plot mc-plot internal :25569 via velocity compose/plot-compose.yml plot world
mc-pg mc-pg internal :5432 compose/preprod-compose.yml CoreProtect DB
mc-velocity-bot mc-velocity-bot 25591 compose/velocity-bot-compose.yml bot proxy

All backends share the external Docker network mc-net. Backend ports bind to 127.0.0.1 only — only velocity is exposed to LAN/WAN.

Day-1 install on minis

Run once when setting up GitOps on a fresh minis:

ssh exo "sudo mkdir -p /opt/mc-stack/.git-source /opt/mc-stack/.secrets /opt/mc-stack/.gitops-state"
ssh exo "sudo chown -R exo:exo /opt/mc-stack/.git-source /opt/mc-stack/.gitops-state"
ssh exo "sudo chmod 0700 /opt/mc-stack/.secrets"
ssh exo "cd /opt/mc-stack && sudo -u exo git clone https://forgejo.ekaii.fr/exo/ekaii-mc-stack.git .git-source"
# Populate secrets:
scp /path/to/your/local/secrets.env exo:/tmp/secrets.env
ssh exo "sudo mv /tmp/secrets.env /opt/mc-stack/.secrets/secrets.env && sudo chmod 0600 /opt/mc-stack/.secrets/secrets.env && sudo chown exo:exo /opt/mc-stack/.secrets/secrets.env"
# Install systemd units:
ssh exo "sudo cp /opt/mc-stack/.git-source/systemd/mc-stack-*.{service,timer} /etc/systemd/system/"
ssh exo "sudo systemctl daemon-reload && sudo systemctl enable --now mc-stack-webhook.service mc-stack-audit.timer"
# Verify:
ssh exo "sudo journalctl -u mc-stack-webhook.service -n 20"
# Configure Forgejo webhook → http://192.168.50.61:9876/sync with the WEBHOOK_SHARED_SECRET value.

After install, every git push origin main triggers a sync within ~5 seconds.

Stack architecture

WAN:25590 ──> UDM Pro ──> exo:25590 ──> mc-velocity ──> { mc-ekaii, mc-creaclone, mc-plot }
                                                              (via mc-net Docker network)

DNS routing → 89.226.110.44 (maison WAN), UDM NATs 25590 → exo. SRV _minecraft._tcp.<host>.ekaii.fr → port 25590. try = [] in velocity.toml — no fallback when forced-host fails.

Velocity routing (forced-hosts)

Hostname → Backend
ekaii.fr / beta.ekaii.fr / mc.ekaii.fr / fibre.ekaii.fr / local.ekaii.fr ekaii
crea.ekaii.fr / beta.crea.ekaii.fr creaclone
plot.ekaii.fr plot

Whitelist

white-list=true + enforce-whitelist=true on all 3 backends. Maintained as runtime state via /whitelist add rcon (NOT git-tracked — it's mutable state, would race the server). scripts/wl-auto-sync.sh propagates between backends every minute.

DHS / LOD keys

Backend server_key / level_key_prefix
ekaii ekaiiserver
creaclone creaclone
plot plotworld

LuckPerms (creaclone + plot)

Folia-compatible fork at admin_ekaii/luckperms-folia-ekaii (v0.3.1-ekaii). Group default has worldedit.*, axiom.*, chunklock.use, extendedhorizons.distance.unlimited.

Session history

See sessions/ for chronological notes from pre-GitOps operations.

Bootstrap sync test

2026-05-24 12:02 CEST — webhook → sync.sh smoke test.