- SHARED_SECRET now read from env and fail-closed: unset/placeholder refuses ALL plugin connections (constant-time compare). The old hardcoded 'your_shared_secret' in this public repo was no auth at all. Dockerfile default removed; generate_data.py reads the env var. - SECRET_KEY fails closed at startup (main.py and agent/auth.py) instead of falling back to a publicly-known signing key; agent systemd unit now requires /etc/overlord/agent.env (no '-' prefix). - AuthMiddleware + /ws/live: replace the 172.x source-IP trust (which every nginx-proxied internet request satisfied via docker-proxy — full session bypass and unauthenticated in-game command injection) with private-source AND no X-Forwarded-For, i.e. only genuinely internal callers (overlord-agent on the host, compose-network services). Invariant documented in nginx/overlord.conf: every tracker-bound location must set X-Forwarded-For. - /character-stats/test endpoints gated behind admin (they upsert real rows). - docker-compose: bind 5432/5433 to 127.0.0.1 (both DBs were internet- reachable; active brute-force observed in dereth-db logs). - discord-rare-monitor: drop dead SHARED_SECRET constant. - scripts/backup-databases.sh + docs/backups.md: nightly pg_dump of both DBs (telemetry/spawn hypertable data excluded), 10MB canary, umask 077, TimescaleDB restore procedure. - Remove stray mangled-path css file from repo root. Adversarially reviewed pre-deploy (3-lens workflow): ship verdict; deploy- sequencing blockers addressed (secret staged before enforcement, exec bit set, cron uses bash). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
53 lines
2.6 KiB
Bash
Executable file
53 lines
2.6 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Nightly logical backups for both MosswartOverlord databases.
|
|
# Install as a cron job on the live host (see docs/backups.md). Note `bash`
|
|
# in the cron line (survives a lost executable bit) and that /home/erik/backups
|
|
# must exist BEFORE the first run (cron sets up the >> redirection before this
|
|
# script's mkdir runs):
|
|
# 15 3 * * * bash /home/erik/MosswartOverlord/scripts/backup-databases.sh >> /home/erik/backups/backup.log 2>&1
|
|
#
|
|
# What is backed up:
|
|
# - dereth (TimescaleDB): full schema + all data EXCEPT the raw
|
|
# telemetry_events/spawn_events hypertable chunks. Those tables hold
|
|
# ~12 GB of data that expires via retention policies in 7-30 days
|
|
# anyway; the irreplaceable rows (users, char_stats, rare_stats,
|
|
# rare_events, combat_stats*, portals, character_stats, server_status)
|
|
# are all included.
|
|
# - inventory_db (postgres): full dump (~1 GB raw, much smaller compressed).
|
|
#
|
|
# Restore procedure: docs/backups.md (TimescaleDB needs pre/post restore calls).
|
|
set -euo pipefail
|
|
# Dumps contain the users table (bcrypt hashes) — keep them owner-only.
|
|
umask 077
|
|
|
|
BACKUP_DIR="${BACKUP_DIR:-/home/erik/backups/postgres}"
|
|
KEEP_DAYS="${KEEP_DAYS:-7}"
|
|
STAMP="$(date -u +%Y%m%d-%H%M)"
|
|
mkdir -p "$BACKUP_DIR"
|
|
|
|
# dereth: -Fc is compressed; exclude hypertable chunk DATA (schema kept so a
|
|
# restore recreates the tables empty and retention/compression jobs reattach).
|
|
docker exec dereth-db pg_dump -U postgres -Fc \
|
|
--exclude-table-data='public.telemetry_events' \
|
|
--exclude-table-data='public.spawn_events' \
|
|
--exclude-table-data='_timescaledb_internal._hyper_*' \
|
|
dereth > "$BACKUP_DIR/dereth-$STAMP.dump.tmp"
|
|
# Canary: a healthy dereth dump is ~50 MB; a tiny one means pg_dump silently
|
|
# produced garbage (fail the run so the old dumps are kept and cron logs it).
|
|
if [ "$(stat -c%s "$BACKUP_DIR/dereth-$STAMP.dump.tmp")" -lt 10000000 ]; then
|
|
echo "$(date -u +%FT%TZ) FAIL dereth dump under 10MB — keeping old backups" >&2
|
|
exit 1
|
|
fi
|
|
mv "$BACKUP_DIR/dereth-$STAMP.dump.tmp" "$BACKUP_DIR/dereth-$STAMP.dump"
|
|
|
|
docker exec inventory-db pg_dump -U inventory_user -Fc inventory_db \
|
|
> "$BACKUP_DIR/inventory-$STAMP.dump.tmp"
|
|
mv "$BACKUP_DIR/inventory-$STAMP.dump.tmp" "$BACKUP_DIR/inventory-$STAMP.dump"
|
|
|
|
# Retention: keep KEEP_DAYS days of dailies.
|
|
find "$BACKUP_DIR" -name 'dereth-*.dump' -mtime +"$KEEP_DAYS" -delete
|
|
find "$BACKUP_DIR" -name 'inventory-*.dump' -mtime +"$KEEP_DAYS" -delete
|
|
# Clean up aborted runs older than a day.
|
|
find "$BACKUP_DIR" -name '*.dump.tmp' -mtime +1 -delete
|
|
|
|
echo "$(date -u +%FT%TZ) OK dereth=$(du -h "$BACKUP_DIR/dereth-$STAMP.dump" | cut -f1) inventory=$(du -h "$BACKUP_DIR/inventory-$STAMP.dump" | cut -f1)"
|