Aplikasi billing & manajemen ISP (fiber optic) — PWA pelanggan, portal teknisi & kolektor, admin panel lengkap, multi-vendor OLT, RADIUS, WhatsApp/Telegram, pembayaran QRIS. Kredit & lisensi (ISC): - Base kode & repo: alijayanet/billing-rtrw oleh Alijaya Net — terima kasih banyak atas base kode dan repo yang bermanfaat. - Add-on: GoWA, LibreSpeed/OpenSpeedTest, Uptime Kuma, notification-forwarder. - Dikembangkan menjadi OPEN-ISP oleh oxpoe — https://github.com/oxpoe/open-isp
453 lines
10 KiB
Markdown
453 lines
10 KiB
Markdown
# BACKUP & RESTORE CHECKLIST - Aplikasi Billing B481
|
|
|
|
## ✅ Pre-Audit Backup (CRITICAL)
|
|
|
|
Sebelum melakukan perubahan apapun pada aplikasi, lakukan backup lengkap:
|
|
|
|
### Step 1: Backup Database
|
|
```bash
|
|
cd /path/to/billing-rtrw
|
|
|
|
# Method 1: Using built-in backup
|
|
node -e "
|
|
const backupService = require('./services/backupService.js');
|
|
backupService.backupDatabase();
|
|
console.log('Backup selesai!');
|
|
"
|
|
|
|
# Method 2: Manual SQLite backup
|
|
sqlite3 database/billing.db ".backup 'database/backup-$(date +%Y-%m-%d).db'"
|
|
|
|
# Method 3: Copy file
|
|
cp database/billing.db database/backup-$(date +%Y-%m-%d-%H%M%S).db
|
|
```
|
|
|
|
### Step 2: Backup Settings
|
|
```bash
|
|
# Backup konfigurasi
|
|
cp settings.json settings.json.backup-$(date +%Y-%m-%d-%H%M%S)
|
|
cp .env .env.backup-$(date +%Y-%m-%d-%H%M%S) 2>/dev/null || true
|
|
```
|
|
|
|
### Step 3: Backup Aplikasi Source
|
|
```bash
|
|
# Tar entire application
|
|
cd /path/to
|
|
tar -czf billing-rtrw-backup-$(date +%Y-%m-%d-%H%M%S).tar.gz billing-rtrw/
|
|
|
|
# Or zip
|
|
zip -r billing-rtrw-backup-$(date +%Y-%m-%d-%H%M%S).zip billing-rtrw/
|
|
```
|
|
|
|
### Step 4: Backup Upload Files
|
|
```bash
|
|
# Backup QRIS images & payment proofs
|
|
tar -czf uploads-backup-$(date +%Y-%m-%d-%H%M%S).tar.gz public/uploads/
|
|
```
|
|
|
|
### Step 5: Verify Backups
|
|
```bash
|
|
# List backups
|
|
ls -lh database/backup-*.db
|
|
ls -lh *.tar.gz
|
|
ls -lh settings.json.backup-*
|
|
|
|
# Check backup integrity
|
|
sqlite3 database/backup-*.db "SELECT COUNT(*) FROM customers;"
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 Backup Checklist
|
|
|
|
**Date:** _______________
|
|
|
|
- [ ] Database backup dibuat
|
|
- Path: _______________
|
|
- Size: _______________
|
|
- Integrity: ✓ verified
|
|
|
|
- [ ] Settings backup dibuat
|
|
- `settings.json` ✓
|
|
- `.env` ✓
|
|
|
|
- [ ] Aplikasi source backup dibuat
|
|
- Format: _____ (tar.gz / zip)
|
|
- Size: _______________
|
|
- Location: _______________
|
|
|
|
- [ ] Upload files backup dibuat
|
|
- Location: _______________
|
|
- Size: _______________
|
|
|
|
- [ ] Backups disimpan di lokasi aman
|
|
- Local: _______________
|
|
- USB Drive: ✓ / ✗
|
|
- Cloud: _______________
|
|
- Network Drive: _______________
|
|
|
|
- [ ] Backup list di-dokumentasikan
|
|
- File: BACKUP_INVENTORY.md
|
|
|
|
- [ ] Restore test dilakukan
|
|
- Database restored: ✓ / ✗
|
|
- Settings verified: ✓ / ✗
|
|
|
|
---
|
|
|
|
## 🔄 Restore Procedures
|
|
|
|
### Restore Database Only
|
|
```bash
|
|
# Stop aplikasi
|
|
pm2 stop all
|
|
# atau
|
|
pkill -f "node app-customer.js"
|
|
|
|
# Restore dari backup
|
|
sqlite3 database/billing.db ".restore 'database/backup-2026-06-19.db'"
|
|
|
|
# Verify
|
|
sqlite3 database/billing.db "SELECT COUNT(*) FROM invoices;"
|
|
|
|
# Start aplikasi
|
|
npm start
|
|
# atau
|
|
pm2 start app-customer.js --name billing
|
|
```
|
|
|
|
### Restore Settings
|
|
```bash
|
|
# Restore settings.json
|
|
cp settings.json.backup-2026-06-19 settings.json
|
|
|
|
# Restore .env
|
|
cp .env.backup-2026-06-19 .env
|
|
|
|
# Restart aplikasi untuk apply settings
|
|
pm2 restart all
|
|
```
|
|
|
|
### Full Application Restore
|
|
```bash
|
|
# Backup current application
|
|
mv billing-rtrw billing-rtrw-broken-$(date +%s)
|
|
|
|
# Extract backup
|
|
tar -xzf billing-rtrw-backup-2026-06-19-120000.tar.gz
|
|
|
|
# Atau restore individual files
|
|
cd billing-rtrw
|
|
sqlite3 database/billing.db ".restore '../backup-2026-06-19.db'"
|
|
|
|
# Restart
|
|
npm start
|
|
```
|
|
|
|
### Restore Upload Files
|
|
```bash
|
|
# Extract backup
|
|
cd public
|
|
tar -xzf ../uploads-backup-2026-06-19.tar.gz
|
|
|
|
# Verify
|
|
ls -la uploads/qris/
|
|
ls -la uploads/payment_proofs/
|
|
```
|
|
|
|
---
|
|
|
|
## 🗂️ Backup Inventory
|
|
|
|
Buat file `BACKUP_INVENTORY.md` untuk tracking:
|
|
|
|
```markdown
|
|
# Backup Inventory - Aplikasi Billing B481
|
|
|
|
## Backup Schedule
|
|
- **Frequency:** Daily / Weekly / Manual
|
|
- **Retention:** 30 days
|
|
- **Storage Location:** /backup, /mnt/backup, S3, etc
|
|
|
|
## Backup History
|
|
|
|
| Date | Type | Filename | Size | Location | Status |
|
|
|------|------|----------|------|----------|--------|
|
|
| 2026-06-19 | Full | billing-rtrw-backup-2026-06-19.tar.gz | 150 MB | /backup | ✓ Verified |
|
|
| 2026-06-19 | DB | database/backup-2026-06-19.db | 5 MB | /backup/db | ✓ Verified |
|
|
| 2026-06-18 | Full | billing-rtrw-backup-2026-06-18.tar.gz | 150 MB | /backup | ✓ Verified |
|
|
|
|
## Last Restore Test
|
|
- **Date:** 2026-06-19 14:30
|
|
- **Result:** ✓ Successful
|
|
- **Database Records:** 12,345 customers
|
|
- **Notes:** All tables verified, data integrity OK
|
|
```
|
|
|
|
---
|
|
|
|
## 🔐 Secure Backup Storage
|
|
|
|
### Option 1: Local Storage (USB Drive)
|
|
```bash
|
|
# Weekly backup to USB
|
|
cp database/backup-*.db /mnt/usb/backups/
|
|
cp settings.json.backup-* /mnt/usb/backups/
|
|
```
|
|
|
|
### Option 2: Network Drive (NAS/SMB)
|
|
```bash
|
|
# Mount network share
|
|
sudo mount -t cifs //192.168.1.100/backups /mnt/network -o user=admin
|
|
|
|
# Copy backup
|
|
cp database/backup-*.db /mnt/network/
|
|
```
|
|
|
|
### Option 3: Cloud Storage
|
|
```bash
|
|
# Using rclone to sync to cloud (Google Drive, OneDrive, S3)
|
|
rclone sync database/backup-*.db gdrive:/billing-backups/
|
|
|
|
# Or AWS S3
|
|
aws s3 cp database/backup-*.db s3://my-billing-backups/
|
|
```
|
|
|
|
### Option 4: Encrypted Backup
|
|
```bash
|
|
# Create encrypted backup
|
|
gpg --symmetric --cipher-algo AES256 database/backup-2026-06-19.db
|
|
|
|
# Restore encrypted backup
|
|
gpg -d database/backup-2026-06-19.db.gpg > database/backup-2026-06-19.db
|
|
```
|
|
|
|
---
|
|
|
|
## ⚙️ Automated Backup (Cron Job)
|
|
|
|
### Setup Daily Backup (Linux/Mac)
|
|
```bash
|
|
# Edit crontab
|
|
crontab -e
|
|
|
|
# Add this line (backup setiap hari jam 2 pagi)
|
|
0 2 * * * cd /path/to/billing-rtrw && ./scripts/backup-daily.sh
|
|
|
|
# Add this line (cleanup backups older than 30 days)
|
|
0 3 * * 0 find /path/to/billing-rtrw/database/backup-* -mtime +30 -delete
|
|
```
|
|
|
|
### Create Backup Script (`scripts/backup-daily.sh`)
|
|
```bash
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
BACKUP_DIR="/path/to/billing-rtrw/database"
|
|
DATE=$(date +%Y-%m-%d-%H%M%S)
|
|
|
|
echo "[$(date)] Starting backup..."
|
|
|
|
# Database backup
|
|
sqlite3 "$BACKUP_DIR/billing.db" ".backup '$BACKUP_DIR/backup-$DATE.db'"
|
|
|
|
# Settings backup
|
|
cp /path/to/billing-rtrw/settings.json /path/to/billing-rtrw/settings.json.backup-$DATE
|
|
|
|
# Cleanup old backups (older than 30 days)
|
|
find "$BACKUP_DIR/backup-*.db" -mtime +30 -delete
|
|
|
|
# Optional: Upload to cloud
|
|
# aws s3 cp "$BACKUP_DIR/backup-$DATE.db" s3://my-bucket/backups/
|
|
|
|
echo "[$(date)] Backup completed: backup-$DATE.db"
|
|
```
|
|
|
|
### Make Script Executable
|
|
```bash
|
|
chmod +x scripts/backup-daily.sh
|
|
|
|
# Test
|
|
./scripts/backup-daily.sh
|
|
```
|
|
|
|
---
|
|
|
|
## 🚨 Disaster Recovery Plan
|
|
|
|
### Scenario 1: Database Corrupted
|
|
```bash
|
|
# Stop aplikasi
|
|
pm2 stop billing-rtrw
|
|
|
|
# Restore dari backup terakhir
|
|
sqlite3 database/billing.db ".restore 'database/backup-latest.db'"
|
|
|
|
# Restart
|
|
pm2 start app-customer.js --name billing-rtrw
|
|
|
|
# Monitor logs
|
|
pm2 logs billing-rtrw
|
|
```
|
|
|
|
### Scenario 2: Aplikasi Crashed
|
|
```bash
|
|
# Check error
|
|
pm2 logs billing-rtrw --tail 100
|
|
|
|
# Restart
|
|
pm2 restart billing-rtrw
|
|
|
|
# If still crashing, restore backup
|
|
# ... follow procedure above
|
|
```
|
|
|
|
### Scenario 3: Akses Denied / Permission Error
|
|
```bash
|
|
# Check file ownership
|
|
ls -la database/
|
|
ls -la settings.json
|
|
|
|
# Fix permissions
|
|
sudo chown -R $USER:$USER /path/to/billing-rtrw
|
|
chmod -R u+w database/
|
|
chmod 600 settings.json .env
|
|
```
|
|
|
|
### Scenario 4: HDD Full / Disk Space Error
|
|
```bash
|
|
# Check disk usage
|
|
df -h
|
|
du -sh *
|
|
|
|
# Cleanup old backups
|
|
find database/backup-*.db -mtime +30 -delete
|
|
|
|
# Cleanup old uploads if needed
|
|
find public/uploads/ -mtime +90 -delete
|
|
|
|
# Vacuum database
|
|
sqlite3 database/billing.db "VACUUM;"
|
|
```
|
|
|
|
### Scenario 5: Settings Misconfiguration
|
|
```bash
|
|
# Restore settings dari backup
|
|
cp settings.json settings.json.broken
|
|
cp settings.json.backup-last-good settings.json
|
|
|
|
# Restart aplikasi
|
|
pm2 restart billing-rtrw
|
|
|
|
# Verify settings applied
|
|
curl http://localhost:3001/health
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Backup Size Monitoring
|
|
|
|
### Check Database Size
|
|
```bash
|
|
# SQLite database
|
|
ls -lh database/billing.db
|
|
sqlite3 database/billing.db "SELECT page_count * page_size / 1024 / 1024 AS size_mb FROM pragma_page_count(), pragma_page_size();"
|
|
|
|
# Backup directory
|
|
du -sh database/backup-*
|
|
du -sh public/uploads/
|
|
```
|
|
|
|
### Estimated Growth
|
|
- **Customers:** ~1 KB per record
|
|
- **Invoices:** ~0.5 KB per record
|
|
- **Payments:** ~0.3 KB per record
|
|
- **Traffic Samples:** ~0.1 KB per record (auto-cleaned)
|
|
|
|
**Example:**
|
|
- 10,000 customers = ~10 MB
|
|
- 120,000 invoices/year = ~60 MB
|
|
- 1,000+ agents = ~1 MB
|
|
- **Total:** ~80-150 MB (reasonable)
|
|
|
|
---
|
|
|
|
## ✨ Best Practices
|
|
|
|
### DO ✅
|
|
- ✓ Backup sebelum production deployment
|
|
- ✓ Test restore secara berkala (minimal monthly)
|
|
- ✓ Store backups di multiple locations
|
|
- ✓ Encrypt sensitive backups
|
|
- ✓ Document backup procedures
|
|
- ✓ Use versioning (date-based naming)
|
|
- ✓ Monitor backup integrity
|
|
- ✓ Keep detailed backup inventory
|
|
|
|
### DON'T ❌
|
|
- ✗ Delete backups tanpa verification
|
|
- ✗ Store backups hanya di local storage
|
|
- ✗ Skip restore testing
|
|
- ✗ Use generic filename (backup.db)
|
|
- ✗ Keep unencrypted backups exposed
|
|
- ✗ Ignore disk space warnings
|
|
- ✗ Backup ke lokasi yang sama dengan data
|
|
- ✗ Forget to document backup location
|
|
|
|
---
|
|
|
|
## 📞 Recovery Time Objective (RTO)
|
|
|
|
| Scenario | RTO | RPO |
|
|
|----------|-----|-----|
|
|
| Database recovery | 5-15 min | 24 hours (daily backup) |
|
|
| Full application restore | 30-60 min | 24 hours |
|
|
| Settings recovery | 1-5 min | Real-time (git backup) |
|
|
| Upload files recovery | 10-30 min | 7 days (weekly backup) |
|
|
|
|
**RTO:** Recovery Time Objective (berapa lama untuk recover)
|
|
**RPO:** Recovery Point Objective (berapa lama data boleh hilang)
|
|
|
|
---
|
|
|
|
## 📝 Backup Verification Checklist
|
|
|
|
Setelah membuat backup, verifikasi dengan:
|
|
|
|
```bash
|
|
# Test 1: File exists & readable
|
|
[ -f database/backup-2026-06-19.db ] && echo "✓ File exists"
|
|
file database/backup-2026-06-19.db
|
|
|
|
# Test 2: SQLite integrity check
|
|
sqlite3 database/backup-2026-06-19.db "PRAGMA integrity_check;"
|
|
|
|
# Test 3: Row counts
|
|
sqlite3 database/backup-2026-06-19.db "SELECT COUNT(*) as customer_count FROM customers;"
|
|
sqlite3 database/backup-2026-06-19.db "SELECT COUNT(*) as invoice_count FROM invoices;"
|
|
|
|
# Test 4: Recent data present
|
|
sqlite3 database/backup-2026-06-19.db "SELECT MAX(created_at) FROM customers;"
|
|
|
|
# Test 5: Restore test (optional, on staging)
|
|
cp database/backup-2026-06-19.db /tmp/test-restore.db
|
|
sqlite3 /tmp/test-restore.db ".tables"
|
|
```
|
|
|
|
---
|
|
|
|
## 🔗 Related Documentation
|
|
|
|
- [AUDIT_LENGKAP.md](AUDIT_LENGKAP.md) - Full audit report
|
|
- [DATABASE_SCHEMA.md](DATABASE_SCHEMA.md) - Database structure
|
|
- [QUICK_REFERENCE.md](QUICK_REFERENCE.md) - Quick commands
|
|
|
|
---
|
|
|
|
**Document Version:** 1.0
|
|
**Last Updated:** Juni 2026
|
|
**Status:** ✓ Ready for Production
|
|
|
|
**⚠️ REMEMBER:** Backups are only useful if you can restore them. Test regularly!
|
|
|