from key generation to restore
An unencrypted database backup sitting in external storage or with a cloud provider is a full export of every customer record the moment an attacker gains access to that storage. This article shows how Percona XtraBackup produces encrypted backups using the --encrypt options, how keys are managed securely, how the restore workflow with decryption plays out, and how to build a retention strategy for several backup generations under different keys.
Table of Contents
- 1. Why unencrypted backups are a risk of their own
- 2. XtraBackup basics briefly: this article's focus on encryption
- 3. The --encrypt options in detail: algorithm and key source
- 4. Key management: generation and secure storage
- 5. The restore workflow: decrypt first, then prepare
- 6. Combining compression and encryption: the correct order
- 7. Retention strategy: encrypted backup generations and key rotation
- 8. Automation in cron or in the CI pipeline
- 9. Monitoring and integrity verification of encrypted backups
- 10. Summary
- 11. FAQ
1. Why unencrypted backups are a risk of their own
Many Magento operators invest considerable effort in securing the running database, for instance through TLS-encrypted connections and strict user privileges, while the nightly backup, a plain copy of all that data, lands unencrypted in offsite storage or with a cloud storage provider. A backup is functionally identical to the database itself, so it holds the same customer data, addresses, and, depending on configuration, payment references, often even spanning a longer historical period than the current production database.
Cloud storage buckets in particular are a popular target for automated scans looking for misconfigured access permissions, and even with correct configuration, the risk of a compromised access key for the storage service remains. Consistently encrypting the backup file itself ensures that plain read access to the storage location alone is not enough to obtain usable data.
2. XtraBackup basics briefly: this article's focus on encryption
The basic mechanics of Percona XtraBackup as a tool for consistent hot backups of InnoDB tables, including the two-phase logic of backup followed by a prepare step, are covered in detail in a separate article in this series that contrasts XtraBackup with mysqldump. This article assumes a basic understanding of XtraBackup and focuses exclusively on the encryption features that are essential for backups holding sensitive customer data.
The one thing worth knowing here is that XtraBackup encrypts data block by block during the actual backup process, before the data is even written to the target storage, so a complete, unencrypted copy never exists on the target medium at any point.
3. The --encrypt options in detail: algorithm and key source
The central option --encrypt=AES256 enables encryption using the AES algorithm with a 256-bit key length, the currently recommended standard for backup encryption. The actual key can be supplied two ways: directly as a base64-encoded string through --encrypt-key, which suits automated scripts that load the key from a secrets manager at runtime, or through a file via --encrypt-key-file, which keeps the key out of the operating system's process list.
From a security standpoint, --encrypt-key-file is clearly preferable to passing the key directly, since command-line parameters can be read by other processes on the same system through ps aux or similar tools, while a key file with restrictive permissions is not exposed to that risk. In addition, --encrypt-threads and --encrypt-chunk-size let you tune the encryption's parallelism and block size to the available CPU capacity.
# Generate a key and store it in a file with restrictive permissions
openssl rand -base64 24 > /etc/xtrabackup/backup.key
chmod 600 /etc/xtrabackup/backup.key
chown mysql:mysql /etc/xtrabackup/backup.key
# Produce an encrypted backup
xtrabackup --backup --target-dir=/backup/full-2026-08-08 --encrypt=AES256 --encrypt-key-file=/etc/xtrabackup/backup.key --encrypt-threads=4
4. Key management: generation and secure storage
An AES256 key for XtraBackup can be generated with a single call to openssl rand -base64 24, though the actual management deserves far more attention than the plain generation step. The key must never live in the same directory or on the same storage system as the encrypted backup itself, since an attacker with access to the backup storage would otherwise find the matching key right there, rendering the encryption pointless.
In production environments the key should instead live in a dedicated secrets management system such as HashiCorp Vault or a comparable cloud KMS service, and be loaded onto the executing server only briefly, for the duration of the backup or restore run. Once the operation completes, the local copy of the key file should be actively removed again, to minimize the attack surface between two backup runs.
5. The restore workflow: decrypt first, then prepare
An encrypted backup cannot be processed directly with --prepare, since InnoDB's redo log application works on unencrypted files. The first step of any restore is therefore xtrabackup --decrypt=AES256 using the same key that was used for the backup, applied against the target directory holding the encrypted files. Only afterward does the familiar --prepare step follow, applying InnoDB's internal consistency mechanisms and making the backup restorable.
A common mistake in practice is forgetting the decryption step and jumping straight to --prepare, which produces cryptic error messages about corrupted or unreadable files, since XtraBackup does not recognize encrypted files as such, it just sees malformed InnoDB structures. A documented, tested restore runbook with the correct sequence of steps is therefore essential, precisely because restores are almost always performed under time pressure during a real incident.
# Step 1: decrypt (same key as used for the backup)
xtrabackup --decrypt=AES256 --encrypt-key-file=/etc/xtrabackup/backup.key --target-dir=/backup/full-2026-08-08
# Step 2: bring InnoDB to a consistent state
xtrabackup --prepare --target-dir=/backup/full-2026-08-08
# Step 3: copy the restore into the data directory
xtrabackup --copy-back --target-dir=/backup/full-2026-08-08 --datadir=/var/lib/mysql
6. Combining compression and encryption: the correct order
Besides encryption, XtraBackup also supports compression through --compress, and both features can be enabled together in the same backup run to address both storage footprint and confidentiality. Internally, XtraBackup applies compression first and encryption second, which makes cryptographic sense, since compressed data has higher entropy and is therefore better suited to encryption than uncompressed raw data.
For restore, that means the reverse order applies: decryption must happen first, then decompression via xtrabackup --decompress, and only after that does the usual --prepare step follow. Getting this order wrong here, too, produces no meaningful error message, just unreadable, seemingly corrupted files.
7. Retention strategy: encrypted backup generations and key rotation
Unlike unencrypted backups, it is not enough with encrypted generations to simply delete an outdated key once a new one is in use: every backup remains tied to exactly the key it was created with, and a key deleted too early makes the corresponding historical backups permanently unusable. A sensible key rotation, say quarterly, must therefore be planned hand in hand with the actual backup retention period.
In practice, an approach that works well tags every generated key uniquely with a timestamp or a generation ID and documents it alongside the metadata of the corresponding backup run, so it is unambiguously traceable which specific key any given historical backup needs for a restore. Old keys are not deleted under this approach, they are archived in the same secrets management solution until the last backup encrypted with them has itself been deleted per the retention period.
8. Automation in cron or in the CI pipeline
For production use, the entire backup process, including loading the current key from the secrets management system, should be automated in a versioned script rather than typing commands manually on the database server. Such a script should load the key onto the server temporarily right before the backup call, remove it again once the run completes, and report the outcome of the operation, success or failure, to a monitoring system.
Just as important as automating the backup process itself is regular, automated verification: a restore test in an isolated environment that runs through the full decryption and restore workflow reliably reveals whether a key was documented incorrectly, or a backup is otherwise genuinely not restorable, long before a real incident exposes that gap painfully.
9. Monitoring and integrity verification of encrypted backups
A backup run only counts as complete once both the xtrabackup process's exit code and a subsequent checksum over the produced archive file have been verified successfully, since an aborted or incomplete run can sometimes still leave behind a target file that looks plausible but is actually unusable. An additional SHA256 checksum comparison between the locally produced archive and its copy in the target storage reliably reveals whether data was lost or corrupted during transfer.
For ongoing monitoring, every backup run should actively report its success or failure to a central monitoring system, rather than relying on purely passive checks of files present in the target directory, since a missing report can go unnoticed even when a cron job simply stops firing altogether. A simple rule that raises an alert as soon as a day passes without a successfully completed, encrypted backup run being reported closes that gap reliably.
# Generate a checksum for the local archive and compare it against target storage
sha256sum /backup/full-2026-08-08.xbstream > /backup/full-2026-08-08.sha256
sha256sum -c /backup/full-2026-08-08.sha256
# Report the backup run's exit code to the monitoring system
xtrabackup --backup --target-dir=/backup/full-2026-08-08 --encrypt=AES256 --encrypt-key-file=/etc/xtrabackup/backup.key
echo "backup_exit_code:$? backup_date:$(date +%F)" | curl -s --data-binary @- https://monitoring.internal/api/backup-status
| Option | Purpose | Example Value | Note |
|---|---|---|---|
| --encrypt | Selects the encryption algorithm | AES256 | Currently the only supported algorithm tier in XtraBackup |
| --encrypt-key-file | Path to the key file | /etc/xtrabackup/backup.key | Preferred over --encrypt-key due to process list visibility |
| --encrypt-key | Key passed directly as a base64 string | loaded from an environment variable | Suitable only for automated scripts with secrets injection |
| --encrypt-threads | Parallelism of the encryption | 4 | Tune to the backup server's available CPU cores |
| --decrypt | Decryption before the prepare step | AES256 | Mandatory first step of any encrypted backup's restore |
Mironsoft
Database performance, index tuning, and Magento DB optimization
A Magento shop suffering from slow database queries?
We analyze MySQL databases for performance bottlenecks, optimize indexes and queries with purpose, and set up backup and replication strategies that actually work when it counts.
Performance Audit
Systematically investigate the slow query log and explain plans for bottlenecks.
Index Optimization
Build indexes with purpose for the shop's actual query load.
Backup Strategy
Set up reliable backup and restore processes for production Magento databases.
10. Summary
Backup Encryption with XtraBackup at a Glance
Algorithm
AES256 via --encrypt is the currently recommended standard for XtraBackup encryption.
Key file
--encrypt-key-file is preferable to passing the key directly, due to process list visibility.
Restore order
Decrypt first, decompress if needed, and only then run the familiar --prepare step.
Generations
Old keys must stay archived until the associated backup's retention period has expired.