---
title: "What a WordPress Backup Has to Contain Before a Restore Will Work"
url: https://adityaarsharma.com/what-a-wordpress-backup-must-contain/
date: 2026-09-26
modified: 2026-09-03
lang: en
author: "Aditya Sharma"
description: "UpdraftPlus free does not archive wp-config.php. Read from three plugins' source: what is in the archive, what is not, and the restore rehearsal that finds out."
categories:
  - "Cyber Security"
  - "WordPress"
image: https://adityaarsharma.com/wp-content/uploads/2026/09/f3653ca0-dcc4-49a5-a3a0-97ab99345ad5_2400x2400-1024x1024.png
word_count: 1742
---

# What a WordPress Backup Has to Contain Before a Restore Will Work

UpdraftPlus documents what its free version backs up in one sentence:

"The free version backs up all of the files in the wp_content directory (e.g. plugins, themes, other files) and the WordPress database." Its next line lists what the paid version adds, and the first item is your `wp-config.php` file.

I read that page on 3 September 2026.

![Active installs across two backup plugins whose archive contains no copy of wp-config.php.](https://adityaarsharma.com/wp-content/uploads/2026/09/f3653ca0-dcc4-49a5-a3a0-97ab99345ad5_2400x2400.png)The WordPress.org plugin API reports 3,000,000 active installs for UpdraftPlus, checked on 3 September 2026, and the default archive does not contain the file that holds your database credentials, your table prefix, your salts and every constant your site depends on.

That is not a criticism of UpdraftPlus. It is a correct engineering decision, because `wp-config.php` contains secrets and shipping it to Dropbox by default would be worse.

But it means the thing most people call "my backup" cannot rebuild the site on its own, and almost nobody has checked.

The way to find that out is not to look at your backup. It is to restore it somewhere and see what breaks.

[elementor-template]

## What a restore actually needs
Work backwards from a blank server. To get a working site you need, in this order:

- **The database dump**, with the same table prefix as the `$table_prefix` in the wp-config you are going to use, and the same character set and collation as the tables were created with.- **wp-content/uploads**, in the directory layout the `upload_path` and `upload_url_path` options expect. Those options live in the database, not in a file.- **wp-content/plugins** and **wp-content/themes**, including the parent of any child theme.- **wp-content/mu-plugins**, which is a separate directory that some backup tools treat as a separate thing and some do not.- **The drop-ins**: `wp-content/object-cache.php`, `advanced-cache.php`, `db.php`, `maintenance.php`. These are loose PHP files sitting directly in wp-content, they are installed by caching and database plugins, and a site that loads a stale one throws a fatal error before it reaches your theme.- **wp-config.php**, or at minimum a written record of every constant in it.- **The server configuration** that is not in the WordPress tree at all: your `.htaccess` or nginx rules, your PHP version, your PHP extensions, your cron entries, your DNS.- **WordPress core itself**, which most backup plugins deliberately skip because it is a known download.Items 5, 6 and 7 are where restores fail. Nobody forgets the database.

![The TeamUpdraft documentation page describing exactly what UpdraftPlus backs up.](https://adityaarsharma.com/wp-content/uploads/2026/09/8281531f-f9da-4d13-b085-61bca7d07d97_2800x2000-scaled.png)teamupdraft.com documentation, What does UpdraftPlus back up, screenshot taken 3 September 2026. The paid-only list starts with wp-config.php.

## The constants people lose

### Read past the database credentials

Open your `wp-config.php` right now and read past the database credentials. The lines that will hurt you if they go missing:

- `$table_prefix`. If the dump was made from tables named `xyz_posts` and the config says `wp_`, WordPress will offer you the installation screen and you will think the dump is corrupt.- The eight authentication keys and salts. Losing them does not destroy anything, it logs every user out and invalidates every password-reset link in flight. Worth knowing before you tell a client the restore was clean.- `WP_HOME` and `WP_SITEURL` if they are defined there, because they override the database values and will silently send a restored staging copy to the production domain.- `WP_CONTENT_DIR` and `WP_PLUGIN_DIR` on any site where wp-content has been moved.- `DB_CHARSET` and `DB_COLLATE`. A dump written from `utf8mb4_unicode_520_ci` tables and loaded against a config expecting something else is how you get a site full of question marks in place of apostrophes.- Anything a plugin asked you to define: license keys, S3 credentials, SMTP passwords, `DISALLOW_FILE_MODS`, Redis host and port.
### The group that calls you three days later

That last group is the one that produces the "it restored but the emails stopped" call three days later.

## What four popular tools actually put in the archive
I read the source of three of these on 3 September 2026, at the versions on WordPress.org that day, rather than trusting the feature pages.

### UpdraftPlus 1.26.7, 3,000,000 active installs
The backup entities are defined in `get_backupable_file_entities()` in `class-updraftplus.php`: `plugins`, `themes`, `uploads`, `mu-plugins`, and then `others`, which is the rest of `WP_CONTENT_DIR`. Must-use plugins are their own entity, which is better than most people assume.

The default exclusions are two `define()` calls at the top of `updraftplus.php`:

`define('UPDRAFT_DEFAULT_OTHERS_EXCLUDE', 'upgrade,cache,updraft,backup*,*backups,mysql.sql,debug.log');
define('UPDRAFT_DEFAULT_UPLOADS_EXCLUDE', 'backup*,*backups,backwpup*,wp-clone,snapshots,wp-staging');`
### The uploads exclusion nobody reads

Read the uploads line carefully. Any media folder whose name starts with `backup` is excluded from your uploads backup by default.

If a client has a page of downloadable files in `/uploads/backups-2024/`, it is not in the archive, and the failure is silent.

And, from the vendor documentation quoted at the top: no `wp-config.php` and no core customisations in the free version.

### All-in-One WP Migration 7.110, 5,000,000 active installs
The export enumerates media, plugins, themes and the remainder of wp-content, plus a database dump and a `package.json` that records `SiteURL` and `HomeURL`.

Grepping the whole `lib/` directory for `wp-config` returns nothing at all, so the archive contains no copy of your config file and no core files.

Note also `class-ai1wm-export-enumerate-content.php`, which adds `mu-plugins` to the exclude filter list under a condition, so must-use plugins are an option here rather than a default entity.

Two plugins, eight million active installs between them by the WordPress.org API count on 3 September 2026, and neither archive contains your config file.

The table prefix is handled by rewriting it to the placeholder `SERVMASK_PREFIX_` on export and substituting the target prefix on import, which is why this tool moves cleanly between hosts and why the dump inside it is not a plain mysqldump you can pipe into MySQL.

### Duplicator 1.5.17, 1,000,000 active installs
Duplicator is the odd one out, and the detail is worth knowing. In `classes/package/class.pack.archive.php` it explicitly adds three files to the exclusion list:

`$this->FilterFilesAll[] = $abs_path . '/.htaccess';
$this->FilterFilesAll[] = $abs_path . '/web.config';
$this->FilterFilesAll[] = $abs_path . '/wp-config.php';`Then it stores copies of those same files separately in the package, and before doing so it runs `cleanTempWPConfArkFilePath()` in `class.pack.installer.php`, which blanks `DB_NAME`, `DB_USER`, `DB_PASSWORD` and `DB_HOST` in the stored copy.

So a Duplicator package does carry your wp-config, including your salts and your custom constants, with the four database constants emptied for the installer to fill in.

That is the most complete answer of the three, and it is also a reason to treat the package file as a secret: your salts are in there.

### Your host panel backup
Usually a filesystem snapshot plus a database dump, taken independently, at whatever moment the job ran.

The risk is not coverage, it is consistency: files written after the database dump started are in the file half of a backup whose database half predates them.

For a busy WooCommerce store that window matters. Ask your host, in writing, whether the two halves are taken from the same point in time.

![Bar chart of active installs for All-in-One WP Migration, UpdraftPlus and Duplicator, with which archives carry wp-config.php.](https://adityaarsharma.com/wp-content/uploads/2026/09/8d388f9e-b4da-4d8e-84d1-f07a3d0e392a_2912x1632-scaled.png)Built from the install counts and archive contents in this post, read 3 September 2026.
[elementor-template]

## The restore rehearsal

### The exercise, in six steps

Here is the exercise. It takes about forty minutes the first time and you should do it on a laptop, not on a server.

- Take a fresh backup with whatever tool you actually use.- Bring up an empty WordPress on Docker or Local. Do not copy anything from the live server by hand at this point. The rule is: only what is in the archive.- Load the database dump. Note the exact command you had to run and any prefix or collation errors.- Copy in the files from the archive. Nothing else.- Load the front page. Then the admin. Then a post with images. Then a form. Then the checkout, if there is one.- Write down every single thing you had to fetch from somewhere other than the archive to make it work.
### The list you end up with is the gap

That list is your real backup gap.

Based on what the three archives above actually contain, the predictable entries are the config constants, any drop-in installed by a caching or object-cache plugin, and whatever lives in the server configuration rather than in the WordPress tree.

### The same test with WP-CLI

A minimal version of the same test with WP-CLI, which is what I reach for first:

`# on the live site
wp db export live.sql --add-drop-table
wp core verify-checksums
wp plugin list --status=active --format=csv > active-plugins.csv
ls -la wp-content/*.php # the drop-ins nobody backs up
grep -E "^(define|\\$table_prefix)" wp-config.php > constants.txt
# on the blank target
wp core download --version=$(wp core version)
wp config create --dbname=test --dbuser=root --dbpass=root --dbprefix=wp_
wp db create
wp db import live.sql
wp option get siteurl
wp search-replace 'https://live.example.com' 'http://localhost:8080' --dry-run``wp core verify-checksums` is doing double duty there.

It tells you whether core is stock, which tells you whether skipping core in the backup is safe, and it is also the fastest check for modified core files if you suspect a compromise.

If it reports files that do not match, stop and read [your access logs](https://adityaarsharma.com/reading-wordpress-access-logs/) before you back anything up, because you may be about to make a clean copy of the wrong thing.

![The UpdraftPlus listing on the WordPress.org plugin directory.](https://adityaarsharma.com/wp-content/uploads/2026/09/b6f5594d-c043-4c6c-845d-acefcc4fc106_2800x2000-scaled.png)wordpress.org/plugins/updraftplus/, screenshot taken 3 September 2026.

## The parts that are not in any archive
Two things I have never seen a WordPress backup plugin capture, and both have ended restores:

- **Scheduled events that live outside WordPress.** A real system cron entry calling `wp cron event run`, or a deploy hook, or a queue worker. WP-Cron entries are in the options table and come back with the database. The crontab does not.- **The DNS and the mail path.** A restored site with the right content and the wrong SPF record sends nothing. Nothing in the archive tells you that.
### Keep a plain text file beside the archive

Keep a plain text file next to your backups listing PHP version, PHP extensions, cron entries, DNS records and the constants in wp-config. It is the least sophisticated part of a backup strategy and it saves the most time.

If you run sites for other people, this belongs in whatever you already use to track them; [how I manage WordPress sites for clients](https://adityaarsharma.com/how-to-manage-wordpress-websites-for-clients/) and [the management tool comparison](https://adityaarsharma.com/best-8-wordpress-management-tools/) both go into how I keep that record.

And the boring one that fixes a lot of this at the source: keep the site updatable so restores are rare. [Automatic updates not working](https://adityaarsharma.com/how-to-fix-wordpress-automatic-updates-not-working/) is the failure I see most on sites that later need a restore.

[elementor-template]

## Do this today
Open your backup plugin and find the last archive it made. Download it, unzip it, and search for `wp-config.php` and for `wp-content/object-cache.php`.

If either is missing, you now know one thing your restore will need from somewhere else, and you have ten minutes to write it down while you still can.

## Resources
- [What exactly does UpdraftPlus back up, TeamUpdraft documentation](https://teamupdraft.com/documentation/updraftplus/topics/backups/what-does-updraftplus-back-up/)- [Backups, WordPress Advanced Administration Handbook](https://developer.wordpress.org/advanced-administration/security/backup/)- [wp db export, WP-CLI command reference](https://developer.wordpress.org/cli/commands/db/export/)- [wp core verify-checksums, WP-CLI command reference](https://developer.wordpress.org/cli/commands/core/verify-checksums/)- [UpdraftPlus on WordPress.org](https://wordpress.org/plugins/updraftplus/)- [Duplicator on WordPress.org](https://wordpress.org/plugins/duplicator/)- [All-in-One WP Migration on WordPress.org](https://wordpress.org/plugins/all-in-one-wp-migration/)