redact: scrub leaked Minecraft secrets from public repo

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/.
This commit is contained in:
s8n 2026-05-08 15:36:20 +01:00
parent 4116d67eaf
commit 3336f52142
13 changed files with 17 additions and 17 deletions

View file

@ -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 <world> 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 |
---

View file

@ -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

View file

@ -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).

View file

@ -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"

View file

@ -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.
```

View file

@ -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).

View file

@ -1 +1 @@
password=*redacted*
password=${RCON_PASSWORD}

View file

@ -1 +1 @@
password: "*redacted*"
password: "${RCON_PASSWORD}"

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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"