changes
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
state/**
|
state/**
|
||||||
tailscale-nginx/**
|
tailscale-nginx/**
|
||||||
|
gitea-backups/**
|
||||||
|
|||||||
70
BACKUP_RUNNER_PLAN.md
Normal file
70
BACKUP_RUNNER_PLAN.md
Normal 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
|
||||||
54
README.md
54
README.md
@@ -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
4
gitea-backup.cron
Normal 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
|
||||||
@@ -9,7 +9,7 @@ mkdir -p "$BACKUP_DIR"
|
|||||||
echo "Backing up Gitea data to $BACKUP_DIR/gitea-backup-$DATE.tar.gz..."
|
echo "Backing up Gitea data to $BACKUP_DIR/gitea-backup-$DATE.tar.gz..."
|
||||||
|
|
||||||
docker run --rm \
|
docker run --rm \
|
||||||
-v ai-game-2_gitea-data:/data \
|
-v gitea_gitea-data:/data \
|
||||||
-v "$(pwd)/$BACKUP_DIR":/backup \
|
-v "$(pwd)/$BACKUP_DIR":/backup \
|
||||||
alpine \
|
alpine \
|
||||||
tar czf "/backup/gitea-backup-$DATE.tar.gz" -C /data .
|
tar czf "/backup/gitea-backup-$DATE.tar.gz" -C /data .
|
||||||
|
|||||||
76
gitea-dump-backup.sh
Executable file
76
gitea-dump-backup.sh
Executable 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
|
||||||
Reference in New Issue
Block a user