PrestaShop backups and tested disaster recovery
Back up PrestaShop files and database, automate checked encrypted copies, retain off-server history and test a complete isolated restoration.
Back up your database and persistent files as a coordinated recovery point. A usable recovery plan also needs checked transfers, retained history, accessible keys and a tested restore.
What we would do
We would start with the shop you already run: its hosting access, database engines, module storage, theme and custom code, order data, integrations, markets and the team available to recover it. Agree what you can afford to lose and how long you can stop trading, then choose a backup route whose recovery you can demonstrate.
Rehearse a new backup process on an isolated staging copy with the same relevant storage and deployment layout. Keep the existing checked process until the replacement has produced a matched recovery set and passed a restore. Plan the production switch, name the person watching the first scheduled runs and keep the previous configuration available if the new job fails.
| Your situation | Starting route | Evidence before relying on it |
|---|---|---|
| Your host manages the server and you have no shell access. | Start with the hosting backup service, supplemented by downloadable exports where needed. | A restore of your actual database and persistent files, plus a recovery route if the hosting account itself is unavailable. |
| Your team wants backup controls in the back office. | Assess Security Revolution, whose backups follow your chosen scope, destination and retention. | The installed release captures your module data, and the recovery instructions remain usable when the back office cannot load. |
| You control a Linux server and have someone responsible for scheduled jobs. | Use a checked database export and coordinated file capture, as in the examples below. | The actual scheduled account can finish, transfer and restore the complete set without an interactive prompt. |
| A snapshot restore cannot meet your acceptable data-loss window. | Ask the host or database specialist about point-in-time recovery alongside matched file recovery. | A rehearsal showing the chosen database boundary and the corresponding files and external business records. |
Whichever route you choose, require independently protected retention and a tested recovery. A hosting feature, module status or successful shell exit is evidence about part of the process; acceptance is a usable restored shop.
If you want the routine maintained for you, the PrestaShop Store Care & Maintenance Plan includes encrypted off-site backups and restore tests.
Back up files and database together
You need both the database and the shop files, including configuration secrets and customer data. Schedule backups according to how much change you can afford to lose, and take a separate recovery point before core/module/theme updates, imports, migrations and server changes.
| Component | What to retain |
|---|---|
| Database | Orders, customers, catalogue, configuration, module tables and applicable stored programs |
modules/, themes/, override/ | Installed versions, custom code, child themes, module data and assets |
img/ | Product, category, CMS and other shop imagery |
download/ | Virtual products and product attachments |
upload/ | Customer customization uploads |
| Configuration | app/config/parameters.php on modern shops, other required configuration and cryptographic keys; legacy installations can use config/settings.inc.php |
| Custom mail and translations | Core, module and theme resources plus database translation overrides |
| External deployment configuration | Web-server configuration, PHP settings, scheduled jobs, service definitions and required credentials |
Inspect module-specific storage and external object storage. Module uploads are not inherently disposable. A database without the matching uploaded file, download or cryptographic key may be unusable for that function.
Exclude only data you can demonstrably regenerate. Cache, build dependencies and sessions may be disposable for your recovery plan. Retain vendor packages when you cannot reproduce the exact versions and custom changes from trusted artifacts. Logs can be important for incident investigation even if you retain them separately from the recovery archive. Do not delete business data merely to make a backup smaller.
Coordinate database and file capture. For a strict recovery point, quiesce all writers or use a tested database/filesystem snapshot strategy. A maintenance page alone does not stop cron, queues, imports or incoming integrations. Record the exact database and file artifact names in a recovery manifest, with their capture boundaries, shop identity, software versions and any excluded storage. That manifest lets someone distinguish a matched set from unrelated archives with similar dates.
Choose a database export method
First inventory storage engines, replacing the database name:
SELECT TABLE_NAME, ENGINE
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'prestashop'
AND TABLE_TYPE = 'BASE TABLE';
--single-transaction provides a consistent snapshot for transactional tables such as InnoDB. MyISAM and MEMORY tables can still change during that dump. Quiesce writes or choose an appropriate locking/physical-backup method for those tables. Avoid concurrent ALTER, CREATE, DROP, RENAME or TRUNCATE operations during the dump. See the MySQL snapshot limitations.
--quick streams rows. --skip-lock-tables does not make nontransactional tables consistent. Triggers are normally included by default; request routines and events explicitly when they belong in the backup. The account needs the privileges required by your server/client version and objects. Check a compatible MariaDB client separately where applicable. See MySQL stored-program export options.
For no-SSH hosting, use a tested hosting-panel or phpMyAdmin export. Review selected tables, export options and server/PHP limits. There is no universal 100 MB export limit. Test the downloaded archive by restoring it elsewhere.
PrestaShop's Advanced Parameters > DB Backup tool can supplement your process, but it exports database tables rather than the whole shop. Do not assume stored-program coverage. Download the result and include it in your off-server retention; same-server storage alone cannot survive loss of that server.
Automate a checked and encrypted dump
This Linux/Bash example is for the transactional-dump conditions above. It needs MySQL client tools, gzip, GnuPG 2.1 or later with loopback pinentry permitted by gpg-agent, rsync, flock and Python 3. Prepare a dedicated backup directory outside the web root and an off-server SSH account with the remote directory already created. Test the account's permissions and SSH host key before scheduling. Ensure the backup account has a writable GnuPG home and can retrieve the secret noninteractively.
Store database credentials in a protected option file, readable only by the backup account, for example /home/backup/.my.cnf:
[client]
user=your_backup_user
password=your_database_password
host=localhost
Set its mode to 600. Supply the encryption secret through your protected secret mechanism as a readable descriptor/file for the backup job. Keep a recoverable copy in a separate password manager or secret store. Do not put a passphrase in the command line or script.
The script stages output, checks the whole pipeline, decrypts to test gzip integrity, checks archive copies and off-server transfer, then publishes locally and rotates. It retains at most seven successful daily-run archives, four Sunday-run archives and twelve first-of-month-run archives. These are copy counts, not guaranteed calendar-day coverage; extra manual runs and missed jobs affect coverage.
#!/usr/bin/env bash
set -Eeuo pipefail
umask 077
DB_NAME='prestashop'
BACKUP_DIR='/srv/backups/prestashop/database'
DEFAULTS_FILE='/home/backup/.my.cnf'
SECRET_FILE='/run/secrets/prestashop-backup-passphrase'
REMOTE='backupuser@backup-host:/srv/backups/prestashop/database/'
mkdir -p "$BACKUP_DIR"/{daily,weekly,monthly}
exec 9>"$BACKUP_DIR/.lock"
flock -n 9 || { echo 'Another backup is running' >&2; exit 1; }
work=$(mktemp -d "$BACKUP_DIR/.run.XXXXXX")
trap 'rm -rf -- "$work"' EXIT
trap 'echo "Backup failed: inspect the job log" >&2' ERR
stamp=$(date -u +%Y%m%dT%H%M%SZ)
name="db_${stamp}.sql.gz.gpg"
mkdir "$work/daily"
mysqldump --defaults-extra-file="$DEFAULTS_FILE" \
--single-transaction --quick --skip-lock-tables \
--routines --triggers --events "$DB_NAME" \
| gzip \
| gpg --batch --yes --pinentry-mode loopback \
--passphrase-fd 3 --symmetric --cipher-algo AES256 \
3<"$SECRET_FILE" >"$work/daily/$name"
test -s "$work/daily/$name"
gpg --batch --pinentry-mode loopback --passphrase-fd 3 \
--decrypt "$work/daily/$name" 3<"$SECRET_FILE" | gzip -t
if [ "$(date -u +%u)" = 7 ]; then
mkdir "$work/weekly"
cp -- "$work/daily/$name" "$work/weekly/$name"
fi
if [ "$(date -u +%d)" = 01 ]; then
mkdir "$work/monthly"
cp -- "$work/daily/$name" "$work/monthly/$name"
fi
# The remote root and account must already be prepared and tested.
rsync -a --checksum --delay-updates "$work/" "$REMOTE"
# Publish locally only after all staged copies and transfer succeeded.
for tier in daily weekly monthly; do
if [ -d "$work/$tier" ]; then
mv -- "$work/$tier/$name" "$BACKUP_DIR/$tier/$name"
fi
done
# Count retention, not an age approximation. Remote retention is separate.
python3 - "$BACKUP_DIR" <<'ROTATE'
from pathlib import Path
import sys
root = Path(sys.argv[1])
for tier, keep in [('daily', 7), ('weekly', 4), ('monthly', 12)]:
archives = sorted((root / tier).glob('db_*.sql.gz.gpg'), reverse=True)
for archive in archives[keep:]:
archive.unlink()
ROTATE
printf 'Backup completed: %s\n' "$name"
Adjust all paths, account settings and database name before use. The GnuPG descriptor mechanism uses --pinentry-mode loopback for unattended passphrase use; see the GnuPG manual. Local staging output is removed when the script exits. Bash pipefail prevents a successful final pipeline command from hiding a failed dump.
A decrypt/gzip test proves transport-format integrity, not that every required SQL object or file exists. Perform restoration tests too. Configure the scheduler to alert on a nonzero exit and on missing successful runs; the example writes errors to stderr but does not implement an email delivery service. Protect logs from secrets and monitor available space.
Example daily schedule, using the server's timezone. UTC in filenames does not change cron's scheduling timezone:
0 3 * * * /home/backup/bin/backup-db.sh >> /home/backup/log/backup-db.log 2>&1
Create the log directory first and test the job as its actual account. Keep pre-change backups in a separate policy so normal rotation does not remove the recovery point you need. Manage off-server retention independently; this script never deletes remote history.
Create consistent file archives and mirrors
Write archives outside the shop tree to avoid backing the archive into itself. The following command uses member names relative to the shop root and stores symbolic links as links. Include persistent link targets outside that tree in the coordinated recovery set, and record them in the deployment inventory:
tar -czf /srv/backups/prestashop/files.tar.gz --exclude='./var/cache' --exclude='./var/sessions' --exclude='./node_modules' -C /var/www/html .
A modern-shop critical-file archive can use this starting inventory. Check every listed directory, add any other persistent module data, and adapt web-server configuration to your deployment:
tar -czf /srv/backups/prestashop/critical.tar.gz -C /var/www/html modules themes img download upload override mails translations config app/config .htaccess
This is not a complete substitute for the full deployment inventory. A missing expected member or changed file during capture must be investigated rather than ignoring tar's exit status. Encrypt file archives containing personal data or secrets and transfer them under the same checked process as database backups. The example filenames describe a single capture: give retained file archives unique recovery-point names and add them to the manifest. Reusing files.tar.gz without keeping earlier versions can overwrite the only file set matching an older database dump.
Rsync is useful when many files are unchanged; there is no universal directory-size threshold for switching methods. Start with a dry run and a validated source:
rsync -an --delete /var/www/html/ backupuser@backup-host:/srv/mirror/prestashop/
Inspect changes before using the corresponding live transfer. --delete makes a mirror follow source deletions. A readable but unexpectedly empty mount or valid-but-wrong source can therefore remove useful destination data. A nonexistent source argument normally errors, and detected I/O errors normally suppress deletion; these are different cases. Validate the mounted filesystem and expected shop files, and retain versioned snapshots outside the mirror. See the rsync manual.
Do not exclude module uploads just because the directory name suggests runtime data. Keep history protected from both accidental source changes and compromised shop credentials.
Keep recoverable off-server history
A local backup can help with a local mistake, but a copy on the same machine shares risks with the shop. Keep a recoverable copy outside that failure domain. A 3-2-1 plan means three copies, two storage types and at least one off-site copy. Include an offline or protected historical copy where that fits your recovery risks.
Object storage, another server and managed backup services are options. Compare access controls, versioning, deletion protection, restore speed, region, operations, retrieval and egress costs. Do not assume one provider is always cheaper. Use scoped credentials and ensure the shop cannot erase every retained recovery point.
Set retention from your incident-detection window and storage budget. Count-based policies and age-based policies are different. For example, find -mtime +7 does not mean exactly seven copies or exactly seven days; GNU find uses completed 24-hour age buckets. Keep daily, weekly and monthly layers if useful and verify actual coverage.
Ask your host what is included, consistency method, frequency, retention, location, encryption, restore granularity, fees and response time. Request a test restore. Record the provider's commitments and the results of a test restore.
Document access to off-server storage and decryption keys where you can reach it when production is unavailable. A protected backup with a lost key cannot meet your recovery objective.
Investigate reassuring results that hide a recovery gap
| What you observe | What to check next |
|---|---|
| The dashboard shows success, but the newest usable recovery point has not advanced. | Match the scheduler result to the named final artifact and completed remote transfer. Check that the dashboard is reading this job and account, rather than a previous run or a different shop. |
| The local archive decrypts, but nobody has retrieved the remote copy. | Download a retained remote artifact using the recovery account and restore from that copy. Local checks do not exercise remote read permissions, retrieval credentials or the recovery operator's access. |
| The developer can restore from their usual machine, but a replacement operator cannot. | Repeat from a prepared recovery environment using the documented accounts and secrets. Identify missing client tools, private keys or configuration that existed only on the developer's machine. |
| A job fails on staging and no owner receives an alert. | Exercise the failure and missing-run notifications deliberately. Make sure the missing-run check can still report when the shop server is unavailable, and confirm the named recipient can respond. |
Record the last successful capture, checked transfer and application restore separately. A recently uploaded archive can still contain an older capture, so use the recovery manifest when judging the age of the data you could actually recover.
Restore to isolation and verify completeness
- Create an isolated staging environment using compatible PrestaShop, PHP and database versions. Preserve the original backup.
- Before importing SQL, disable the database event scheduler in the isolated test environment. Block outbound mail, payment capture, webhooks, scheduled fulfilment and other production side effects before starting the restored application or its jobs. Restrict access and indexing, and use sandbox credentials for checkout tests.
- Decrypt the database archive and import it into a new empty test database with a test account. Never begin a test by dropping the production database.
- Inspect and extract the matching file archive into an empty staging root. Set correct ownership/permissions and configure staging database credentials and shop URLs while preserving required cryptographic keys.
- Clear application caches using supported controls, then test front office, back office, product/combination pages, downloads, customer customizations, cart and a sandbox checkout.
- Compare the backed-up inventory: table and object counts, row counts for key business tables, latest orders, persistent files, modules and configuration. Counts alone do not prove application correctness.
- Record elapsed recovery time, missing prerequisites and the exact restored recovery point.
Run decryption/import with pipeline failure checking. This example assumes the option file authenticates to the isolated test database, which already exists:
set -o pipefail
gpg --batch --pinentry-mode loopback --passphrase-fd 3 --decrypt /srv/restore/db.sql.gz.gpg 3</run/secrets/prestashop-backup-passphrase | gzip -dc | mysql --defaults-extra-file=/home/backup/.my.cnf prestashop_test
Example queries, using the actual table prefix:
SELECT COUNT(*) AS products FROM ps_product;
SELECT COUNT(*) AS orders FROM ps_orders;
SELECT COUNT(*) AS customers FROM ps_customer;
SELECT MAX(date_add) AS latest_order FROM ps_orders;
Capture comparison data at the recovery point or account for later changes. A growing production database will not match an older snapshot. Verify routines, events and triggers if they are required. Keep the restored event scheduler and application jobs controlled so a test cannot act on production systems.
Repeat tests after backup-tool, credential or infrastructure changes and at a planned interval, such as a quarterly drill. Choose the interval for your risk and record the outcome of each drill.
Rehearse an update rollback before changing production
Suppose a module update changes database tables and writes new files. Replacing its directory with the old package can leave old code reading the new schema. Your rehearsal needs to prove how the previous application state is recovered as well as whether the update installs.
- On the isolated shop copy, choose representative records: an order, a product with combinations, a download or customer upload where used, and a module-specific record. Record the expected result in each relevant shop, language and currency.
- Take a matched pre-change recovery set, perform the update, then rehearse the documented reversal into a separate recovery environment. Check those records and business functions, and keep the evidence with the exact module and shop versions.
- Agree what failure stops the launch, who makes that decision and which recovery set is authorised. If the rehearsal misses the recovery target, change the process before booking the live window.
- For the production change, take a fresh coordinated recovery point after controlling writes and in-flight integrations. Record any accepted orders or external events still awaiting processing, rather than relying on the older staging backup.
- Before reopening, verify the agreed tests and assign responsibility for restoring each paused job or integration. Once new transactions are accepted, reassess rollback against those transactions before replacing live data.
A successful technical reversal does not settle what happened outside the shop. Include the payment provider, warehouse, ERP and other systems that can accept or act on an event during the change window in the reconciliation plan.
Use a recovery runbook for each incident
Server or shop outage
Identify whether the issue is the server, database, network, DNS or proxy before replacing data. Contact the host, establish scope and provision a compatible recovery environment if needed. Restore matched files and database, verify URLs, DNS, TLS and permissions, then test orders and transactional communications before reopening.
Database corruption
Stop all relevant writes and preserve logs, data and available snapshots for diagnosis. Identify affected engines. mysqlcheck --auto-repair is not an InnoDB recovery tool: REPAIR TABLE applies only to supported engines, as the MySQL documentation explains. Choose engine-specific recovery or restore a tested backup into a new environment. Reconcile orders/payments created after that recovery point before switching over.
Compromised shop
Isolate the shop and preserve evidence before cleanup. Do not treat a search for suspicious PHP strings or recent modification dates as proof that all backdoors were found. Establish the entry point, restore/rebuild from a known trusted state, patch affected software, rotate relevant credentials and verify configuration and external integrations.
Review employee identities, active flags, profiles and shop permissions against a trusted inventory. The standard employee model has no date_add field, so a query based on an employee creation timestamp will fail. Use actual audit records for chronology. Review modified configuration and payments, then monitor according to the incident findings.
Deleted module files
For the full archive created with -C /var/www/html ., inspect members before selecting one:
tar -tzf /srv/backups/prestashop/files.tar.gz
# In an empty staging root, after confirming this exact member:
tar -xzf /srv/backups/prestashop/files.tar.gz -C /srv/restore/shop ./modules/your_module_name
The staging target directory must exist. Check the restored module, then deploy the required files through your normal recovery process. If it was uninstalled and its tables/configuration were removed, restoring files alone will not restore its data. Reinstalling or recovering module data needs a compatible plan; rolling the whole database back can also remove newer orders.
Work through a mistaken stock import
An import replaces valid stock quantities while customers continue ordering. The latest backup predates both the import and some legitimate orders. First stop the faulty import and identify which system is authoritative for stock; an ERP that immediately resends the same file can undo a repair.
Restore the pre-import set in isolation and compare the affected product and combination identifiers, stock context and import mappings. Preserve the current orders and payment references as evidence. If the damage is confined to identifiable stock records, ask for a scoped correction through the supported stock workflow, rehearsed on a copy of the current shop and accounting for legitimate movements since the backup.
If you must recover the whole database, agree how later orders, payments, shipments and stock movements will be reconciled before switching. Do not reopen simply because the earlier stock figures look right. Keep the import source, affected identifiers and correction results so the same feed can be checked before it runs again.
Set RPO, RTO and point-in-time recovery
RPO is the acceptable data-loss window. RTO is the target time to restore the service. A once-daily schedule can leave almost a day of changes outside the latest successful backup, and failed jobs make the gap larger. Set targets from the business impact and measured recovery performance, not a universal order-count rule.
A short RTO may be met by a fast restore, standby or another design, depending on the shop. Measure provisioning, transfer, decryption, import, verification, DNS and reopening. A standby does not by itself guarantee failover time or protection from replicated corruption.
For MySQL point-in-time recovery:
- Enable and retain the appropriate binary logs and verify that your server configuration actually records the required changes.
- Capture the backup's exact binlog coordinates or supported GTID metadata using the documented backup options for that server/client version.
- Retain every required log from that snapshot boundary off-server. Monitor growth, gaps and retention.
- Restore the snapshot into isolation.
- Inspect the logs to find the transaction boundary before the unwanted change, then replay from the exact recorded snapshot boundary to the chosen transaction boundary.
- Validate the resulting application state and reconcile external orders/payments before promotion.
The scheduled start time, such as 03:00, is not the snapshot's exact log boundary. Replaying from that wall-clock time can repeat transactions already included in the dump. See MySQL's event-position recovery procedure. Size log storage from measured workload and retention needs, and monitor it for gaps.
Maintain the recovery routine
- For each scheduled run: verify success, recent artifacts, integrity checks, off-server transfer and useful recovery-point age.
- Regularly: inspect capacity, retention coverage, protected history, permissions and key recoverability. Confirm file backups are as current as your RPO requires.
- After important changes: take and retain a separate matched backup and verify the backup job still works with the new credentials or deployment.
- At the chosen drill interval: restore the whole shop in isolation, test business functions and record the measured RTO/RPO.
- After an incident or failed drill: update the runbook, correct the process and repeat the relevant test.
Keep the runbook and contact/access instructions outside the production server. Include who can authorize reopening, where recovery artifacts and secrets are held, and how to reconcile changes that happened after the restored snapshot.
For the supporting environments, see the staging guide and security guide.
Ask your developer for a usable recovery handover
Ask for a recovery pack that another authorised person can use if the usual developer or agency is unavailable. Have that person follow it during a drill, and correct any step that depends on undocumented knowledge.
- Which shop and data does the plan cover? Get the deployment inventory, table prefix, multistore scope, persistent module storage and exclusions, with a recovery manifest from a completed run.
- Which environment can run the recovered shop? Keep the required PrestaShop, PHP, database and module versions, deployment artifacts and instructions for provisioning the replacement environment.
- How do we retrieve and decrypt without production access? Record storage locations, account ownership, secret-store references and account-recovery instructions. Keep access controlled, with a named authorised alternate; the runbook should point to secrets rather than contain plaintext passwords.
- Who notices a missed backup and who acts? Name the primary and alternate contacts, escalation route and access they need, with evidence that failure notifications reach them.
- What recovery has actually passed? Request the tested recovery point, restored business functions, measured timings and outstanding gaps, including any dependency on provider support.
- Who controls external effects and reopening? List the switches for mail, payment notifications, scheduled jobs and fulfilment exports, the system responsible for each business record, and who approves reconciliation and the production switch.
- What happens if we leave the provider? Confirm how you export retained sets, keep the means to decrypt them and transfer recovery responsibility before accounts or access are closed.
Questions owners ask
Can I restore just one shop in a multistore installation?
Agree the scope before restoring. Shops can share tables, customers, catalogue records and files, so restoring selected tables by name can affect other shops or break relationships. Rehearse the proposed scope against the complete installation.
Can an anonymised staging copy be our emergency backup?
An anonymised copy cannot recover customer details or order data that were removed or changed. Keep the protected original recovery set, and create sanitised development copies from it when needed.
Will restoring an order database refund a captured payment?
No. A payment already accepted by the provider still needs reconciliation even if its local order disappears. Check the provider reference before retrying a charge, issuing a refund or recreating an order.
Can we upgrade PrestaShop while recovering an outage?
Recover the backed-up version in its compatible environment first where possible. Combining recovery with an untested core, theme or module upgrade adds another possible cause of failure; validate any required upgrade separately before the production switch.
Can we delete old encryption keys after rotating them?
Keep the ability to decrypt every retained recovery point. Before retiring a key, confirm which archives use it and rehearse their recovery under the replacement arrangement; changing the key for future jobs does not change existing encrypted archives.