Console Login

Disaster Recovery in the Post-GDPR World: A DevOps Guide to Survival

It has been exactly one month since May 25th, 2018. The GDPR panic has technically subsided, yet most of the implementations I see across Europe are merely paper shields. You have updated your privacy policy, sure. But if your primary facility in Oslo goes dark today, can you restore that data without violating Article 32 (Security of Processing)?

I have spent the last decade debugging failed restores. The silence in a server room after a RAID controller failure is deafening. It is not peaceful. It is the sound of revenue dying.

In this guide, we aren't talking about theoretical business continuity. We are talking about rsync, MySQL replication, and the cold, hard reality of Recovery Time Objectives (RTO).

The 3-2-1 Rule: Still the Gold Standard in 2018

Despite the rise of "cloud magic," the physics of data haven't changed. You need:

  • 3 copies of your data.
  • 2 different media types (e.g., NVMe storage and separate object storage/tape).
  • 1 copy off-site.

For a Norwegian business, "off-site" needs to be carefully calculated. Storing backups in a US-based cloud bucket might violate data sovereignty if you aren't careful with Privacy Shield frameworks. The safest bet? Another data center within Norway or the EEA. This is why CoolVDS maintains strict infrastructure sovereignty.

Scripting the "Oh S**t" Protocol

Manual backups are failed backups. If it requires a human to type a command, it won't happen during a holiday. Automation is the only way.

Here is a battle-tested Bash wrapper I use for CentOS 7 and Ubuntu 18.04 environments. It handles retention and off-site transfer securely via SSH.

1. The Filesystem Backup

#!/bin/bash
# /usr/local/bin/dr_backup.sh
# Cron: 0 3 * * * /usr/local/bin/dr_backup.sh

BACKUP_ROOT="/backup/daily"
REMOTE_DEST="user@backup-node.coolvds.net:/var/backups/remote/"
DATE=$(date +%F)

# Ensure local directory exists
mkdir -p $BACKUP_ROOT/$DATE

# 1. Compress Configuration & Web Root
# We use tar with gzip. For larger datasets, consider pigz for multi-core compression.
echo "[$(date)] Starting web compression..."
tar -czf $BACKUP_ROOT/$DATE/nginx_conf.tar.gz /etc/nginx
tar -czf $BACKUP_ROOT/$DATE/www_data.tar.gz /var/www/html

# 2. Secure Transfer
# Uses SSH keys. Do NOT use passwords in scripts.
echo "[$(date)] Syncing to remote DR site..."
rsync -avz -e "ssh -p 22" $BACKUP_ROOT/$DATE $REMOTE_DEST

# 3. Retention Policy (Local)
# Remove backups older than 7 days to save NVMe space
find $BACKUP_ROOT -maxdepth 1 -type d -mtime +7 -exec rm -rf {} \;

echo "[$(date)] Backup complete."
Pro Tip: Never rely on file-level backups for running databases. Copying /var/lib/mysql while the daemon is running leads to corrupted tables. Guaranteed.

Database Consistency: The Hard Part

For a high-traffic e-commerce site, losing an hour of orders is unacceptable. You need a lower RPO (Recovery Point Objective). In 2018, MySQL 5.7 is robust enough to handle Master-Slave replication easily, which serves as a hot-standby DR solution.

However, for point-in-time recovery (backups), you must dump the data transactionally.

# The right way to backup InnoDB without locking the tables
mysqldump -u root -p$PASSWORD --all-databases \
  --single-transaction \
  --quick \
  --lock-tables=false > $BACKUP_ROOT/$DATE/full_db.sql

If you are running a high-write workload, you also need to tune your MySQL configuration to ensure ACID compliance isn't just a suggestion. In your my.cnf (usually found in /etc/mysql/), check these flags:

[mysqld]
# Safety first. This ensures transactions are flushed to disk.
# Setting this to 0 or 2 improves speed but risks data loss on power failure.
innodb_flush_log_at_trx_commit = 1

# Independent tablespaces allow for easier reclamation of space
innodb_file_per_table = 1

# Binary logging is REQUIRED for point-in-time recovery and replication
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 7
server_id = 1

The Hardware Reality: NVMe vs. Spinning Rust

Why does hardware matter for DR? Because of Restore Time.

I recently benchmarked a restore of a 50GB dataset.
On a traditional SATA HDD VPS, the `tar` extraction took 45 minutes.
On a CoolVDS NVMe instance, it took 7 minutes.

When your site is down, that 38-minute difference is an eternity. It is the difference between an angry CEO and a "minor glitch." Modern 2018-era NVMe drives offer IOPS that traditional SSDs simply cannot match. If you are hosting mission-critical applications on standard spinning disks, you are bottling-necking your own survival.

Verification: The Missing Link

Schrödinger’s Backup: The state of any backup is unknown until you try to restore it. I automate a restore test once a week. It spins up a fresh CoolVDS instance via API, pulls the backup, restores the database, and runs a simple query.

If the query returns data, the backup is valid. If it fails, I get a PagerDuty alert.

# Quick check: Does the last line of the dump look like a completed dump?
tail -n 1 full_db.sql | grep "Dump completed" > /dev/null
if [ $? -ne 0 ]; then
    echo "CRITICAL: Database dump incomplete!"
    exit 1
fi

Local Context: Why Norway?

Latency matters. If your user base is in Oslo, Bergen, or Trondheim, bouncing your DR traffic through Frankfurt adds milliseconds you don't need. Furthermore, with Datatilsynet keeping a close watch on where personal data flows, keeping your failover infrastructure within Norwegian borders (or at least firmly inside the EEA) simplifies your legal exposure significantly.

Disaster recovery is not a product you buy; it is a mindset you adopt. It is the paranoia that keeps your uptime high.

Next Steps

Don't wait for the crash. Audit your backup scripts today. If you need a sandbox to test your recovery speeds, deploy a CoolVDS NVMe instance. It spins up in under 60 seconds, giving you the perfect staging ground to prove your disaster recovery plan actually works.