Last active
December 17, 2025 18:18
-
-
Save cau1k/ac2db1cf91087dc7eba33ce402c5ebec to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # forgejo backup script - READ ONLY, NON-DESTRUCTIVE | |
| # run directly on the forgejo server | |
| # thanks, opus! | |
| set -euo pipefail | |
| # auto-detect forgejo container (matches forgejo or gitea in image name) | |
| CONTAINER=$(docker ps --format '{{.Names}}\t{{.Image}}' | grep -E 'forgejo|gitea' | head -1 | cut -f1) | |
| if [ -z "${CONTAINER}" ]; then | |
| echo "ERROR: No Forgejo/Gitea container found running!" | |
| echo "Running containers:" | |
| docker ps --format '{{.Names}}\t{{.Image}}' | |
| exit 1 | |
| fi | |
| # auto-detect data volume from container mounts | |
| DATA_VOLUME=$(docker inspect "${CONTAINER}" --format '{{range .Mounts}}{{if eq .Destination "/data"}}{{.Source}}{{end}}{{end}}') | |
| if [ -z "${DATA_VOLUME}" ]; then | |
| echo "ERROR: Could not find /data volume mount for container ${CONTAINER}" | |
| exit 1 | |
| fi | |
| # auto-detect UID:GID from data files | |
| RUN_UID=$(stat -c '%u:%g' "${DATA_VOLUME}/gitea/gitea.db" 2>/dev/null || stat -c '%u:%g' "${DATA_VOLUME}/gitea" 2>/dev/null || echo "1000:1000") | |
| BACKUP_DIR="$HOME/forgejo-backups" | |
| TIMESTAMP=$(date +%Y%m%d_%H%M%S) | |
| BACKUP_NAME="forgejo-backup-${TIMESTAMP}" | |
| BACKUP_PATH="${BACKUP_DIR}/${BACKUP_NAME}" | |
| echo "=== Forgejo Backup Script (NON-DESTRUCTIVE) ===" | |
| echo "Timestamp: ${TIMESTAMP}" | |
| echo "Container: ${CONTAINER}" | |
| echo "Data volume: ${DATA_VOLUME}" | |
| echo "Run UID:GID: ${RUN_UID}" | |
| echo "" | |
| # create backup directory | |
| mkdir -p "${BACKUP_PATH}" | |
| echo "[1/6] Created backup directory: ${BACKUP_PATH}" | |
| # verify container exists | |
| echo "[2/6] Verifying container is running..." | |
| if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER}$"; then | |
| echo "ERROR: Container ${CONTAINER} not found or not running!" | |
| exit 1 | |
| fi | |
| echo " ✓ Container is running" | |
| # get forgejo version | |
| echo "[3/6] Recording Forgejo version..." | |
| FORGEJO_VERSION=$(docker exec ${CONTAINER} forgejo --version 2>/dev/null || docker exec ${CONTAINER} gitea --version 2>/dev/null) | |
| echo "${FORGEJO_VERSION}" > "${BACKUP_PATH}/VERSION.txt" | |
| echo " ✓ Version: ${FORGEJO_VERSION}" | |
| # use forgejo's built-in dump (creates a zip with db + repos + config) | |
| echo "[4/6] Running forgejo dump inside container..." | |
| docker exec -u ${RUN_UID} ${CONTAINER} forgejo dump -c /data/gitea/conf/app.ini -f /tmp/forgejo-dump.zip 2>/dev/null || \ | |
| docker exec -u ${RUN_UID} ${CONTAINER} gitea dump -c /data/gitea/conf/app.ini -f /tmp/forgejo-dump.zip | |
| docker cp ${CONTAINER}:/tmp/forgejo-dump.zip "${BACKUP_PATH}/forgejo-dump.zip" | |
| docker exec -u ${RUN_UID} ${CONTAINER} rm -f /tmp/forgejo-dump.zip | |
| echo " ✓ Dump created and copied" | |
| # also backup the raw data directory (belt and suspenders) | |
| echo "[5/6] Creating raw volume backup (tar archive)..." | |
| tar -czf "${BACKUP_PATH}/forgejo-data-raw.tar.gz" -C "${DATA_VOLUME}" . | |
| echo " ✓ Raw data backup complete" | |
| # generate and verify checksums | |
| echo "[6/6] Generating and verifying checksums..." | |
| cd "${BACKUP_PATH}" | |
| sha256sum forgejo-dump.zip > forgejo-dump.zip.sha256 | |
| sha256sum forgejo-data-raw.tar.gz > forgejo-data-raw.tar.gz.sha256 | |
| sha256sum VERSION.txt > VERSION.txt.sha256 | |
| echo " ✓ Checksums generated" | |
| echo "" | |
| echo "=== Verifying backup integrity ===" | |
| sha256sum -c forgejo-dump.zip.sha256 | |
| sha256sum -c forgejo-data-raw.tar.gz.sha256 | |
| sha256sum -c VERSION.txt.sha256 | |
| # summary | |
| echo "" | |
| echo "=== BACKUP COMPLETE ===" | |
| echo "Location: ${BACKUP_PATH}" | |
| echo "" | |
| echo "Contents:" | |
| ls -lh "${BACKUP_PATH}" | |
| echo "" | |
| echo "Checksums:" | |
| cat "${BACKUP_PATH}"/*.sha256 | |
| echo "" | |
| echo "To verify later, run:" | |
| echo " cd ${BACKUP_PATH} && sha256sum -c *.sha256" | |
| echo "" | |
| echo "To restore, see: https://forgejo.org/docs/latest/admin/backup-and-restore/" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment