frappe_docker/production/backup/README.md
duthink e41569e459 Add ERPNext Backup System Documentation and Scripts
- Created README.md for comprehensive ERPNext backup system setup and management.
- Implemented backup-to-s3.sh script for automated backups to Digital Ocean Spaces.
- Added compose.backup-s3.yaml for Docker Compose configuration of backup services.
- Developed manage-backups.sh script for managing backup processes and configurations.
2025-11-20 17:31:22 +05:30

414 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ERPNext Backup System - Complete Guide
Automated backup system with Digital Ocean Spaces (S3) for ERPNext production.
---
## 🚀 Quick Production Setup (5 minutes)
### Option 1: Interactive Setup
```bash
cd production/backup
./manage-backups.sh setup # Interactive wizard
chmod 600 backup.env
./manage-backups.sh start
./manage-backups.sh test
```
### Option 2: Manual Configuration
**Edit `backup/backup.env`:**
```bash
ENV_PREFIX=production # Change from 'development'
BACKUP_SITES=your-domain.com # Change from 'erp.localhost'
S3_BACKUP_RETENTION_DAYS=30 # Increase from 5
S3_ACCESS_KEY_ID=your-key
S3_SECRET_ACCESS_KEY=your-secret
```
**Deploy:**
```bash
chmod 600 backup/backup.env
./manage-backups.sh restart
./manage-backups.sh test
./manage-backups.sh list-s3 | grep "production/"
```
**Verify automated backups:**
- Hourly DB backup runs every hour from container start time
- Daily full backup runs at 3:00 AM
- Check status: `./manage-backups.sh status`
- Monitor logs: `./manage-backups.sh logs`
---
## 📦 What Gets Backed Up?
### Always Included
**Database** - All data, doctypes, settings (compressed SQL)
### Backup Modes
**Full Backup** (recommended for daily):
```bash
BACKUP_WITH_FILES=1 # Everything: DB + all files + site_config
```
**Database Only** (recommended for frequent/hourly):
```bash
BACKUP_WITH_FILES=0 # Database + site_config only
```
**What's in site_config.json:**
```json
{
"db_name": "_73c82ec6d255ebe3",
"db_password": "Dp0yVfnoBvwYpR0y",
"db_type": "mariadb"
}
```
*Note: production.env and other secrets are NOT included*
---
## ⏰ Backup Schedules
### Single Schedule (Simple)
```bash
# Note: For dual-schedule setup, see compose.backup-s3.yaml
# Single schedule is not commonly used in production
BACKUP_CRON_SCHEDULE=@every 1h # Every hour
```
### Dual Schedule (Recommended for Your Use Case)
**Frequent DB backups + Occasional full backups:**
Edit `compose.backup-s3.yaml` to add two jobs:
```yaml
scheduler:
labels:
# Job 1: Hourly database-only backup (official @every syntax)
ofelia.job-exec.backup-db.schedule: "@every 1h"
ofelia.job-exec.backup-db.command: "bash -c 'export BACKUP_WITH_FILES=0 && /bin/bash /usr/local/bin/backup-to-s3.sh'"
ofelia.job-exec.backup-db.user: "frappe"
ofelia.job-exec.backup-db.no-overlap: "true"
# Job 2: Daily full backup at 3 AM (standard cron)
ofelia.job-exec.backup-full.schedule: "0 3 * * *"
ofelia.job-exec.backup-full.command: "bash -c 'export BACKUP_WITH_FILES=1 && /bin/bash /usr/local/bin/backup-to-s3.sh'"
ofelia.job-exec.backup-full.user: "frappe"
ofelia.job-exec.backup-full.no-overlap: "true"
```
### Common Schedules
```bash
# Interval syntax (recommended for sub-daily)
@every 1h # Every hour
@every 2h # Every 2 hours
@every 30m # Every 30 minutes
# Standard cron format (for specific times)
0 3 * * * # Daily at 3 AM
0 3 * * 0 # Weekly on Sunday at 3 AM
0 0,12 * * * # Twice daily (midnight and noon)
```
**References:**
- [Go cron intervals](https://pkg.go.dev/github.com/robfig/cron/v3#hdr-Intervals)
- [Cron format generator](https://crontab.guru/)
---
## 🗂️ S3 Structure & Environment Segregation
```
s3://erp-is-backup/
├── production/ ← ENV_PREFIX=production
│ └── erp.example.com/
│ └── 2025-11-20/ ← Single date folder
│ ├── 20251120_120000-database.sql.gz
│ ├── 20251120_120000-files.tar
│ └── 20251120_120000-site_config_backup.json
├── staging/ ← ENV_PREFIX=staging
├── development/ ← ENV_PREFIX=development
└── local/ ← ENV_PREFIX=local
```
**Set environment:**
```bash
ENV_PREFIX=production # For production
ENV_PREFIX=staging # For staging
ENV_PREFIX=local # For local dev
```
---
## ⚙️ Configuration
**File:** `backup/backup.env`
### Essential Settings
```bash
# Credentials (MUST CHANGE)
S3_ACCESS_KEY_ID=your_key_here
S3_SECRET_ACCESS_KEY=your_secret_here
# S3 Config
S3_ENDPOINT_URL=https://blr1.digitaloceanspaces.com
S3_BUCKET_NAME=erp-is-backup
S3_REGION=blr1
# Environment
ENV_PREFIX=production
# Schedule (configured in compose.backup-s3.yaml)
# See "Dual Schedule" section for details
# What to backup
BACKUP_WITH_FILES=1 # 1=DB+files, 0=DB only
BACKUP_COMPRESS=1 # Compress SQL (recommended)
# Sites
BACKUP_SITES=erp.localhost
# Retention
BACKUP_RETENTION_DAYS=7 # Local retention
S3_BACKUP_RETENTION_DAYS=30 # S3 retention
```
---
## 🛠️ Management Commands
```bash
cd production/backup
# Service control
./manage-backups.sh start # Start backup services
./manage-backups.sh stop # Stop backup services
./manage-backups.sh restart # Restart services
# Operations
./manage-backups.sh test # Run backup now
./manage-backups.sh status # Check status
./manage-backups.sh logs # View logs
./manage-backups.sh list-s3 # List S3 backups
./manage-backups.sh validate # Validate config
# Interactive setup
./manage-backups.sh setup # Configuration wizard
```
---
## 📋 Example Configurations
### Dual Schedule: Hourly DB + Daily Full (Recommended)
```bash
# backup.env
ENV_PREFIX=production
BACKUP_SITES=erp.localhost
BACKUP_WITH_FILES=0 # Default (overridden by cron)
BACKUP_COMPRESS=1
BACKUP_RETENTION_DAYS=1 # Keep local 1 day
S3_BACKUP_RETENTION_DAYS=5 # Keep S3 5 days
# Schedules are in compose.backup-s3.yaml:
# - Hourly: BACKUP_WITH_FILES=0 (DB only)
# - Daily 3AM: BACKUP_WITH_FILES=1 (Full)
```
### High-Traffic Production
```bash
# Note: Schedule is set in compose.backup-s3.yaml, not in backup.env
ENV_PREFIX=production
BACKUP_WITH_FILES=1
S3_BACKUP_RETENTION_DAYS=90
# In compose.backup-s3.yaml:
# ofelia.job-exec.backup-db.schedule: "@every 2h"
```
### Staging/Dev
```bash
ENV_PREFIX=staging
BACKUP_WITH_FILES=0 # DB only
S3_BACKUP_RETENTION_DAYS=14
# In compose.backup-s3.yaml:
# ofelia.job-exec.backup-daily.schedule: "0 3 * * *"
```
---
## 🔄 Restore Process
### Download from S3
```bash
# List backups
aws s3 ls s3://erp-is-backup/production/erp.localhost/ --recursive \
--endpoint-url=https://blr1.digitaloceanspaces.com
# Download specific backup
aws s3 cp s3://erp-is-backup/production/erp.localhost/2025-11-20/backup.sql.gz . \
--endpoint-url=https://blr1.digitaloceanspaces.com
```
### Restore Database
```bash
# Copy to container
docker cp backup.sql.gz erpnext-production-backend:/tmp/
# Restore
docker compose -p erpnext-production exec backend \
bench --site erp.localhost --force restore /tmp/backup.sql.gz
```
### Restore with Files
```bash
docker compose -p erpnext-production exec backend \
bench --site erp.localhost --force restore \
--with-public-files /tmp/files.tar \
--with-private-files /tmp/private-files.tar \
/tmp/backup.sql.gz
```
---
## 🔍 Monitoring
### Check Status
```bash
./manage-backups.sh status
# Or manually
docker ps | grep backup
docker compose -p erpnext-production logs -f backup-cron
```
### View Recent Backups
```bash
# Local backups
docker compose -p erpnext-production exec scheduler \
ls -lht /home/frappe/frappe-bench/sites/*/private/backups/ | head -10
# S3 backups
./manage-backups.sh list-s3
```
---
## 📁 File Structure
```
production/
├── backup/ ← All backup configs here
│ ├── backup.env ← Main configuration
│ ├── compose.backup-s3.yaml ← Docker compose override
│ ├── backup-to-s3.sh ← S3 backup script
│ ├── backup-site.sh ← Local backup script
│ └── manage-backups.sh ← Management helper
├── backups/ ← Local backup storage
│ └── {timestamp}-{site}-*.{sql.gz|tar|json}
├── scripts/ ← Other scripts
└── docs/ ← This documentation
```
---
## 🚨 Troubleshooting
### Services Not Running
```bash
./manage-backups.sh restart
docker ps -a | grep backup
```
### S3 Upload Fails
- Check credentials in `backup.env`
- Verify bucket exists in Digital Ocean
- Test connection: `./manage-backups.sh validate`
### No Backups Created
```bash
# Verify site name
docker compose -p erpnext-production exec backend bench list-apps
# Check site in backup.env matches actual site
grep BACKUP_SITES backup.env
# Run with debug
docker compose -p erpnext-production exec scheduler bash -c "
export BACKUP_DEBUG=1
/bin/bash /usr/local/bin/backup-to-s3.sh
"
```
### AWS CLI Missing
Script auto-installs, but if issues:
```bash
docker compose -p erpnext-production exec scheduler bash -c "
pip3 install --user awscli --upgrade
export PATH=\"\$HOME/.local/bin:\$PATH\"
aws --version
"
```
---
## 🔐 Security
```bash
# Protect credentials
chmod 600 backup/backup.env
# Gitignore
echo "production/backup/backup.env" >> .gitignore
# Use Digital Ocean IAM
# Create dedicated API keys with bucket-only access
```
---
## 💡 Best Practices
1. **Test Restores** - Regularly test restore in staging
2. **Monitor Sizes** - Check backup sizes, adjust file inclusion
3. **Environment Prefix** - Always use for clarity
4. **Start Conservative** - Begin with less frequent, increase as needed
5. **Document Changes** - Note when you modify backup config
---
## Storage Estimates
| Frequency | With Files | DB Only | Monthly (30d) |
|-----------|-----------|---------|---------------|
| Hourly | ~200MB × 24 = 4.8GB/day | ~50MB × 24 = 1.2GB/day | 144GB / 36GB |
| Every 6h | ~200MB × 4 = 800MB/day | ~50MB × 4 = 200MB/day | 24GB / 6GB |
| Daily | ~200MB × 1 = 200MB/day | ~50MB × 1 = 50MB/day | 6GB / 1.5GB |
**Your Config (Hourly DB + Daily Full):**
- Hourly DB: ~50MB × 24 = 1.2GB/day
- Daily Full: ~200MB × 1 = 200MB/day
- **Total: ~1.4GB/day = ~42GB/month** (30 day retention)
---
## Support & Resources
- [Digital Ocean Spaces Docs](https://docs.digitalocean.com/products/spaces/)
- [Ofelia Cron Scheduler](https://github.com/mcuadros/ofelia)
- [ERPNext Backup Docs](https://frappeframework.com/docs/user/en/bench/reference/backup)
- [Cron Schedule Generator](https://crontab.guru/)
**Management Script:**
```bash
./manage-backups.sh help
```