diff --git a/.gitignore b/.gitignore index 0890c9b..35d34c8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ *secrets* *.pem *.key -*backup* **/config/ **/data/ *.db diff --git a/docker-compose/gitlab/backups/gitlab-backup.sh b/docker-compose/gitlab/backups/gitlab-backup.sh new file mode 100644 index 0000000..b084d70 --- /dev/null +++ b/docker-compose/gitlab/backups/gitlab-backup.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# GitLab weekly backup — creates a fresh backup, then prunes to keep only +# the single newest copy of each type. Sized for limited free disk space. +# +# Must run as root: GitLab's config/secrets files and data/backups directory +# are owned by root inside the bind-mounted volumes. Ownership of this +# script's own output is handed back to the regular user at the end. +# +# Scheduled via root's crontab: +# 0 2 * * 0 /home/rezayaghobi/backups/run-backup.sh + +set -e + +TIMESTAMP=$(date +%F) +BACKUP_DIR="/home/rezayaghobi/backups" +GITLAB_DATA_BACKUPS="/home/rezayaghobi/docker/gitlab/data/backups" +LOG_FILE="$BACKUP_DIR/backup.log" + +echo "=== Backup started: $(date) ===" >> "$LOG_FILE" + +# 1. GitLab's own backup tool (repos, DB, uploads) — does NOT include secrets +docker exec gitlab gitlab-backup create CRON=1 >> "$LOG_FILE" 2>&1 + +# 2. Config + secrets (gitlab.rb, gitlab-secrets.json, SSH host keys) — +# root-owned, and not included in gitlab-backup by design. Without this, +# a restored gitlab-backup archive is unreadable. +tar czf "$BACKUP_DIR/gitlab-config-$TIMESTAMP.tar.gz" /home/rezayaghobi/docker/gitlab/config >> "$LOG_FILE" 2>&1 + +# 3. Runner config — small, but losing it means re-registering from scratch +tar czf "$BACKUP_DIR/gitlab-runner-config-$TIMESTAMP.tar.gz" /home/rezayaghobi/docker/gitlab/runner-config >> "$LOG_FILE" 2>&1 + +# 4. Prune: keep only the newest file of each type, delete the rest. +# Time-based retention (e.g. GitLab's own backup_keep_time) was skipped +# in favor of this, since a single-copy policy maps more predictably to +# limited free disk space than a rolling time window would. +find "$GITLAB_DATA_BACKUPS" -name "*_gitlab_backup.tar" -printf '%T@ %p\n' | sort -rn | tail -n +2 | cut -d' ' -f2- | xargs -r rm -f +find "$BACKUP_DIR" -name "gitlab-config-*.tar.gz" -printf '%T@ %p\n' | sort -rn | tail -n +2 | cut -d' ' -f2- | xargs -r rm -f +find "$BACKUP_DIR" -name "gitlab-runner-config-*.tar.gz" -printf '%T@ %p\n' | sort -rn | tail -n +2 | cut -d' ' -f2- | xargs -r rm -f + +# 5. Hand ownership back to the regular user — the script ran as root +chown -R rezayaghobi:rezayaghobi "$BACKUP_DIR" + +echo "=== Backup finished: $(date) ===" >> "$LOG_FILE" +echo "" >> "$LOG_FILE"