From 3336f521429dc6a0510840897252be2a8c0679c2 Mon Sep 17 00:00:00 2001 From: s8n Date: Fri, 8 May 2026 15:36:20 +0100 Subject: [PATCH] redact: scrub leaked Minecraft secrets from public repo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced literal values with env-var placeholders (${RCON_PASSWORD}, ${MGMT_SECRET}, ${MC_RCON_PASSWORD}) across server.properties, .rcon-cli.env, docker-compose.yml(s), backup scripts, and AUDIT-2026-05-07.md. Affected secrets: - Paper management-server-secret (HIGH; mitigated by management-server-enabled=false) - RCON password '*redacted*' (MEDIUM; bound to 127.0.0.1) - MC_RCON_PASSWORD backup-pipeline default fallback (MEDIUM; same blast radius) WARNING: HEAD redaction only — values remain in git history. Treat as compromised and rotate (closes F-17 audit-finding's deferred TODO). Originals backed up to private s8n/secrets/minecraft-server/. --- AUDIT-2026-05-07.md | 2 +- BACKUP-STRATEGY.md | 2 +- README.md | 2 +- docker-compose.yml | 2 +- docs/RUNBOOK-BACKUP-RESTORE.md | 8 ++++---- docs/plugins/README.md | 2 +- live-server/.rcon-cli.env | 2 +- live-server/.rcon-cli.yaml | 2 +- live-server/docker-compose.yml | 2 +- live-server/server.properties | 4 ++-- scripts/backup.sh | 2 +- scripts/restic-init.sh | 2 +- staging/excellentshop/scripts/docker-compose.patch.yml | 2 +- 13 files changed, 17 insertions(+), 17 deletions(-) diff --git a/AUDIT-2026-05-07.md b/AUDIT-2026-05-07.md index a930556..8f873ec 100644 --- a/AUDIT-2026-05-07.md +++ b/AUDIT-2026-05-07.md @@ -49,7 +49,7 @@ Severity = Likelihood x Impact. P0 = act this week, P1 = this month, P2 = this q | F-14 | **P2 / 9** | No TPS Discord webhook alert (mentioned on TODO). spark is installed but auto-profile + alerting are not wired up. | spark already supports `spark profile --thresholds`; route to Discord via existing webhook stack. | 0.5d | | F-15 | **P2 / 8** | RCON output for async commands (CoreProtect, LuckPerms) does not return to the issuing rcon-cli session. Found while trying `co inspect` from RCON. Async command results land in console only. | Document this in `docs/OPERATIONS.md` (does not exist yet — create it). For automation, attach to `docker logs -f minecraft-mc` in parallel. | 30 min doc | | F-16 | **P2 / 8** | `gamerule keepInventory` could not be queried via `rcon-cli` due to `execute in run` argument parsing bug in itzg's rcon-cli wrapper (or RCON quoting). State unknown without in-game console. | Verify in-game by op user, document the rcon-cli limitation. | 5 min in-game | -| F-17 | **P2 / 6** | `RCON_PASSWORD` is committed to `docker-compose.yml` in plaintext (`*redacted*`). RCON port (25575) is bound to `127.0.0.1` so the blast radius is local only — but the secret is still in git history. | Rotate password, move to `.env` (gitignored), confirm `127.0.0.1`-only binding stays. | 30 min | +| F-17 | **P2 / 6** | `RCON_PASSWORD` is committed to `docker-compose.yml` in plaintext (`${MC_RCON_PASSWORD}`). RCON port (25575) is bound to `127.0.0.1` so the blast radius is local only — but the secret is still in git history. | Rotate password, move to `.env` (gitignored), confirm `127.0.0.1`-only binding stays. | 30 min | | F-18 | **P2 / 6** | `restart: unless-stopped` with no `start_period` re-evaluation on rapid OOM-restart loops. If the container OOMs every 60s, Docker keeps restarting indefinitely. | Add `restart_policy: { condition: on-failure, max_attempts: 5, window: 300s }` (compose v3+ deploy block) and a watchdog alert. | 30 min | --- diff --git a/BACKUP-STRATEGY.md b/BACKUP-STRATEGY.md index 2a69bb8..e53dc7a 100644 --- a/BACKUP-STRATEGY.md +++ b/BACKUP-STRATEGY.md @@ -247,7 +247,7 @@ RESTIC_PASSWORD_FILE=/etc/mc-backup.pw MC_DATA=/opt/docker/minecraft RCON_HOST=127.0.0.1 RCON_PORT=25575 -RCON_PASS=*redacted* +RCON_PASS=${RCON_PASSWORD} HEARTBEAT_URL=https://ntfy.s8n.ru/mc-backup-frequent ALERT_URL=https://ntfy.s8n.ru/mc-backup-alerts TS_OFFHOST_USER=mc-backup diff --git a/README.md b/README.md index b61ef0a..127622f 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ First boot: ~3-5 min (Purpur jar DL, ~14 plugin DL, world gen). | Online mode | false (cracked clients allowed) | | Spawn protection | 0 | | RAM | 8G min, 16G max (18G hard cap) | -| RCON | enabled, port 25575, password `*redacted*` | +| RCON | enabled, port 25575, password `${RCON_PASSWORD}` | Full settings in [`config/server.properties`](config/server.properties). diff --git a/docker-compose.yml b/docker-compose.yml index 85c59ed..93c593b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -29,7 +29,7 @@ services: MAX_TICK_TIME: "-1" ENABLE_RCON: "true" - RCON_PASSWORD: "*redacted*" + RCON_PASSWORD: "${RCON_PASSWORD}" TZ: "Europe/London" ENABLE_ROLLING_LOGS: "true" diff --git a/docs/RUNBOOK-BACKUP-RESTORE.md b/docs/RUNBOOK-BACKUP-RESTORE.md index 6920925..f7de76a 100644 --- a/docs/RUNBOOK-BACKUP-RESTORE.md +++ b/docs/RUNBOOK-BACKUP-RESTORE.md @@ -24,9 +24,9 @@ file /tmp/restore-$$/opt/docker/minecraft/world/playerdata/${PUUID}.dat # Apply (server must be running so playerdata is writable; the player # MUST be offline or we're racing the writer): -mcrcon -H 127.0.0.1 -P 25575 -p *redacted* "kick ${PUUID_NICK} Restore in progress" -mcrcon -H 127.0.0.1 -P 25575 -p *redacted* "save-off" -mcrcon -H 127.0.0.1 -P 25575 -p *redacted* "save-all flush" +mcrcon -H 127.0.0.1 -P 25575 -p ${RCON_PASSWORD} "kick ${PUUID_NICK} Restore in progress" +mcrcon -H 127.0.0.1 -P 25575 -p ${RCON_PASSWORD} "save-off" +mcrcon -H 127.0.0.1 -P 25575 -p ${RCON_PASSWORD} "save-all flush" cp /opt/docker/minecraft/world/playerdata/${PUUID}.dat \ /opt/docker/minecraft/world/playerdata/${PUUID}.dat.preFix-$(date +%s) @@ -34,7 +34,7 @@ cp /tmp/restore-$$/opt/docker/minecraft/world/playerdata/${PUUID}.dat \ /opt/docker/minecraft/world/playerdata/${PUUID}.dat chown 100000:100000 /opt/docker/minecraft/world/playerdata/${PUUID}.dat # userns-remap -mcrcon -H 127.0.0.1 -P 25575 -p *redacted* "save-on" +mcrcon -H 127.0.0.1 -P 25575 -p ${RCON_PASSWORD} "save-on" # Tell the player to log back in. ``` diff --git a/docs/plugins/README.md b/docs/plugins/README.md index 7d46911..a130530 100644 --- a/docs/plugins/README.md +++ b/docs/plugins/README.md @@ -58,7 +58,7 @@ First boot: ~3-5 min (Purpur jar DL, ~14 plugin DL, world gen). | Online mode | false (cracked clients allowed) | | Spawn protection | 0 | | RAM | 8G min, 16G max (18G hard cap) | -| RCON | enabled, port 25575, password `*redacted*` | +| RCON | enabled, port 25575, password `${RCON_PASSWORD}` | Full settings in [`config/server.properties`](config/server.properties). diff --git a/live-server/.rcon-cli.env b/live-server/.rcon-cli.env index 9438aaf..2332865 100755 --- a/live-server/.rcon-cli.env +++ b/live-server/.rcon-cli.env @@ -1 +1 @@ -password=*redacted* +password=${RCON_PASSWORD} diff --git a/live-server/.rcon-cli.yaml b/live-server/.rcon-cli.yaml index e5bbe6b..2d86b19 100755 --- a/live-server/.rcon-cli.yaml +++ b/live-server/.rcon-cli.yaml @@ -1 +1 @@ -password: "*redacted*" +password: "${RCON_PASSWORD}" diff --git a/live-server/docker-compose.yml b/live-server/docker-compose.yml index 77a5132..7889d3c 100644 --- a/live-server/docker-compose.yml +++ b/live-server/docker-compose.yml @@ -26,7 +26,7 @@ services: MAX_TICK_TIME: "-1" ENABLE_RCON: "true" - RCON_PASSWORD: "*redacted*" + RCON_PASSWORD: "${RCON_PASSWORD}" TZ: "Europe/London" ENABLE_ROLLING_LOGS: "true" diff --git a/live-server/server.properties b/live-server/server.properties index 6226ebc..614d1e8 100755 --- a/live-server/server.properties +++ b/live-server/server.properties @@ -32,7 +32,7 @@ management-server-allowed-origins= management-server-enabled=false management-server-host=localhost management-server-port=0 -management-server-secret=*redacted* +management-server-secret=${MGMT_SECRET} management-server-tls-enabled=true management-server-tls-keystore= management-server-tls-keystore-password= @@ -49,7 +49,7 @@ player-idle-timeout=0 prevent-proxy-connections=false query.port=25565 rate-limit=0 -rcon.password=*redacted* +rcon.password=${RCON_PASSWORD} rcon.port=25575 region-file-compression=deflate require-resource-pack=false diff --git a/scripts/backup.sh b/scripts/backup.sh index e8cea61..8edb587 100755 --- a/scripts/backup.sh +++ b/scripts/backup.sh @@ -129,7 +129,7 @@ mc_backup() { # tar inside the container so we get a consistent point-in-time. if command -v mcrcon >/dev/null 2>&1; then mcrcon -H 127.0.0.1 -P 25575 \ - -p "${MC_RCON_PASSWORD:-*redacted*}" \ + -p "${MC_RCON_PASSWORD:-${MC_RCON_PASSWORD}}" \ -w 1 "save-all flush" >/dev/null 2>&1 || true fi diff --git a/scripts/restic-init.sh b/scripts/restic-init.sh index b3a04f4..b003358 100644 --- a/scripts/restic-init.sh +++ b/scripts/restic-init.sh @@ -71,7 +71,7 @@ MC_BACKUP_WORLD_SENTINEL=$SENTINEL_DIR/last-success-world # compose file (services.mc.environment.RCON_PASSWORD). MC_RCON_HOST=127.0.0.1 MC_RCON_PORT=25575 -MC_RCON_PASSWORD=*redacted* +MC_RCON_PASSWORD=${MC_RCON_PASSWORD} # Off-host mirror destination (onyx via Tailscale). Empty = skip mirror. TS_OFFHOST_USER=mc-backup diff --git a/staging/excellentshop/scripts/docker-compose.patch.yml b/staging/excellentshop/scripts/docker-compose.patch.yml index ffa013f..63ed394 100644 --- a/staging/excellentshop/scripts/docker-compose.patch.yml +++ b/staging/excellentshop/scripts/docker-compose.patch.yml @@ -29,7 +29,7 @@ services: MAX_TICK_TIME: "-1" ENABLE_RCON: "true" - RCON_PASSWORD: "*redacted*" + RCON_PASSWORD: "${RCON_PASSWORD}" TZ: "Europe/London" ENABLE_ROLLING_LOGS: "true"