# World Backup Automation - Deployment Plan **Status:** Planning Complete, Ready to Implement **Priority:** Tier 3 - Disaster Recovery **Time Estimate:** 1-2 hours implementation **Last Updated:** 2026-02-17 --- ## Overview Automated backup system for all 11 Minecraft server worlds. Scheduled daily backups with intelligent retention policy (7 daily, 4 weekly, 3 monthly) and off-server storage for disaster recovery. **The Problem:** - No automated backups = risk of data loss - Manual backups = inconsistent, time-consuming - No off-server storage = vulnerable to hardware failure - No retention policy = storage bloat or premature deletion **The Solution:** - Automated Python script with Pterodactyl SFTP integration - Daily backups at off-peak hours (integrate with restart system) - Smart retention: 7 daily, 4 weekly, 12 monthly backups - Off-server storage (NextCloud or S3-compatible) - Compression (tar.gz) to save space - Restoration procedures documented - Discord notifications --- ## Architecture ``` Backup Schedule (Daily 3:30 AM) ↓ Python Backup Script ↓ Pterodactyl SFTP → Download world files ↓ Compress (tar.gz) ↓ Upload to NextCloud/S3 ↓ Apply Retention Policy (delete old backups) ↓ Discord Notification (success/failure) ``` **Timing Integration with Restarts:** - **3:30 AM** - Backups start (before restart cycle) - **4:00 AM** - Staggered restarts start (after backups complete) This ensures fresh backups before any server restarts. --- ## Features ### Core Features **✅ Automated Daily Backups** - Runs automatically via cron - All 11 servers backed up - World files only (not plugins/configs - those are in git) - Compressed to save space (~80% reduction) **✅ Intelligent Retention Policy** - **Daily:** Keep last 7 days - **Weekly:** Keep last 4 weeks (Sunday backups) - **Monthly:** Keep last 12 months (1st of month backups) - Automatic cleanup of old backups - Prevents storage bloat **✅ Off-Server Storage** - Stored on NextCloud (downloads.firefrostgaming.com) - Alternative: S3-compatible storage (Backblaze B2, Wasabi, etc.) - Protects against node hardware failure - Accessible from anywhere **✅ Discord Notifications** - Backup started notification - Per-server completion - Final summary (success/failed/size) - Error alerts **✅ Restoration Procedures** - Documented step-by-step restoration - Test restoration regularly - Recovery time objective: < 1 hour --- ## Server World Paths **TX1 Dallas servers:** - Reclamation: `/var/lib/pterodactyl/volumes/{uuid}/world/` - Stoneblock 4: `/var/lib/pterodactyl/volumes/{uuid}/world/` - Society Sunlit Valley: `/var/lib/pterodactyl/volumes/{uuid}/world/` - Vanilla 1.21.11: `/var/lib/pterodactyl/volumes/{uuid}/world/` - All The Mons: `/var/lib/pterodactyl/volumes/{uuid}/world/` **NC1 Charlotte servers:** - The Ember Project: `/var/lib/pterodactyl/volumes/{uuid}/world/` - Minecolonies Create & Conquer: `/var/lib/pterodactyl/volumes/{uuid}/world/` - All The Mods 10: `/var/lib/pterodactyl/volumes/{uuid}/world/` - Homestead: `/var/lib/pterodactyl/volumes/{uuid}/world/` - EMC Subterra Tech: `/var/lib/pterodactyl/volumes/{uuid}/world/` **Note:** Some modpacks use different world folder names (e.g., `dimensions/` for custom dimensions) --- ## Storage Requirements ### Per-Server Estimates **Compressed backup sizes (approximate):** - Vanilla: ~50 MB - Modded (light): ~200 MB - Modded (heavy): ~500 MB - ATM10: ~1 GB (largest) **Total daily backup:** ~4-5 GB (all 11 servers compressed) ### Retention Storage **Daily (7 days):** 7 × 5 GB = 35 GB **Weekly (4 weeks):** 4 × 5 GB = 20 GB **Monthly (12 months):** 12 × 5 GB = 60 GB **Total storage needed:** ~115 GB (with compression) **Recommended:** 200 GB storage allocation (room to grow) --- ## Implementation ### Script Location **File:** `/opt/automation/world-backup.py` **Config:** `/opt/automation/backup-config.json` **Logs:** `/var/log/world-backup.log` **Local staging:** `/opt/automation/backup-staging/` **Remote storage:** `downloads.firefrostgaming.com:/backups/worlds/` ### Configuration File (backup-config.json) ```json { "pterodactyl": { "url": "https://panel.firefrostgaming.com", "api_key": "PTERODACTYL_API_KEY_HERE", "sftp_host": "us.tx1.firefrostgaming.com", "sftp_port": 2022 }, "nextcloud": { "webdav_url": "https://downloads.firefrostgaming.com/remote.php/dav/files/admin/", "username": "admin", "password": "NEXTCLOUD_PASSWORD_HERE", "backup_path": "backups/worlds/" }, "discord": { "webhook_url": "DISCORD_WEBHOOK_URL_HERE", "notifications_enabled": true }, "backup_settings": { "staging_dir": "/opt/automation/backup-staging", "compression": "gzip", "compression_level": 6, "retention": { "daily": 7, "weekly": 4, "monthly": 12 } }, "servers": [ { "name": "Vanilla 1.21.11", "uuid": "3bed1bda-f648-4630-801a-fe9f2e3d3f27", "world_path": "world", "node": "TX1" }, { "name": "All The Mons", "uuid": "668a5220-7e72-4379-9165-bdbb84bc9806", "world_path": "world", "node": "TX1" }, { "name": "Stoneblock 4", "uuid": "a0efbfe8-4b97-4a90-869d-ffe6d3072bd5", "world_path": "world", "node": "TX1" }, { "name": "Society: Sunlit Valley", "uuid": "9310d0a6-62a6-4fe6-82c4-eb483dc68876", "world_path": "world", "node": "TX1" }, { "name": "Reclamation", "uuid": "1eb33479-a6bc-4e8f-b64d-d1e4bfa0a8b4", "world_path": "world", "node": "TX1" }, { "name": "The Ember Project", "uuid": "124f9060-58a7-457a-b2cf-b4024fce2951", "world_path": "world", "node": "NC1" }, { "name": "Minecolonies: Create and Conquer", "uuid": "a14201d2-83b2-44e6-ae48-e6c4cbc56f24", "world_path": "world", "node": "NC1" }, { "name": "All The Mods 10", "uuid": "82e63949-8fbf-4a44-b32a-53324e8492bf", "world_path": "world", "node": "NC1" }, { "name": "Homestead", "uuid": "2f85d4ef-aa49-4dd6-b448-beb3fca1db12", "world_path": "world", "node": "NC1" }, { "name": "EMC Subterra Tech", "uuid": "09a95f38-9f8c-404a-9557-3a7c44258223", "world_path": "world", "node": "NC1" } ] } ``` ### Main Script Overview **See `deployments/world-backup/world-backup.py` for complete script** **Key functions:** - `download_world_via_sftp(server)` - Download world files from Pterodactyl - `compress_backup(server)` - Create tar.gz archive - `upload_to_nextcloud(backup_file)` - Upload to remote storage - `apply_retention_policy()` - Delete old backups per policy - `discord_notify(message)` - Send notifications - `main()` - Orchestrate backup process --- ## Deployment Steps ### Phase 1: Prerequisites (15 min) - [ ] NextCloud admin access (or S3 credentials) - [ ] Pterodactyl API key with SFTP access - [ ] Discord webhook for #server-status - [ ] Command Center SSH access - [ ] 200 GB storage available on NextCloud/S3 ### Phase 2: Setup Storage (15 min) **Option A: NextCloud (Recommended)** ```bash # Create backup directory in NextCloud # Via web interface: Create folder "backups/worlds/" # Or via WebDAV: curl -X MKCOL -u admin:PASSWORD \ https://downloads.firefrostgaming.com/remote.php/dav/files/admin/backups/ curl -X MKCOL -u admin:PASSWORD \ https://downloads.firefrostgaming.com/remote.php/dav/files/admin/backups/worlds/ ``` **Option B: S3-Compatible (Alternative)** - Configure AWS S3, Backblaze B2, or Wasabi bucket - Create bucket: `firefrost-world-backups` - Generate access key/secret - Update script to use boto3/s3cmd instead of WebDAV ### Phase 3: Install Script (20 min) ```bash # On Command Center mkdir -p /opt/automation/backup-staging cd /opt/automation # Create config nano backup-config.json # Paste config, update credentials # Create script nano world-backup.py # Paste script # Make executable chmod +x world-backup.py # Install dependencies pip3 install requests paramiko --break-system-packages # Create log file touch /var/log/world-backup.log chmod 644 /var/log/world-backup.log ``` ### Phase 4: Test Backup (30 min) ```bash # Test with ONE server first (Vanilla) # Edit config to include only Vanilla server temporarily # Run manually python3 /opt/automation/world-backup.py # Verify: # - World downloaded from Pterodactyl # - Compressed successfully # - Uploaded to NextCloud # - Discord notification received # - Backup appears in NextCloud # Check backup file # Download and extract to verify integrity ``` ### Phase 5: Schedule with Cron (10 min) ```bash # Edit crontab crontab -e # Add daily backup at 3:30 AM (before restart cycle) 30 3 * * * /usr/bin/python3 /opt/automation/world-backup.py >> /var/log/world-backup.log 2>&1 ``` **Why 3:30 AM?** - Low player activity - Before 4:00 AM restart cycle - Ensures fresh backup before restarts - Backups complete before restarts begin ### Phase 6: Test Restoration (20 min) **CRITICAL: Test restoration on a TEST server BEFORE you need it!** ```bash # Download backup from NextCloud # Extract tar.gz # Stop test server # Replace world folder # Start server # Verify world loads correctly ``` --- ## Retention Policy Logic **How it works:** 1. **Daily backups:** Every backup is initially a "daily" backup 2. **Weekly promotion:** Sunday backups are kept as "weekly" (in addition to daily) 3. **Monthly promotion:** 1st of month backups are kept as "monthly" (in addition to weekly) **Example retention:** ``` Daily (7 days): - Feb 17 (today) - Feb 16 - Feb 15 - Feb 14 - Feb 13 - Feb 12 - Feb 11 Weekly (4 weeks) - Sundays only: - Feb 10 (Sunday) - Feb 3 (Sunday) - Jan 27 (Sunday) - Jan 20 (Sunday) Monthly (12 months) - 1st of month: - Feb 1 - Jan 1 - Dec 1, 2025 - Nov 1, 2025 ... (back 12 months) ``` **Old backups deleted:** - Daily backups older than 7 days (unless promoted to weekly/monthly) - Weekly backups older than 4 weeks (unless promoted to monthly) - Monthly backups older than 12 months --- ## Restoration Procedures ### Standard Restoration (World Corruption) **Scenario:** Server world corrupted, need to restore from backup **Steps:** 1. **Stop the affected server** (via Pterodactyl panel) 2. **Download latest backup from NextCloud** ```bash # Find latest backup ls backups/worlds/[server-name]/ # Download wget https://downloads.firefrostgaming.com/backups/worlds/[server-name]/[backup-file].tar.gz ``` 3. **Connect to server via SFTP** ```bash sftp -P 2022 admin@us.tx1.firefrostgaming.com # (or NC1 host for NC1 servers) ``` 4. **Backup current world (just in case)** ```bash cd /var/lib/pterodactyl/volumes/[uuid]/ mv world world-corrupted-backup-$(date +%Y%m%d) ``` 5. **Extract backup** ```bash tar -xzf [backup-file].tar.gz ``` 6. **Verify world folder exists and has proper permissions** 7. **Start server** (via Pterodactyl panel) 8. **Test in-game** - Join and verify world loaded correctly 9. **Monitor logs** for any errors **Estimated recovery time:** 15-30 minutes ### Disaster Recovery (Node Failure) **Scenario:** Entire TX1 or NC1 node failed, need to restore all servers **Steps:** 1. **Provision new node** (or repair existing) 2. **Reinstall Pterodactyl Wings** 3. **Download ALL backups for that node** 4. **Restore each server world** (use parallel restoration if possible) 5. **Update DNS/IP mappings** if IPs changed 6. **Test each server** **Estimated recovery time:** 2-4 hours (depends on number of servers and backup size) --- ## Discord Notifications ### Notification Examples **Backup Started:** ``` 💾 **World Backup Started** Servers: 11 Estimated duration: ~30 minutes ``` **Per-Server:** ``` ✅ **Vanilla 1.21.11** backed up Size: 47 MB compressed Duration: 2m 15s ``` **Completion:** ``` ✅ **Backup Cycle Complete** Successful: 11/11 Failed: 0 Total size: 4.2 GB compressed Duration: 28 minutes Next backup: Tomorrow 3:30 AM ``` **Error:** ``` ❌ **Backup Failed: ATM10** Reason: SFTP connection timeout Attempt: 3/3 Action: Manual backup required ``` --- ## Monitoring & Maintenance ### Daily - Check Discord for backup completion notification - Verify no failed backups ### Weekly - Review backup logs for errors - Check NextCloud storage usage - Verify retention policy working ### Monthly - Test restoration on one random server - Review backup sizes (growing unexpectedly?) - Verify off-server storage accessible - Check that monthly backups are being promoted correctly ### Quarterly - Full disaster recovery drill (restore all servers to test environment) - Review and update restoration procedures - Verify backup script still compatible with Pterodactyl updates --- ## Troubleshooting ### SFTP connection fails **Check:** - Pterodactyl SFTP service running on node - Firewall allows port 2022 - API key has SFTP permissions - Correct hostname (us.tx1 vs us.nc1) ### Backup file corrupt **Verify:** - Download completed successfully (check file size) - Compression succeeded (try manual tar -xzf test) - Upload to NextCloud succeeded - NextCloud not corrupting on upload ### Retention policy not deleting old backups **Debug:** - Check backup filenames follow expected format - Verify date parsing logic in script - Check NextCloud permissions (can delete?) - Review logs for deletion attempts ### NextCloud storage full **Actions:** - Check retention policy running - Manually delete very old backups if needed - Consider upgrading NextCloud storage - Enable NextCloud auto-delete for old files --- ## Advanced Features (Phase 2) **Incremental backups:** - Only backup changed files - Significant storage savings - Faster backup times - More complex restoration **Encrypted backups:** - Encrypt before upload - GPG or age encryption - Protects against NextCloud compromise - Key management required **Multi-region storage:** - Upload to multiple locations - S3 + NextCloud redundancy - Geographic disaster protection - Higher costs **Real-time backups:** - Continuous backup on world save - Near-zero data loss - Much higher storage usage - More complex implementation --- ## Related Tasks - **Staggered Server Restart System** - Runs after backups complete - **Netdata Deployment** - Monitor backup job duration - **NextCloud Setup** - Storage backend - **Discord Reorganization** - #server-status for notifications --- **Fire + Frost + Foundation = Where Love Builds Legacy** 💙🔥❄️ --- **Document Status:** COMPLETE **Ready for Implementation:** When SSH access available (1-2 hours) **Dependencies:** NextCloud or S3, Pterodactyl API, Command Center access **Storage Needed:** 200 GB recommended