This commit is contained in:
2026-04-07 17:53:21 -07:00
parent 916cbaa612
commit eb69ee13e6
6 changed files with 206 additions and 1 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
state/**
tailscale-nginx/**
gitea-backups/**

70
BACKUP_RUNNER_PLAN.md Normal file
View File

@@ -0,0 +1,70 @@
# Gitea Backup Runner Plan
## Objective
Create a scheduled backup runner that:
1. Dumps Gitea data using the native `gitea dump` command via `docker exec`
2. Copies the backup archive from the container to the host
3. Transfers the backup to remote location `workstation:/mnt/data/git-backups`
4. Runs automatically once a month via cron
## Current State
- Existing `gitea-backup.sh` uses `docker run` with tar to backup volume data
- This new approach uses Gitea's built-in `gitea dump` command which creates a complete backup including database, repos, and settings
## Implementation Plan
### 1. Create Backup Script: `gitea-dump-backup.sh`
- **Location**: `./gitea-dump-backup.sh`
- **Functions**:
- Generate timestamped backup filename
- Execute `gitea dump` inside the container via `docker exec`
- Copy the resulting archive from container to host backup directory
- Upload to remote workstation via `scp` or `rsync`
- Clean up old local backups (keep last N)
- Logging and error handling
### 2. Create Cron Configuration
- **Location**: `./gitea-backup.cron`
- **Schedule**: First day of each month at 2:00 AM
```
0 2 1 * * /path/to/gitea-dump-backup.sh >> /var/log/gitea-backup.log 2>&1
```
### 3. Directory Structure
```
gitea-backups/ # Local backup storage (git-ignored)
├── gitea-dump-20260401-020000.zip
└── ...
```
### 4. Remote Transfer Options
- **Primary**: `rsync` over SSH to `workstation:/mnt/data/git-backups`
- Requires SSH key-based authentication setup or SSH agent forwarding
### 5. Backup Retention
- Keep last 3 local backups (configurable)
- Remote retention handled by remote system
### 6. Prerequisites
- SSH access to `workstation` server
- Sufficient disk space in container for dump operation
- Backup directory created on remote server
## File Changes
| File | Action |
|------|--------|
| `gitea-dump-backup.sh` | Create - main backup script |
| `gitea-backup.cron` | Create - cron configuration |
| `.gitignore` | Update - exclude gitea-backups/ directory |
## Security Considerations
- Store remote credentials securely (SSH key)
- Ensure backup files have appropriate permissions (600)
- Log handling for debugging
## Testing Checklist
- [ ] Run backup script manually
- [ ] Verify archive contains expected files
- [ ] Test remote transfer
- [ ] Verify cron installation
- [ ] Test error handling scenarios

View File

@@ -0,0 +1,54 @@
# Gitea Docker
A simple Docker Compose setup for running Gitea with Tailscale networking.
## Backup
This project includes a backup runner that uses Gitea's built-in `gitea dump` command.
### Manual Backup
```bash
./gitea-dump-backup.sh
```
### Automated Backup (Cron)
The backup runs automatically on the 1st of every month at 2:00 AM.
To install the cron job:
```bash
crontab ./gitea-backup.cron
```
Or append to existing crontab:
```bash
crontab -l | cat - ./gitea-backup.cron | crontab -
```
### Configuration
Edit the script variables to customize:
- `REMOTE_HOST`: Remote backup server (default: `workstation`)
- `REMOTE_PATH`: Remote backup path (default: `/mnt/data/git-backups`)
- `KEEP_LOCAL`: Number of local backups to keep (default: 3)
### Requirements
- SSH access to the remote backup server
- `rsync` installed locally
- Backup directory must exist on remote server
## Quick Start
1. Create the remote backup directory:
```bash
ssh workstation "mkdir -p /mnt/data/git-backups"
```
2. Start Gitea:
```bash
docker compose -f docker-compose.gitea.yml up -d
```

4
gitea-backup.cron Normal file
View File

@@ -0,0 +1,4 @@
# Gitea Backup Cron Configuration
# Runs backup on the 1st of every month at 2:00 AM
0 2 1 * * /home/noti/dev/gitea-docker/gitea-dump-backup.sh >> /var/log/gitea-backup.log 2>&1

View File

@@ -9,7 +9,7 @@ mkdir -p "$BACKUP_DIR"
echo "Backing up Gitea data to $BACKUP_DIR/gitea-backup-$DATE.tar.gz..."
docker run --rm \
-v ai-game-2_gitea-data:/data \
-v gitea_gitea-data:/data \
-v "$(pwd)/$BACKUP_DIR":/backup \
alpine \
tar czf "/backup/gitea-backup-$DATE.tar.gz" -C /data .

76
gitea-dump-backup.sh Executable file
View File

@@ -0,0 +1,76 @@
#!/bin/bash
# Gitea Dump Backup Script
# Backs up Gitea using the native 'gitea dump' command and transfers to remote storage
set -euo pipefail
# Configuration
BACKUP_DIR="./gitea-backups"
REMOTE_HOST="workstation"
REMOTE_PATH="/mnt/data/git-backups"
REMOTE_USER="${REMOTE_USER:-$(whoami)}"
CONTAINER_NAME="${CONTAINER_NAME:-gitea}"
KEEP_LOCAL="${KEEP_LOCAL:-3}"
LOG_FILE="${LOG_FILE:-/var/log/gitea-backup.log}"
# Timestamps
DATE=$(date +%Y%m%d)
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
error() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $*" | tee -a "$LOG_FILE" >&2
exit 1
}
# Ensure local backup directory exists
mkdir -p "$BACKUP_DIR"
log "Starting Gitea backup process..."
# Step 1: Execute gitea dump inside the container
log "Creating Gitea dump inside container..."
CONTAINER_DUMP_PATH="/data/gitea-dump-${TIMESTAMP}.zip"
docker exec -u 1000 -i "$CONTAINER_NAME" bash -c "/app/gitea/gitea dump -c /data/gitea/conf/app.ini -f ${CONTAINER_DUMP_PATH}" \
|| error "Failed to execute gitea dump command"
log "Dump created in container at: $CONTAINER_DUMP_PATH"
# Step 2: Copy the archive from container to host
LOCAL_BACKUP="${BACKUP_DIR}/gitea-dump-${TIMESTAMP}.zip"
log "Copying backup from container to host..."
docker cp "${CONTAINER_NAME}:${CONTAINER_DUMP_PATH}" "$LOCAL_BACKUP" \
|| error "Failed to copy backup from container"
log "Backup saved locally: $LOCAL_BACKUP"
# Step 3: Clean up the dump file inside the container
log "Cleaning up container dump file..."
docker exec "$CONTAINER_NAME" rm -f "$CONTAINER_DUMP_PATH" || log "Warning: Failed to clean up container dump file (non-fatal)"
# Step 4: Upload to remote workstation
log "Uploading backup to remote storage (${REMOTE_HOST}:${REMOTE_PATH})..."
if ssh "$REMOTE_USER@$REMOTE_HOST" "test -d $REMOTE_PATH"; then
rsync -avz --progress "$LOCAL_BACKUP" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/" \
|| error "Failed to upload backup to remote storage"
log "Backup uploaded successfully"
else
error "Remote backup directory does not exist: ${REMOTE_HOST}:${REMOTE_PATH}"
fi
# Step 5: Clean up old local backups (keep only KEEP_LOCAL most recent)
log "Cleaning up old local backups (keeping last $KEEP_LOCAL)..."
cd "$BACKUP_DIR" || error "Cannot access backup directory"
ls -t gitea-dump-*.zip 2>/dev/null | tail -n +$((KEEP_LOCAL + 1)) | xargs -r rm -f
log "Local cleanup complete"
# Final status
log "Backup completed successfully!"
log "Backup file: $(ls -lh "$LOCAL_BACKUP" | awk '{print $5, $9}')"
exit 0