refactor: Improve backup-env-files.sh for temp file handling and enhance crontab entries for .env backups

This commit is contained in:
Peter Wood
2025-05-29 07:19:12 -04:00
parent 20737f7872
commit faf5102cd7
6 changed files with 99 additions and 40 deletions

View File

@@ -83,6 +83,10 @@ list_env_files() {
echo -e "${BLUE}=== Environment Files Found ===${NC}" echo -e "${BLUE}=== Environment Files Found ===${NC}"
local count=0 local count=0
# Use a temp file to avoid subshell issues
local temp_file=$(mktemp)
find_env_files "$DOCKER_DIR" > "$temp_file"
while IFS= read -r env_file; do while IFS= read -r env_file; do
if [ -n "$env_file" ]; then if [ -n "$env_file" ]; then
local rel_path="${env_file#$DOCKER_DIR/}" local rel_path="${env_file#$DOCKER_DIR/}"
@@ -93,9 +97,12 @@ list_env_files() {
echo " Size: $size | Modified: $modified" echo " Size: $size | Modified: $modified"
echo " Full path: $env_file" echo " Full path: $env_file"
echo "" echo ""
((count++)) count=$((count + 1))
fi fi
done < <(find_env_files "$DOCKER_DIR") done < "$temp_file"
# Clean up temp file
rm -f "$temp_file"
echo -e "${BLUE}Total .env files found: $count${NC}" echo -e "${BLUE}Total .env files found: $count${NC}"
@@ -247,7 +254,10 @@ backup_env_files() {
local backup_count=0 local backup_count=0
local unchanged_count=0 local unchanged_count=0
# Process each .env file # Process each .env file using a temp file to avoid subshell issues
local temp_file=$(mktemp)
find_env_files "$DOCKER_DIR" > "$temp_file"
while IFS= read -r env_file; do while IFS= read -r env_file; do
if [ -n "$env_file" ]; then if [ -n "$env_file" ]; then
# Determine relative path and backup location # Determine relative path and backup location
@@ -268,7 +278,7 @@ backup_env_files() {
if [ -f "$backup_path" ] && [ "$force" != "true" ]; then if [ -f "$backup_path" ] && [ "$force" != "true" ]; then
if cmp -s "$env_file" "$backup_path"; then if cmp -s "$env_file" "$backup_path"; then
needs_backup=false needs_backup=false
((unchanged_count++)) unchanged_count=$((unchanged_count + 1))
fi fi
fi fi
@@ -276,7 +286,7 @@ backup_env_files() {
# Copy the file # Copy the file
cp "$env_file" "$backup_path" cp "$env_file" "$backup_path"
echo -e "${GREEN}✓ Backed up: $rel_path${NC}" echo -e "${GREEN}✓ Backed up: $rel_path${NC}"
((backup_count++)) backup_count=$((backup_count + 1))
# Also create a reference docker-compose.yml if it exists # Also create a reference docker-compose.yml if it exists
local compose_file=$(dirname "$env_file")/docker-compose.yml local compose_file=$(dirname "$env_file")/docker-compose.yml
@@ -290,7 +300,10 @@ backup_env_files() {
echo -e "${YELLOW}- Unchanged: $rel_path${NC}" echo -e "${YELLOW}- Unchanged: $rel_path${NC}"
fi fi
fi fi
done < <(find_env_files "$DOCKER_DIR") done < "$temp_file"
# Clean up temp file
rm -f "$temp_file"
if [ "$dry_run" = "true" ]; then if [ "$dry_run" = "true" ]; then
echo -e "${BLUE}Dry run completed. No files were actually backed up.${NC}" echo -e "${BLUE}Dry run completed. No files were actually backed up.${NC}"
@@ -374,44 +387,52 @@ restore_env_files() {
local restore_count=0 local restore_count=0
local error_count=0 local error_count=0
# Find all backed up .env files # Use a temp file to avoid subshell issues
find docker-containers -name "*.env" -type f 2>/dev/null | while IFS= read -r backup_file; do local temp_file=$(mktemp)
# Determine target path find docker-containers -name "*.env" -type f 2>/dev/null > "$temp_file"
local rel_path="${backup_file#docker-containers/}"
local target_file="$DOCKER_DIR/$rel_path" while IFS= read -r backup_file; do
local target_dir=$(dirname "$target_file") if [ -n "$backup_file" ]; then
# Determine target path
# Create target directory if it doesn't exist local rel_path="${backup_file#docker-containers/}"
if [ ! -d "$target_dir" ]; then local target_file="$DOCKER_DIR/$rel_path"
echo -e "${YELLOW}Creating directory: $target_dir${NC}" local target_dir=$(dirname "$target_file")
mkdir -p "$target_dir"
fi # Create target directory if it doesn't exist
if [ ! -d "$target_dir" ]; then
# Ask for confirmation if file exists and is different echo -e "${YELLOW}Creating directory: $target_dir${NC}"
if [ -f "$target_file" ]; then mkdir -p "$target_dir"
if ! cmp -s "$backup_file" "$target_file"; then fi
echo -e "${YELLOW}File exists and differs: $rel_path${NC}"
read -p "Overwrite? (y/N): " -n 1 -r # Ask for confirmation if file exists and is different
echo if [ -f "$target_file" ]; then
if [[ ! $REPLY =~ ^[Yy]$ ]]; then if ! cmp -s "$backup_file" "$target_file"; then
echo -e "${YELLOW}Skipped: $rel_path${NC}" echo -e "${YELLOW}File exists and differs: $rel_path${NC}"
read -p "Overwrite? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo -e "${YELLOW}Skipped: $rel_path${NC}"
continue
fi
else
echo -e "${GREEN}Identical: $rel_path${NC}"
continue continue
fi fi
fi
# Copy the file
if cp "$backup_file" "$target_file"; then
echo -e "${GREEN}✓ Restored: $rel_path${NC}"
restore_count=$((restore_count + 1))
else else
echo -e "${GREEN}Identical: $rel_path${NC}" echo -e "${RED}✗ Failed to restore: $rel_path${NC}"
continue error_count=$((error_count + 1))
fi fi
fi fi
done < "$temp_file"
# Copy the file
if cp "$backup_file" "$target_file"; then # Clean up temp file
echo -e "${GREEN}✓ Restored: $rel_path${NC}" rm -f "$temp_file"
((restore_count++))
else
echo -e "${RED}✗ Failed to restore: $rel_path${NC}"
((error_count++))
fi
done
echo -e "${GREEN}Restore completed!${NC}" echo -e "${GREEN}Restore completed!${NC}"
echo -e "${BLUE}Summary:${NC}" echo -e "${BLUE}Summary:${NC}"
@@ -479,7 +500,7 @@ main() {
if [ "$list_files" = true ]; then if [ "$list_files" = true ]; then
list_env_files list_env_files
elif [ "$init_repo" = true ]; then elif [ "$init_repo" = true ]; then
init_repo init_backup_repo
elif [ "$restore" = true ]; then elif [ "$restore" = true ]; then
restore_env_files restore_env_files
else else

View File

@@ -1,6 +1,8 @@
0 1 * * * /home/acedanger/shell/move-backups.sh 2>&1 | logger -t backup-move -p user.info 0 1 * * * /home/acedanger/shell/move-backups.sh 2>&1 | logger -t backup-move -p user.info
0 2 * * * { echo "Starting .env files backup"; /home/acedanger/shell/backup-env-files.sh; echo ".env backup completed with exit code: $?"; } 2>&1 | logger -t env-backup -p user.info
15 4 * * * { echo "Starting Plex backup"; /home/acedanger/shell/plex/backup-plex.sh --non-interactive --auto-repair; echo "Plex backup completed with exit code: $?"; } 2>&1 | logger -t plex-backup -p user.info 15 4 * * * { echo "Starting Plex backup"; /home/acedanger/shell/plex/backup-plex.sh --non-interactive --auto-repair; echo "Plex backup completed with exit code: $?"; } 2>&1 | logger -t plex-backup -p user.info
0 7 * * * { echo "Starting Plex backup validation"; /home/acedanger/shell/plex/validate-plex-backups.sh --fix; echo "Validation completed with exit code: $?"; } 2>&1 | logger -t plex-validation -p user.info 0 7 * * * { echo "Starting Plex backup validation"; /home/acedanger/shell/plex/validate-plex-backups.sh --fix; echo "Validation completed with exit code: $?"; } 2>&1 | logger -t plex-validation -p user.info
0 5 * * 1 { echo "Starting Immich database backup move"; if mv /mnt/share/media/immich/uploads/backups/immich-db-backup* /mnt/share/media/backups/immich 2>/dev/null; then echo "Immich backup move completed successfully"; else echo "No Immich backup files found or move failed"; fi; } 2>&1 | logger -t immich-backup -p user.info 0 5 * * 1 { echo "Starting Immich database backup move"; if mv /mnt/share/media/immich/uploads/backups/immich-db-backup* /mnt/share/media/backups/immich 2>/dev/null; then echo "Immich backup move completed successfully"; else echo "No Immich backup files found or move failed"; fi; } 2>&1 | logger -t immich-backup -p user.info
0 4 * * * /home/acedanger/shell/crontab/crontab-backup-system.sh backup auto --auto-cleanup 2>&1 | logger -t crontab-backup -p user.info 0 4 * * * /home/acedanger/shell/crontab/crontab-backup-system.sh backup auto --auto-cleanup 2>&1 | logger -t crontab-backup -p user.info
0 8 * * 0 { echo "Starting weekly Plex backup report generation"; /home/acedanger/shell/plex/validate-plex-backups.sh --report; echo "Weekly report generation completed with exit code: $?"; } 2>&1 | logger -t plex-report -p user.info 0 8 * * 0 { echo "Starting weekly Plex backup report generation"; /home/acedanger/shell/plex/validate-plex-backups.sh --report; echo "Weekly report generation completed with exit code: $?"; } 2>&1 | logger -t plex-report -p user.info
30 8 * * 0 { echo "Starting .env backup validation"; /home/acedanger/shell/validate-env-backups.sh; echo ".env validation completed with exit code: $?"; } 2>&1 | logger -t env-validation -p user.info

View File

@@ -10,6 +10,14 @@
# Daily system backup at 0400 with auto-cleanup # Daily system backup at 0400 with auto-cleanup
0 4 * * * /home/acedanger/shell/crontab/crontab-backup-system.sh backup auto --auto-cleanup 2>&1 | logger -t crontab-backup -p user.info 0 4 * * * /home/acedanger/shell/crontab/crontab-backup-system.sh backup auto --auto-cleanup 2>&1 | logger -t crontab-backup -p user.info
# Daily .env files backup at 0300 with enhanced logging
# Backs up Docker container .env files to Git repository
0 3 * * * { echo "Starting .env files backup"; /home/acedanger/shell/backup-env-files.sh; echo ".env backup completed with exit code: $?"; } 2>&1 | logger -t env-backup -p user.info
# Weekly .env backup validation at 0830 on Sundays
# Validates the integrity of .env backup repository
30 8 * * 0 { echo "Starting .env backup validation"; /home/acedanger/shell/validate-env-backups.sh; echo ".env validation completed with exit code: $?"; } 2>&1 | logger -t env-validation -p user.info
# Optional: Monitor Docker container health (every 6 hours) # Optional: Monitor Docker container health (every 6 hours)
# This can help detect if any download services are failing # This can help detect if any download services are failing
# 0 */6 * * * { echo "Docker health check"; docker ps --format "table {{.Names}}\t{{.Status}}" | grep -v "Up"; } 2>&1 | logger -t docker-health -p user.info # 0 */6 * * * { echo "Docker health check"; docker ps --format "table {{.Names}}\t{{.Status}}" | grep -v "Up"; } 2>&1 | logger -t docker-health -p user.info

View File

@@ -9,6 +9,14 @@
# Daily system backup at 0400 with auto-cleanup # Daily system backup at 0400 with auto-cleanup
0 4 * * * /home/acedanger/shell/crontab/crontab-backup-system.sh backup auto --auto-cleanup 2>&1 | logger -t crontab-backup -p user.info 0 4 * * * /home/acedanger/shell/crontab/crontab-backup-system.sh backup auto --auto-cleanup 2>&1 | logger -t crontab-backup -p user.info
# Daily .env files backup at 0300 with enhanced logging
# Backs up Docker container .env files to Git repository
0 3 * * * { echo "Starting .env files backup"; /home/acedanger/shell/backup-env-files.sh; echo ".env backup completed with exit code: $?"; } 2>&1 | logger -t env-backup -p user.info
# Weekly .env backup validation at 0830 on Sundays
# Validates the integrity of .env backup repository
30 8 * * 0 { echo "Starting .env backup validation"; /home/acedanger/shell/validate-env-backups.sh; echo ".env validation completed with exit code: $?"; } 2>&1 | logger -t env-validation -p user.info
# Optional: Add a health check entry to monitor backup jobs (every 6 hours) # Optional: Add a health check entry to monitor backup jobs (every 6 hours)
# This can help detect if the backup process is failing # This can help detect if the backup process is failing
# 0 */6 * * * { echo "Cron health check - Docker backup job scheduled"; ps aux | grep "backup-docker" | grep -v grep | wc -l; } 2>&1 | logger -t cron-health -p user.info # 0 */6 * * * { echo "Cron health check - Docker backup job scheduled"; ps aux | grep "backup-docker" | grep -v grep | wc -l; } 2>&1 | logger -t cron-health -p user.info

View File

@@ -5,6 +5,7 @@
Your .env backup system is now fully operational! Here's what was set up: Your .env backup system is now fully operational! Here's what was set up:
### ✅ What's Working ### ✅ What's Working
- **31 .env files** discovered across your Docker containers - **31 .env files** discovered across your Docker containers
- **30 files backed up** successfully to `/home/acedanger/.env-backup` - **30 files backed up** successfully to `/home/acedanger/.env-backup`
- **Private Gitea repository** configured and pushed successfully - **Private Gitea repository** configured and pushed successfully
@@ -14,6 +15,7 @@ Your .env backup system is now fully operational! Here's what was set up:
### 🔧 Integration Options ### 🔧 Integration Options
#### 1. Manual Backup (Current) #### 1. Manual Backup (Current)
```bash ```bash
cd /home/acedanger/shell cd /home/acedanger/shell
./backup-env-files.sh # Regular backup ./backup-env-files.sh # Regular backup
@@ -22,14 +24,18 @@ cd /home/acedanger/shell
``` ```
#### 2. Automated Daily Backup (Recommended) #### 2. Automated Daily Backup (Recommended)
Add to your crontab for daily backups at 2 AM: Add to your crontab for daily backups at 2 AM:
```bash ```bash
# Daily .env backup at 2 AM # Daily .env backup at 2 AM
0 2 * * * /home/acedanger/shell/backup-env-files.sh >/dev/null 2>&1 0 2 * * * /home/acedanger/shell/backup-env-files.sh >/dev/null 2>&1
``` ```
#### 3. Integration with Existing Backup Scripts #### 3. Integration with Existing Backup Scripts
The backup integrates with your existing backup system through: The backup integrates with your existing backup system through:
- **Logs**: Written to `/home/acedanger/shell/logs/env-backup.log` - **Logs**: Written to `/home/acedanger/shell/logs/env-backup.log`
- **Completion**: Tab completion available via `env-backup-completion.bash` - **Completion**: Tab completion available via `env-backup-completion.bash`
- **Validation**: Use `validate-env-backups.sh` for integrity checks - **Validation**: Use `validate-env-backups.sh` for integrity checks
@@ -64,16 +70,19 @@ The backup integrates with your existing backup system through:
### 🔄 Common Operations ### 🔄 Common Operations
#### Restore Files (if needed) #### Restore Files (if needed)
```bash ```bash
./backup-env-files.sh --restore ./backup-env-files.sh --restore
``` ```
#### Force Backup (ignore unchanged files) #### Force Backup (ignore unchanged files)
```bash ```bash
./backup-env-files.sh --force ./backup-env-files.sh --force
``` ```
#### Check What Would Change #### Check What Would Change
```bash ```bash
./backup-env-files.sh --dry-run ./backup-env-files.sh --dry-run
``` ```
@@ -95,27 +104,32 @@ If you lose your filesystem:
### 🔧 Maintenance ### 🔧 Maintenance
#### Weekly Validation (Recommended) #### Weekly Validation (Recommended)
```bash ```bash
# Add to crontab for weekly validation # Add to crontab for weekly validation
0 3 * * 0 /home/acedanger/shell/validate-env-backups.sh >/dev/null 2>&1 0 3 * * 0 /home/acedanger/shell/validate-env-backups.sh >/dev/null 2>&1
``` ```
#### Cleanup Old Logs (Monthly) #### Cleanup Old Logs (Monthly)
The system automatically manages logs, but you can clean them manually if needed. The system automatically manages logs, but you can clean them manually if needed.
### 🆘 Troubleshooting ### 🆘 Troubleshooting
#### Push Fails #### Push Fails
- Check SSH key: `ssh -T git@git.ptrwd.com` - Check SSH key: `ssh -T git@git.ptrwd.com`
- Verify repository exists and is private - Verify repository exists and is private
- Check network connectivity - Check network connectivity
#### Files Not Found #### Files Not Found
- Verify Docker directory structure: `ls -la ~/docker/*/` - Verify Docker directory structure: `ls -la ~/docker/*/`
- Check file permissions - Check file permissions
- Run with `--list` to see what's detected - Run with `--list` to see what's detected
#### Restore Issues #### Restore Issues
- Ensure target directories exist - Ensure target directories exist
- Check file permissions - Check file permissions
- Use `--dry-run` first to preview - Use `--dry-run` first to preview
@@ -123,6 +137,7 @@ The system automatically manages logs, but you can clean them manually if needed
## Integration Complete! 🎉 ## Integration Complete! 🎉
Your .env files are now safely backed up and version controlled. The system will: Your .env files are now safely backed up and version controlled. The system will:
1. Track all changes to your .env files 1. Track all changes to your .env files
2. Maintain a secure backup in your private Gitea 2. Maintain a secure backup in your private Gitea
3. Provide easy restore capabilities 3. Provide easy restore capabilities

View File

@@ -207,6 +207,7 @@ The system automatically finds:
### Common Issues ### Common Issues
1. **Git Push Fails** 1. **Git Push Fails**
```bash ```bash
# Check remote URL # Check remote URL
cd ~/.env-backup && git remote -v cd ~/.env-backup && git remote -v
@@ -216,6 +217,7 @@ The system automatically finds:
``` ```
2. **Missing Files** 2. **Missing Files**
```bash ```bash
# List what would be found # List what would be found
./backup-env-files.sh --list ./backup-env-files.sh --list
@@ -279,12 +281,14 @@ git status --porcelain
### Additional Security Measures ### Additional Security Measures
1. **GPG Encryption** (Optional) 1. **GPG Encryption** (Optional)
```bash ```bash
# Encrypt sensitive files before committing # Encrypt sensitive files before committing
gpg --symmetric --cipher-algo AES256 file.env gpg --symmetric --cipher-algo AES256 file.env
``` ```
2. **Restricted Permissions** 2. **Restricted Permissions**
```bash ```bash
# Secure backup directory # Secure backup directory
chmod 700 ~/.env-backup chmod 700 ~/.env-backup
@@ -292,6 +296,7 @@ git status --porcelain
``` ```
3. **Audit Trail** 3. **Audit Trail**
```bash ```bash
# Monitor repository access # Monitor repository access
git log --oneline --graph --all git log --oneline --graph --all