Files
Minecraft-Server/backup.sh

92 lines
2.9 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# Usage: ./backup.sh [label]
# Creates backups/world-YYYY-MM-DD-HHMM[-label].tar.gz and uploads it
# as a Gitea release asset on the `origin` remote.
#
# If the container is running, flushes world via rcon and archives via
# docker exec. Otherwise archives data/world from the host directly.
#
# Token is read from $GITEA_TOKEN or ~/.gitea_token. If neither is set,
# the local archive is still created and upload is skipped.
set -euo pipefail
cd "$(dirname "$0")"
LABEL="${1:-}"
STAMP="$(date +%Y-%m-%d-%H%M)"
SUFFIX="${LABEL:+-$LABEL}"
OUT="backups/world-${STAMP}${SUFFIX}.tar.gz"
mkdir -p backups
if docker ps --format '{{.Names}}' | grep -qx minecraft; then
echo "Server running — flushing world via rcon..."
docker exec minecraft rcon-cli save-off >/dev/null
docker exec minecraft rcon-cli save-all flush >/dev/null
trap 'docker exec minecraft rcon-cli save-on >/dev/null || true' EXIT
echo "Archiving /data/world -> ${OUT}"
docker exec minecraft tar -czf - -C /data world > "${OUT}"
else
echo "Server not running — archiving data/world from host."
tar -czf "${OUT}" -C data world
fi
echo "Archive done: $(ls -lh "${OUT}" | awk '{print $5, $9}')"
# --- Upload to Gitea as a release asset ---
TOKEN="${GITEA_TOKEN:-}"
if [[ -z "$TOKEN" && -r "$HOME/.gitea_token" ]]; then
TOKEN="$(cat "$HOME/.gitea_token")"
fi
if [[ -z "$TOKEN" ]]; then
echo "No Gitea token (set GITEA_TOKEN or ~/.gitea_token) — skipping upload."
exit 0
fi
URL="$(git config --get remote.origin.url)"
SCHEME="${URL%%://*}"
REST="${URL#*://}"; REST="${REST#*@}" # strip any embedded userinfo
HOSTPORT="${REST%%/*}"
REPO_PATH="${REST#*/}"; REPO_PATH="${REPO_PATH%.git}"
OWNER="${REPO_PATH%/*}"
REPO="${REPO_PATH#*/}"
API="${SCHEME}://${HOSTPORT}/api/v1"
TAG="backup-${STAMP}${SUFFIX}"
NAME="World backup ${STAMP}${LABEL:+ ($LABEL)}"
SHA="$(git rev-parse HEAD)"
echo "Pushing main so the release target exists on remote..."
git push origin main >/dev/null
echo "Creating release '${TAG}' on ${OWNER}/${REPO}..."
PAYLOAD=$(printf '{"tag_name":"%s","target_commitish":"%s","name":"%s","body":"Automated world backup"}' \
"$TAG" "$SHA" "$NAME")
RESPONSE=$(curl -fsS -X POST \
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
-d "$PAYLOAD" \
"${API}/repos/${OWNER}/${REPO}/releases")
RELEASE_ID="${RESPONSE#*\"id\":}"
RELEASE_ID="${RELEASE_ID%%,*}"
if ! [[ "$RELEASE_ID" =~ ^[0-9]+$ ]]; then
echo "Could not parse release id from response:" >&2
echo "$RESPONSE" >&2
exit 1
fi
echo "Uploading asset to release ${RELEASE_ID}..."
curl -fsS -X POST \
-H "Authorization: token ${TOKEN}" \
-F "attachment=@${OUT}" \
"${API}/repos/${OWNER}/${REPO}/releases/${RELEASE_ID}/assets?name=$(basename "${OUT}")" \
>/dev/null
echo "Uploaded: ${SCHEME}://${HOSTPORT}/${OWNER}/${REPO}/releases/tag/${TAG}"