A backup that has never been tested is a backup you’re not sure works. This article is both the restore procedure and the test.
Run through it on a test server before you need it for real.
Scenario A — Restoring to the Same Server
Use this when recovering from a database issue, corruption, or accidental content deletion while the server and files are still intact.
Step 1 — Download the backup from cloud storage
# From R2
rclone copy r2:wp-backups/db/wordpress_site_2026-06-08_02-00-00.sql.gz \
/tmp/restore/
# From Google Drive
rclone copy gdrive:wp-backups/db/wordpress_site_2026-06-08_02-00-00.sql.gz \
/tmp/restore/
Step 2 — Drop and recreate the database
mysql -u root -p
DROP DATABASE wordpress_site;
CREATE DATABASE wordpress_site CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL PRIVILEGES ON wordpress_site.* TO 'wp_user'@'localhost';
FLUSH PRIVILEGES;
exit;
Step 3 — Import the backup
gunzip -c /tmp/restore/wordpress_site_2026-06-08_02-00-00.sql.gz | \
mysql -u root -p wordpress_site
Step 4 — Verify
mysql -u root -p -e "SELECT COUNT(*) FROM wordpress_site.wp_posts;"
Should return a number matching your post count.
Scenario B — Restoring to a New Server
Use this after a complete server loss — accidental deletion, provider failure, migration. The stack from Parts 3–5 must be set up first.
Prerequisites:
- New VPS provisioned and configured (Parts 2–3)
- LEMP stack installed (Part 4)
- Web root created with correct permissions
- wp-config.php configured with new database credentials
- DNS updated to point to new server IP
Step 1 — Restore WordPress files from cloud storage
# Restore wp-content/uploads
rclone sync r2:wp-backups/uploads/yourdomain.com/ \
/var/www/yourdomain.com/wp-content/uploads/
# Download fresh WordPress core
cd /var/www/yourdomain.com
sudo wget https://wordpress.org/latest.tar.gz
sudo tar -xzf latest.tar.gz
sudo mv wordpress/* .
sudo rm -rf wordpress/ latest.tar.gz
Step 2 — Restore the database
# Download latest database backup
rclone copy r2:wp-backups/db/ /tmp/restore/ \
--include "wordpress_site_*.sql.gz" \
--max-age 24h
# Find the most recent file
LATEST=$(ls -t /tmp/restore/*.sql.gz | head -1)
# Import
gunzip -c "$LATEST" | mysql -u root -p wordpress_site
Step 3 — Update wp-config.php if credentials changed
If the new server uses different database credentials, update wp-config.php:
sudo nano /var/www/yourdomain.com/wp-config.php
# Update DB_USER and DB_PASSWORD to match the new database user
Step 4 — Fix permissions
sudo chown -R nginx:nginx /var/www/yourdomain.com/
sudo find /var/www/yourdomain.com/ -type f -exec chmod 644 {} \;
sudo find /var/www/yourdomain.com/ -type d -exec chmod 755 {} \;
Step 5 — Install plugins
Core WordPress files and the database are restored. Plugins in the database reference plugin files that need to be reinstalled:
Log into wp-admin → Plugins → any showing as missing will need reinstallation.
Alternatively, if you backed up wp-content/plugins/ separately, restore from there.
Verify the Restore
# Check Nginx serves the site
curl -I https://yourdomain.com
# Should return 200
# Check WordPress is responding
curl -s https://yourdomain.com | grep "<title>"
# Should show your site title
# Check database post count
mysql -u wp_user -p wordpress_site -e "SELECT COUNT(*) FROM wp_posts WHERE post_status='publish';"
The Time Difference
Without database backups (what happened with rm -rf /):
- Provision server: 5 minutes
- Install stack: 2 hours
- Download files: 30 minutes
- Rebuild databases from memory/partial exports: 4–6 hours
- Total: most of a day
With daily mysqldump backups:
- Provision server: 5 minutes
- Install stack: 2 hours
- Restore database: 10 minutes
- Restore files: 30 minutes
- Total: under 3 hours
With a Vultr snapshot from the previous week:
- Restore snapshot: 10 minutes
- Replay any database changes since snapshot: varies
- Total: 30 minutes to 1 hour
The combination — daily database backups plus weekly Vultr snapshots — covers all realistic failure scenarios. Part 7 is done.