A backup nobody has restored is a rumor. This is the shop’s method for any CMS site — Drupal, WordPress, whatever: capture all three parts, get a copy off the server, and then actually prove it. Works with nothing fancier than SSH access; adapt the commands to your setup. If some of it reads like the backups essay, good — this is that essay with its sleeves rolled up.
Know the three parts you’re capturing
A website is a database (content, users, orders), files (everything uploaded — images, PDFs), and code (the theme and customizations). “We have backups” often turns out to mean one of the three. Missing files is the classic: a restored site where every image is a broken square. All three, every time.
Dump the database
Drupal:
drush sql:dump --gzip --result-file=../backups/db-$(date +%Y-%m-%d).sql
WordPress:
wp db export backup-$(date +%Y-%m-%d).sql
Neither? Raw mysqldump does it anywhere:
mysqldump -u USER -p DATABASE | gzip > db-$(date +%Y-%m-%d).sql.gz
Archive the files
The uploads directory is the part you can’t regenerate. Drupal:
tar -czf files-$(date +%Y-%m-%d).tar.gz web/sites/default/files
WordPress:
tar -czf files-$(date +%Y-%m-%d).tar.gz wp-content/uploads
Code should already live in git — if it doesn’t, tar the whole docroot today and make “get this into version control” a very near-future project.
Get a copy off the server
If the hosting account is the thing that fails — billing lapse, account takeover, a dispute — backups stored inside it fail with it. Pull a copy down, or push to separate storage:
scp user@server:~/backups/db-2026-08-10.sql.gz ~/site-backups/
Cloud storage, a NAS, even a dated folder on your laptop that syncs somewhere — the bar is “exists outside the hosting account.” This is the 3-2-1 rule’s whole point, and it has saved every rescue it was present for.
Run the restore drill
The step everyone skips, which is why it’s the step that matters. Spin up a local environment (DDEV, Local, MAMP — anything), load the dump, unpack the files, and click around:
gunzip -c db-2026-08-10.sql.gz | mysql -u USER -p TEST_DATABASE
tar -xzf files-2026-08-10.tar.gz
You’re proving three things: the restore completes, the content is current, and the result is whole — images load, you can log in. Twenty minutes, twice a year. Checking the canoe for cracks in May beats discovering them mid-lake in July.
Put it on a schedule
A backup you take manually once is a good day, not a system. Cron the dump-and-archive, keep a rolling window (dailies for a week, weeklies for a couple of months), and calendar the restore drill twice a year. If nobody at your organization will actually own this, that’s not a character flaw — it’s just what maintenance plans are for.