This is the worst hour in the job, and it is survivable more often than it feels. Work from the newest copy backwards, and do not overwrite anything while you are trying.

First: do not touch the original

cp backup.tar.gz /srv/work/backup-copy.tar.gz

Every recovery attempt below is destructive somewhere. Work on a copy, always, so a failed attempt costs nothing.

If gzip refuses

gzip -t backup.tar.gz                 # what is wrong\nzcat backup.tar.gz > partial.tar 2>/dev/null || true\ntar -xf partial.tar --ignore-zeros --warning=no-timestamp

A truncated gzip still decompresses everything up to the damage. On an alphabetically ordered archive that is often most of the site.

If a SQL dump will not import

zcat db.sql.gz | head -50            # is the header there\nzcat db.sql.gz | tail -5            # does it end with "Dump completed"\n\n# import ignoring the failures, then see what arrived\nzcat db.sql.gz | mysql --force restore_test\nmysql restore_test -e "SHOW TABLES"

--force keeps going past a broken statement. A dump cut off mid-table restores every table before it, and often that is the one you needed.

Then look for other copies

  • The provider's own snapshots, which are separate from yours.
  • A staging server, which is a slightly older copy of production.
  • A developer laptop with a recent dump on it.
  • The application's own exports - an order CSV is worth more than nothing.

Afterwards, so it does not happen twice

A backup is verified or it is a hope. Test the archive on every run and restore one on a schedule - see testing a restore and reading a failed backup log. And keep more than one, in more than one place: why one backup is not a backup.