
Most hosting outages aren’t caused by a “hack.” In 2026, the failures that cost time and money are usually mundane. Think bad updates, full disks, deleted directories, provider incidents, or a database that won’t start after a reboot.
This VPS disaster recovery tutorial shows how to build a recovery plan you can test and trust. You’ll use snapshots for fast rollback, encrypted offsite backups for durability, and a DNS cutover plan that won’t quietly break email.
This guide assumes you run websites or client hosting on Ubuntu/Debian/AlmaLinux/Rocky Linux. It also assumes Nginx/Apache, with optional cPanel/DirectAdmin.
By the end, you’ll have a practical runbook, copy/paste-ready commands, and a restore drill you can run every quarter.
What “disaster recovery” means on a hosting VPS (RPO, RTO, and blast radius)
Before you touch any tooling, define two numbers:
- RPO (Recovery Point Objective): how much data you can lose (example: 15 minutes of orders).
- RTO (Recovery Time Objective): how long you can be down (example: 30 minutes to serve a static maintenance page, 2 hours to full service).
Then define your blast radius. Is it a single WordPress site, a reseller node with 100 accounts, or a combined web + email box?
The more roles you stack on one VPS, the more DR becomes a DNS/TLS/mail deliverability exercise.
At that point, DR is no longer just “restore the files.”
Practical target for many small-business hosting VPS setups (2026): RPO 1 hour, RTO 2–4 hours. If you need RPO < 15 minutes, you’re in “continuous replication” territory. Split services and budget accordingly.
VPS disaster recovery tutorial: the reference architecture you’ll implement
You’ll set up three layers. Each layer protects you from a different failure.
- Local snapshots (fast rollback): recover from a bad update or config change in minutes.
- Encrypted offsite backups (real durability): recover from disk loss, ransomware, or “snapshot is corrupted.”
- DNS cutover plan (availability): move traffic to a standby VPS without waiting for long TTLs.
If you don’t already have a suitable server, start with a clean VPS sized for your workload.
For production hosting, restore speed matters. Leave headroom for imports, decompression, and cache rebuilds.
A HostMyCode VPS is a solid baseline for DIY admins. If you want help building and testing the runbook, managed VPS hosting reduces the “surprises during the first restore” problem.
Step 1: Inventory what must be recovered (and what can be rebuilt)
Create a one-page inventory. Store it somewhere you can reach during an outage, like a password manager or private repo.
- System: OS version, kernel, disk layout, mount points, firewall (UFW/nftables), SSH port.
- Web: Nginx/Apache configs, vhost list, document roots.
- App: WordPress files, wp-config.php, any environment variables, cron jobs.
- Data: database location, size, and how to dump/restore it.
- Secrets: TLS private keys, API keys, SMTP creds, control panel licenses.
- DNS: current DNS provider, zone file export, TTL values.
- Email (if hosted): mailboxes location, SPF/DKIM/DMARC, PTR/rDNS notes.
A classic failure is backing up /var/www but forgetting /etc. That’s where vhosts, TLS paths, cron, and service config live.
The reverse also happens. You capture configs, but you miss uploads.
Inventory first. Then decide what you’ll back up, and why.
Step 2: Implement snapshot rollbacks for fast “oops” recovery
Snapshots are for quick rollback after a failed update or accidental deletion. They do not replace DR.
A provider-level incident can take snapshots down with the VM.
Snapshot checklist (provider-agnostic)
- Take a snapshot before major changes (PHP upgrades, control panel updates, firewall changes).
- Automate daily snapshots with short retention (example: 7 days).
- Label snapshots with reason and ticket number (example:
pre-php82-upgrade-2026-08-27). - Document the restore procedure and downtime expectations.
Pre-snapshot safety steps
For database-backed sites, flush to disk. This reduces crash-recovery surprises:
sync
# If using MariaDB/MySQL, do a quick consistency-friendly flush
mysql -e "FLUSH TABLES WITH READ LOCK;" && sleep 2 && mysql -e "UNLOCK TABLES;"
If you run a busy store, schedule snapshots in low-traffic windows.
For point-in-time needs, rely on offsite backups. Don’t assume a snapshot will line up with the incident.
Step 3: Build encrypted offsite backups (the part that actually saves you)
Offsite backups cover what snapshots won’t. That includes storage failure, a compromised VPS, accidental account termination, or a provider outage.
The goal is simple: independent copies with encryption and retention that you can restore on demand.
A practical pattern is 3-2-1: 3 copies, 2 types of media, 1 offsite.
If you want a deeper blueprint before you commit to retention settings and restore tests, skim HostMyCode’s planning guide: VPS backup strategy tutorial (2026).
Choose backup targets that don’t miss critical config
At minimum, include:
/etc(web server configs, TLS, cron, system services)/var/www(or your vhost roots)- Database dumps (or raw DB directories only if you know exactly what you’re doing)
/home(SFTP users, app files)- Control panel data if applicable (cPanel/DirectAdmin backup outputs, not random directories)
Example: Restic backup to S3-compatible storage (Ubuntu/Debian)
This setup stays readable during an incident. You can use any S3-compatible endpoint.
Create the repo, store secrets in a root-only file, then schedule the job.
# Install restic
sudo apt update
sudo apt install -y restic
# Create a place for secrets
sudo install -d -m 700 /root/.backup
sudo nano /root/.backup/restic.env
Put this in /root/.backup/restic.env (example variables):
export RESTIC_REPOSITORY="s3:https://s3.example.com/your-bucket/vps-01"
export RESTIC_PASSWORD="use-a-long-random-password"
export AWS_ACCESS_KEY_ID="YOURKEY"
export AWS_SECRET_ACCESS_KEY="YOURSECRET"
Initialize the repository:
source /root/.backup/restic.env
restic init
Create a backup script at /usr/local/sbin/backup-restic.sh:
#!/usr/bin/env bash
set -euo pipefail
source /root/.backup/restic.env
# Create a DB dump directory
install -d -m 700 /root/.backup/dumps
# Example: dump all MySQL/MariaDB databases
# Adjust credentials handling for your environment
mysqldump --single-transaction --quick --routines --events --all-databases \
> /root/.backup/dumps/all-databases.sql
# Run restic backup
restic backup \
/etc \
/var/www \
/home \
/root/.backup/dumps \
--tag daily
# Retention policy
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
# Quick health check
restic check --read-data-subset=1/200
Make it executable and run it once:
sudo chmod 700 /usr/local/sbin/backup-restic.sh
sudo /usr/local/sbin/backup-restic.sh
For a full incremental/retention walkthrough, including restore patterns and S3 tuning, see: Incremental Backup Tutorial (2026).
Schedule backups with systemd timer (cleaner than cron)
Create /etc/systemd/system/restic-backup.service:
[Unit]
Description=Nightly Restic Backup
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/backup-restic.sh
Create /etc/systemd/system/restic-backup.timer:
[Unit]
Description=Run Restic Backup nightly
[Timer]
OnCalendar=*-*-* 02:15:00
RandomizedDelaySec=900
Persistent=true
[Install]
WantedBy=timers.target
Enable it:
sudo systemctl daemon-reload
sudo systemctl enable --now restic-backup.timer
systemctl list-timers | grep restic
Step 4: Write the restore runbook (then practice it)
A backup you’ve never restored is a hope, not a plan.
Your runbook should answer one question: “What do I type, in what order, and how do I confirm it worked?”
Restore drill: rebuild a new VPS and restore from offsite
Spin up a fresh VPS (same distro family if possible). Update packages, set the hostname, and install your web stack.
For DR, the backup tool should do most of the work.
Don’t turn restores into a manual file-copy project.
Install restic and fetch the latest snapshot list:
sudo apt update
sudo apt install -y restic
sudo install -d -m 700 /root/.backup
# copy restic.env securely (do not paste it into chat logs)
source /root/.backup/restic.env
restic snapshots
Restore to a staging path first. This prevents blind overwrites of system files:
install -d -m 700 /restore
restic restore latest --target /restore
Move restored content into place (carefully)
- Review
/restore/etcfor vhost configs, TLS paths, cron jobs. - Restore site files to
/var/www(or your chosen roots). - Import database dump(s) and confirm users/permissions.
Example file restore (adjust to your layout):
rsync -aHAX --numeric-ids /restore/var/www/ /var/www/
rsync -aHAX --numeric-ids /restore/home/ /home/
Example DB restore:
mysql < /restore/root/.backup/dumps/all-databases.sql
Verification checks that catch real mistakes
- Web: load homepage and login page; confirm static assets load; check
curl -I https://yourdomain. - Permissions: confirm your web user owns uploads; WordPress can write to
wp-content/uploads. - TLS: check certificate chain and expiration.
- Outgoing mail: send a test from the app and verify it arrives (or at least leaves the queue).
If you host mail on the same VPS, add explicit IMAP/SMTP login tests.
This dovecot triage guide pairs well with DR drills. It covers the common “service is up but logins fail” scenarios: Dovecot IMAP troubleshooting tutorial (2026).
Step 5: Plan DNS failover without breaking web or email
DNS is how “the restore is ready” becomes “users can reach it.” Details matter.
Caches linger, and mail records have sharp edges.
Lower TTL before a planned cutover (and keep it low for DR readiness)
For critical records (A/AAAA, MX, and any “autodiscover” style records), set TTL to 300 seconds.
If you’re planning a move, do this 24–48 hours ahead of time. That gives old resolver caches time to age out.
Use this internal HostMyCode tutorial for a safe TTL reduction workflow: DNS TTL Reduction Tutorial (2026).
Decide what “failover” means for you
- Web-only: change A/AAAA to standby IP. Easiest.
- Web + email: you must also handle MX, SPF/DKIM alignment, and PTR expectations.
- Control panel hosting: you may need to move account data or keep a spare licensed panel ready.
If you need a full domain move workflow (web + mail + subdomains), this HostMyCode guide keeps the order sane: DNS Migration Tutorial (2026).
Quick DNS cutover checklist (usable during an incident)
- Confirm standby VPS is serving the correct vhost and TLS cert.
- Update A/AAAA records (and MX if email moves).
- Verify propagation from two outside resolvers (example:
1.1.1.1and8.8.8.8). - Watch logs for traffic and 404 spikes; fix missing assets fast.
- After stabilization, raise TTL back to 3600–14400 to reduce query load.
Step 6: Add “guard rails” that reduce recoveries in the first place
This isn’t a hardening guide. Still, a few guard rails reduce the number of “we need a restore” days.
Turn on monitoring for disk, load, and service health
Most outages start with disk pressure, not CPU. Alert on:
- Disk usage: 80% warning, 90% critical
- Memory: sustained swap-in activity
- Service health: nginx/apache/php-fpm + database
- SSL expiry: 14-day warning
If you don’t have monitoring yet, set a baseline first: Server Monitoring Tutorial (2026).
Keep mail deliverability stable during recovery
If you send mail from your VPS, failing over to a new IP can trigger reputation checks.
Document your PTR/rDNS and SPF/DKIM setup. Be ready to update them quickly.
If you’d rather decouple website hosting from email delivery, an SMTP relay shrinks the blast radius during a rebuild: SMTP relay setup guide tutorial (2026).
Step 7: A quarterly DR drill that takes 45–90 minutes
Put it on the calendar and run the same drill every quarter.
Measure time-to-restore, not just whether it “worked.”
- Spin up a fresh VPS (test environment).
- Restore from offsite into
/restore, then into live paths. - Start services and validate with a host-file override (no public DNS changes).
- Run a short functional test: login, upload a file, submit a form, place a test order if applicable.
- Record RTO and the top 3 delays (missing package, wrong PHP version, cert path, DNS confusion).
- Update the runbook while it’s still fresh.
Host-file override example (from your laptop):
# Linux/macOS: map domain to standby IP temporarily
sudo sh -c 'echo "203.0.113.10 yourdomain.com www.yourdomain.com" >> /etc/hosts'
# Then test
curl -I https://yourdomain.com
Common failure points (and how to avoid them)
- Backups run but are incomplete: you forgot
/etcor excluded uploads. Fix your include list and re-run. - Restores overwrite the OS: restore to a staging directory first, then selectively sync.
- Wrong PHP version after rebuild: document versions in the inventory; pin packages if needed.
- TLS breaks after cutover: private key wasn’t backed up, or the vhost points to old paths.
- Email breaks: MX/SPF/DKIM/PTR aren’t aligned with the new sending IP/hostname.
Summary: your DR plan should be boring, documented, and tested
Disaster recovery is a process you rehearse, not a tool you install once.
Use snapshots for quick rollbacks. Keep encrypted offsite backups with retention. Maintain a DNS cutover checklist that includes mail.
If you want a stable platform to run these drills on, start with a HostMyCode VPS. For production hosting where you want help validating backups and building a repeatable restore runbook, managed VPS hosting is often the quickest route to a DR posture you can defend.
If your revenue depends on uptime, treat restores like a feature you ship and test. HostMyCode can provision a right-size VPS and help you design backup + failover workflows you can rehearse on schedule.
Start with a HostMyCode VPS, or choose managed VPS hosting if you want hands-on support with recovery planning and restore drills.
FAQ: VPS disaster recovery drills and real-world restores
How often should I run a restore test?
Quarterly is a practical cadence for most hosting VPS setups. Also run a test after major stack changes (web server swap, PHP upgrade, control panel migration).
Are provider snapshots enough?
No. Snapshots are excellent for quick rollback, but they won’t save you from a provider incident or account compromise. Keep encrypted offsite backups.
What should I back up for WordPress specifically?
At minimum: the WordPress directory (including wp-content/uploads), your database dump, and the server config/TLS files that make the site reachable over HTTPS.
Can I do DNS failover without downtime?
You can reduce downtime sharply, but “zero” depends on your TTL and how quickly resolvers and clients respect changes. Keep TTL at 300s for critical records if you need fast DR.
What’s the simplest DR plan for a small business site?
Daily offsite backups + weekly restore test to a spare VPS, plus a documented DNS change checklist. Add snapshots before updates for quick rollback.