595 lines
14 KiB
Markdown
595 lines
14 KiB
Markdown
# WebGIS Poverty Mapping - Backup & Recovery Plan
|
|
|
|
**Version:** 1.0
|
|
**Last Updated:** May 2026
|
|
**Classification:** Important
|
|
|
|
## Executive Summary
|
|
|
|
This document outlines the backup and recovery strategy for the WebGIS Poverty Mapping application. It ensures business continuity, data protection, and rapid recovery from data loss or system failures.
|
|
|
|
### Key Objectives
|
|
|
|
- **Prevent Data Loss:** Regular backups at multiple intervals
|
|
- **Ensure Business Continuity:** Rapid recovery procedures
|
|
- **Minimize Downtime:** RTO ≤ 4 hours, RPO ≤ 1 day
|
|
- **Compliance:** Maintain audit trail and regulatory requirements
|
|
|
|
---
|
|
|
|
## 1. Backup Strategy
|
|
|
|
### 1.1 Backup Schedule
|
|
|
|
| Backup Type | Frequency | Retention | Storage |
|
|
|-------------|-----------|-----------|---------|
|
|
| **Full Daily** | Every day at 2:00 AM | 7 days | Local + Network Drive |
|
|
| **Weekly** | Every Sunday at 3:00 AM | 4 weeks | Local + External HDD |
|
|
| **Monthly** | First day of month at 4:00 AM | 1 year | External HDD Archive |
|
|
| **Transaction Log** | Hourly (if available) | 3 days | Local |
|
|
|
|
### 1.2 Backup Methods
|
|
|
|
#### Method 1: MySQL Dump (Recommended)
|
|
|
|
```bash
|
|
# Full database backup
|
|
mysqldump -u root -p --single-transaction --result-file=/backup/webgis_full_$(date +%Y%m%d).sql webgis_unified
|
|
|
|
# With compression (smaller file)
|
|
mysqldump -u root -p webgis_unified | gzip > /backup/webgis_full_$(date +%Y%m%d).sql.gz
|
|
```
|
|
|
|
#### Method 2: Scheduled Backup Script
|
|
|
|
Create `/backup/backup.sh`:
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
# Configuration
|
|
DB_NAME="webgis_unified"
|
|
DB_USER="root"
|
|
DB_PASSWORD="YourPassword"
|
|
BACKUP_DIR="/backup"
|
|
DATE=$(date +%Y%m%d_%H%M%S)
|
|
BACKUP_FILE="$BACKUP_DIR/webgis_backup_$DATE.sql"
|
|
|
|
# Create backup
|
|
echo "Starting backup: $DATE"
|
|
mysqldump -u $DB_USER -p$DB_PASSWORD $DB_NAME > $BACKUP_FILE
|
|
|
|
# Compress
|
|
gzip $BACKUP_FILE
|
|
BACKUP_FILE="${BACKUP_FILE}.gz"
|
|
|
|
# Check file size
|
|
SIZE=$(du -h $BACKUP_FILE | cut -f1)
|
|
echo "Backup completed: $BACKUP_FILE ($SIZE)"
|
|
|
|
# Remove old backups (keep 7 days)
|
|
find $BACKUP_DIR -name "webgis_backup_*.sql.gz" -mtime +7 -delete
|
|
|
|
# Copy to network drive (optional)
|
|
cp $BACKUP_FILE /mnt/network_backup/
|
|
|
|
# Verify backup
|
|
if gzip -t $BACKUP_FILE; then
|
|
echo "Backup verification: SUCCESS"
|
|
else
|
|
echo "Backup verification: FAILED" | mail -s "Backup Failed" admin@example.com
|
|
fi
|
|
```
|
|
|
|
#### Method 3: Automated Cron Job
|
|
|
|
Edit crontab:
|
|
|
|
```bash
|
|
crontab -e
|
|
```
|
|
|
|
Add:
|
|
|
|
```cron
|
|
# Daily backup at 2:00 AM
|
|
0 2 * * * /backup/backup.sh
|
|
|
|
# Weekly backup (Sunday 3:00 AM)
|
|
0 3 * * 0 /backup/backup_weekly.sh
|
|
|
|
# Monthly backup (1st day 4:00 AM)
|
|
0 4 1 * * /backup/backup_monthly.sh
|
|
```
|
|
|
|
### 1.3 Backup Storage
|
|
|
|
#### Local Storage
|
|
|
|
```
|
|
/backup/
|
|
├── webgis_backup_20260520_020000.sql.gz
|
|
├── webgis_backup_20260519_020000.sql.gz
|
|
├── webgis_backup_20260518_020000.sql.gz
|
|
└── ... (7 days of daily backups)
|
|
```
|
|
|
|
#### Network Storage
|
|
|
|
```
|
|
/mnt/network_backup/
|
|
├── Daily/ (7 copies)
|
|
├── Weekly/ (4 copies)
|
|
└── Monthly/ (12 copies)
|
|
```
|
|
|
|
#### External HDD
|
|
|
|
- Store weekly and monthly backups
|
|
- Keep in secure location (fire-proof safe recommended)
|
|
- Update quarterly
|
|
|
|
### 1.4 File-Level Backup
|
|
|
|
```bash
|
|
# Backup application files
|
|
tar -czf /backup/webgis_files_$(date +%Y%m%d).tar.gz /var/www/html/webgis/
|
|
|
|
# Backup PHP configuration
|
|
tar -czf /backup/php_config_$(date +%Y%m%d).tar.gz /etc/php/
|
|
|
|
# Backup Apache configuration
|
|
tar -czf /backup/apache_config_$(date +%Y%m%d).tar.gz /etc/apache2/
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Recovery Procedures
|
|
|
|
### 2.1 Full Recovery (Complete Restore)
|
|
|
|
**Scenario:** Database completely corrupted or lost
|
|
|
|
**Time to Recover:** 30-60 minutes
|
|
|
|
**Steps:**
|
|
|
|
1. **Stop Application**
|
|
```bash
|
|
sudo systemctl stop apache2
|
|
```
|
|
|
|
2. **Backup Current Database** (if possible)
|
|
```bash
|
|
mysqldump -u root -p webgis_unified > current_backup_$(date +%Y%m%d).sql
|
|
```
|
|
|
|
3. **Drop Current Database**
|
|
```bash
|
|
mysql -u root -p
|
|
DROP DATABASE webgis_unified;
|
|
```
|
|
|
|
4. **Restore from Backup**
|
|
```bash
|
|
# Unzip if compressed
|
|
gunzip /backup/webgis_backup_20260520.sql.gz
|
|
|
|
# Restore
|
|
mysql -u root -p < /backup/webgis_backup_20260520.sql
|
|
```
|
|
|
|
5. **Verify Recovery**
|
|
```bash
|
|
mysql -u root -p
|
|
USE webgis_unified;
|
|
SHOW TABLES;
|
|
SELECT COUNT(*) FROM data_unified;
|
|
```
|
|
|
|
6. **Restart Application**
|
|
```bash
|
|
sudo systemctl start apache2
|
|
```
|
|
|
|
7. **Test Application**
|
|
- Access http://localhost/webgis/
|
|
- Verify data is present
|
|
- Check recent data
|
|
|
|
### 2.2 Partial Recovery (Selective Tables)
|
|
|
|
**Scenario:** Only specific tables corrupted
|
|
|
|
**Time to Recover:** 15-30 minutes
|
|
|
|
**Steps:**
|
|
|
|
1. **Export Specific Table from Backup**
|
|
```bash
|
|
# Extract table from backup
|
|
gunzip -c /backup/webgis_backup_20260520.sql.gz | \
|
|
mysql -u root -p -e "USE webgis_unified; SOURCE /dev/stdin"
|
|
```
|
|
|
|
2. **Or Restore Specific Table**
|
|
```bash
|
|
# Create temporary database
|
|
mysql -u root -p -e "CREATE DATABASE temp_restore"
|
|
|
|
# Restore backup to temporary DB
|
|
mysql -u root -p temp_restore < /backup/webgis_backup_20260520.sql
|
|
|
|
# Copy specific table
|
|
mysql -u root -p -e "
|
|
USE webgis_unified;
|
|
DROP TABLE IF EXISTS data_unified;
|
|
RENAME TABLE temp_restore.data_unified TO webgis_unified.data_unified;
|
|
"
|
|
|
|
# Drop temporary DB
|
|
mysql -u root -p -e "DROP DATABASE temp_restore"
|
|
```
|
|
|
|
### 2.3 Point-in-Time Recovery (Specific Date/Time)
|
|
|
|
**Scenario:** Need to recover data from specific point in time
|
|
|
|
**Requirements:** Transaction logs or multiple daily backups
|
|
|
|
**Steps:**
|
|
|
|
1. **Identify Target Point in Time**
|
|
```bash
|
|
# Example: Recover to May 18, 2:00 PM
|
|
TARGET_DATE="2026-05-18 14:00:00"
|
|
```
|
|
|
|
2. **Restore Latest Backup Before Target**
|
|
```bash
|
|
# Find appropriate backup
|
|
ls -la /backup/webgis_backup_20260518*.sql.gz
|
|
```
|
|
|
|
3. **Restore Full Backup**
|
|
```bash
|
|
mysql -u root -p webgis_unified < /backup/webgis_backup_20260518_020000.sql
|
|
```
|
|
|
|
4. **Apply Transaction Log** (if available)
|
|
```bash
|
|
# Apply changes up to target time
|
|
# Requires binary logging to be enabled
|
|
```
|
|
|
|
### 2.4 Disaster Recovery (System-Wide Failure)
|
|
|
|
**Scenario:** Entire server lost
|
|
|
|
**Time to Recover:** 2-4 hours
|
|
|
|
**Steps:**
|
|
|
|
1. **Provision New Server**
|
|
- Install Ubuntu 18.04 LTS
|
|
- Install Apache, PHP, MySQL
|
|
|
|
2. **Restore Application Files**
|
|
```bash
|
|
cd /var/www/html/
|
|
tar -xzf /external_storage/webgis_files_20260520.tar.gz
|
|
```
|
|
|
|
3. **Restore Database**
|
|
```bash
|
|
mysql -u root -p < /external_storage/webgis_backup_20260520.sql
|
|
```
|
|
|
|
4. **Restore Configurations**
|
|
```bash
|
|
tar -xzf /external_storage/apache_config_20260520.tar.gz -C /
|
|
tar -xzf /external_storage/php_config_20260520.tar.gz -C /
|
|
```
|
|
|
|
5. **Update Network Configuration**
|
|
- Update DNS records
|
|
- Configure IP addresses
|
|
- Update firewall rules
|
|
|
|
6. **Start Services**
|
|
```bash
|
|
sudo systemctl start apache2
|
|
sudo systemctl start mysql
|
|
```
|
|
|
|
7. **Verify Everything**
|
|
- Test website
|
|
- Check database connectivity
|
|
- Verify data integrity
|
|
|
|
---
|
|
|
|
## 3. Backup Verification
|
|
|
|
### 3.1 Regular Testing
|
|
|
|
**Monthly Backup Test:** (1st Sunday of each month)
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# Test backup by restoring to test database
|
|
|
|
echo "Starting monthly backup test..."
|
|
|
|
# Create test database
|
|
mysql -u root -p -e "DROP DATABASE IF EXISTS webgis_test; CREATE DATABASE webgis_test;"
|
|
|
|
# Restore latest backup
|
|
LATEST_BACKUP=$(ls -t /backup/webgis_backup_*.sql.gz | head -1)
|
|
gunzip -c $LATEST_BACKUP | mysql -u root -p webgis_test
|
|
|
|
# Verify
|
|
RECORD_COUNT=$(mysql -u root -p -e "USE webgis_test; SELECT COUNT(*) FROM data_unified;")
|
|
|
|
if [ "$RECORD_COUNT" -gt 0 ]; then
|
|
echo "Backup test PASSED - Restored $RECORD_COUNT records"
|
|
mail -s "Backup Test Passed" admin@example.com
|
|
else
|
|
echo "Backup test FAILED"
|
|
mail -s "ALERT: Backup Test Failed" admin@example.com
|
|
fi
|
|
|
|
# Cleanup
|
|
mysql -u root -p -e "DROP DATABASE webgis_test;"
|
|
```
|
|
|
|
### 3.2 Integrity Checks
|
|
|
|
```bash
|
|
# Check backup file integrity
|
|
gzip -t /backup/webgis_backup_20260520.sql.gz
|
|
|
|
# Verify backup size
|
|
du -h /backup/webgis_backup_20260520.sql.gz
|
|
|
|
# Test restore to temporary location
|
|
mysql -u root -p -e "CREATE DATABASE test_restore"
|
|
gunzip -c /backup/webgis_backup_20260520.sql.gz | mysql -u root -p test_restore
|
|
mysql -u root -p test_restore -e "SELECT COUNT(*) FROM data_unified"
|
|
mysql -u root -p -e "DROP DATABASE test_restore"
|
|
```
|
|
|
|
### 3.3 Audit Trail Verification
|
|
|
|
```sql
|
|
-- Verify audit log is being populated
|
|
SELECT COUNT(*) FROM audit_log;
|
|
|
|
-- Check recent activity
|
|
SELECT * FROM audit_log ORDER BY changed_at DESC LIMIT 10;
|
|
|
|
-- Verify data consistency
|
|
SELECT COUNT(*) FROM data_unified;
|
|
SELECT COUNT(DISTINCT tipe) FROM data_unified;
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Retention Policy
|
|
|
|
### 4.1 Backup Retention
|
|
|
|
| Backup Type | Retention Period | Storage Location |
|
|
|-------------|-----------------|-----------------|
|
|
| Daily | 7 days | Local server |
|
|
| Weekly | 4 weeks | Network drive |
|
|
| Monthly | 1 year | External HDD |
|
|
| Quarterly Archive | 7 years | Off-site (optional) |
|
|
|
|
### 4.2 Data Retention
|
|
|
|
```sql
|
|
-- Archive old audit logs (older than 1 year)
|
|
DELETE FROM audit_log WHERE changed_at < DATE_SUB(NOW(), INTERVAL 1 YEAR);
|
|
|
|
-- Archive old statistics
|
|
DELETE FROM data_statistics WHERE stat_date < DATE_SUB(CURDATE(), INTERVAL 1 YEAR);
|
|
```
|
|
|
|
### 4.3 Cleanup Script
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
# Remove backups older than 7 days
|
|
find /backup -name "webgis_backup_*.sql.gz" -mtime +7 -exec rm {} \;
|
|
|
|
# Remove backups older than 30 days from network drive
|
|
find /mnt/network_backup -name "webgis_backup_*.sql.gz" -mtime +30 -exec rm {} \;
|
|
|
|
# Archive monthly backups to external HDD (optional)
|
|
find /backup -name "webgis_backup_*.sql.gz" -mtime +30 -exec cp {} /mnt/external_hdd/archive/ \;
|
|
```
|
|
|
|
---
|
|
|
|
## 5. Recovery Time Objectives (RTO/RPO)
|
|
|
|
### 5.1 Service Level Agreements
|
|
|
|
| Scenario | RTO | RPO | Priority |
|
|
|----------|-----|-----|----------|
|
|
| Single record loss | 1 hour | 24 hours | Medium |
|
|
| Table corruption | 2 hours | 24 hours | High |
|
|
| Database corruption | 4 hours | 24 hours | Critical |
|
|
| Complete server failure | 4 hours | 24 hours | Critical |
|
|
| Ransomware attack | 8 hours | 24 hours | Critical |
|
|
|
|
### 5.2 Target Metrics
|
|
|
|
- **RTO** (Recovery Time Objective): Max 4 hours to restore full service
|
|
- **RPO** (Recovery Point Objective): Max 24 hours of data loss acceptable
|
|
|
|
---
|
|
|
|
## 6. Disaster Recovery Plan
|
|
|
|
### 6.1 Contact List
|
|
|
|
| Role | Name | Phone | Email |
|
|
|------|------|-------|-------|
|
|
| IT Manager | John Doe | +62-xxx-xxxx | john@example.com |
|
|
| DBA | Jane Smith | +62-xxx-xxxx | jane@example.com |
|
|
| System Admin | Bob Johnson | +62-xxx-xxxx | bob@example.com |
|
|
|
|
### 6.2 Escalation Procedure
|
|
|
|
**Level 1:** System Admin (30 min response)
|
|
**Level 2:** DBA (1 hour response)
|
|
**Level 3:** IT Manager (2 hour response)
|
|
|
|
### 6.3 Communication Plan
|
|
|
|
1. **Alert Detection** → Automated monitoring system
|
|
2. **Notification** → Alert team via email, SMS, Slack
|
|
3. **Incident Assessment** → Determine impact and scope
|
|
4. **Recovery Execution** → Execute appropriate recovery procedure
|
|
5. **Post-Recovery Testing** → Verify system integrity
|
|
6. **Communication Update** → Notify stakeholders of status
|
|
|
|
---
|
|
|
|
## 7. Backup Checklist
|
|
|
|
- [ ] Daily backup script runs successfully
|
|
- [ ] Weekly backup performed
|
|
- [ ] Monthly backup archived
|
|
- [ ] Backup files are compressed
|
|
- [ ] Backups are copied to network drive
|
|
- [ ] Backup verification test passes
|
|
- [ ] Audit logs are being recorded
|
|
- [ ] Retention policy enforced
|
|
- [ ] Off-site backups updated
|
|
- [ ] Team trained on recovery procedures
|
|
- [ ] Documentation is current
|
|
- [ ] Backup location is secure
|
|
- [ ] Power backup for backup storage
|
|
- [ ] Network connectivity stable
|
|
- [ ] External HDD checked monthly
|
|
|
|
---
|
|
|
|
## 8. Monitoring & Alerts
|
|
|
|
### 8.1 Backup Monitoring
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# Monitor backup completion and send alert
|
|
|
|
BACKUP_DIR="/backup"
|
|
YESTERDAY=$(date -d '1 day ago' +%Y%m%d)
|
|
BACKUP_FILE="$BACKUP_DIR/webgis_backup_${YESTERDAY}_*.sql.gz"
|
|
|
|
if [ -f $BACKUP_FILE ]; then
|
|
SIZE=$(du -h $BACKUP_FILE | cut -f1)
|
|
echo "Backup found: $BACKUP_FILE ($SIZE)" | mail -s "Backup Status: OK" admin@example.com
|
|
else
|
|
echo "ERROR: Backup file not found for $YESTERDAY" | mail -s "ALERT: Backup Failed" admin@example.com
|
|
fi
|
|
```
|
|
|
|
### 8.2 Health Checks
|
|
|
|
```bash
|
|
# Check database size
|
|
mysql -u root -p -e "
|
|
SELECT
|
|
table_schema as 'Database',
|
|
ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) as 'Size in MB'
|
|
FROM information_schema.tables
|
|
WHERE table_schema = 'webgis_unified'
|
|
GROUP BY table_schema;
|
|
"
|
|
|
|
# Check free disk space
|
|
df -h /backup
|
|
|
|
# Check backup file count
|
|
ls -1 /backup/webgis_backup_*.sql.gz | wc -l
|
|
```
|
|
|
|
---
|
|
|
|
## 9. Documentation
|
|
|
|
### 9.1 Backup Log
|
|
|
|
Keep record of all backups:
|
|
|
|
```
|
|
Date | Time | Size | Status | Notes
|
|
2026-05-20 | 02:00 | 125 MB | SUCCESS | Daily backup
|
|
2026-05-19 | 02:00 | 124 MB | SUCCESS | Daily backup
|
|
2026-05-18 | 02:00 | 123 MB | SUCCESS | Daily backup
|
|
2026-05-17 | 03:00 | 256 MB | SUCCESS | Weekly backup
|
|
```
|
|
|
|
### 9.2 Recovery Log
|
|
|
|
Record all recovery attempts:
|
|
|
|
```
|
|
Date | Time | Reason | Duration | Result | Notes
|
|
2026-05-15 | 10:30 | Test | 45 min | SUCCESS | Monthly test successful
|
|
2026-04-15 | 09:00 | Test | 40 min | SUCCESS | Monthly test successful
|
|
```
|
|
|
|
---
|
|
|
|
## 10. Revision History
|
|
|
|
| Version | Date | Author | Changes |
|
|
|---------|------|--------|---------|
|
|
| 1.0 | May 2026 | Admin | Initial backup plan |
|
|
|
|
---
|
|
|
|
## 11. Appendix
|
|
|
|
### A. Quick Reference
|
|
|
|
```bash
|
|
# Create backup
|
|
mysqldump -u root -p webgis_unified | gzip > backup_$(date +%Y%m%d).sql.gz
|
|
|
|
# Restore backup
|
|
gunzip -c backup_20260520.sql.gz | mysql -u root -p webgis_unified
|
|
|
|
# List backups
|
|
ls -lh /backup/webgis_backup_*.sql.gz
|
|
|
|
# Check latest backup
|
|
ls -t /backup/webgis_backup_*.sql.gz | head -1
|
|
|
|
# Test backup
|
|
gzip -t /backup/webgis_backup_20260520.sql.gz
|
|
|
|
# Backup size
|
|
du -h /backup/webgis_backup_20260520.sql.gz
|
|
```
|
|
|
|
### B. Resources
|
|
|
|
- MySQL Documentation: https://dev.mysql.com/doc/
|
|
- Backup Best Practices: https://dev.mysql.com/doc/refman/5.7/en/backup-and-recovery.html
|
|
- Linux Backup Tools: man tar, man mysqldump
|
|
|
|
---
|
|
|
|
**Document Status:** APPROVED
|
|
**Last Review:** May 20, 2026
|
|
**Next Review:** August 20, 2026
|
|
|
|
**For questions or updates, contact the IT Administrator.**
|