How to Build an Offline Backup You Can Restore Without Internet
An offline website backup strategy is a plan for keeping a copy of your site and database that you can restore when the host, the cloud provider, or your internet connection is unavailable. The core idea is simple: you own a self contained archive on hardware you control, and you have practiced restoring it without asking anyone else for help.
Most people who think they have backups actually have a copy sitting on the same provider that runs the site. That covers a deleted file or a bad deploy. It does not cover an account suspension, a billing dispute, a provider outage, or a network problem on your end. An offline copy is the one that survives all of those, because restoring it depends on nothing but your own equipment.
What an offline website backup actually contains
Two things have to travel together: the files and the database. The files are the document root, plus any uploads, plus configuration that lives outside the web root, such as the web server virtual host and the TLS material. The database is the content, the users, the settings, and often the plugin state. Backing up one without the other gives you a site that loads but is empty, or a database with no code to run it.
Export the database in a form that restores without the original server. For MySQL or MariaDB that means mysqldump with options that avoid locking surprises and keep the dump portable:
mysqldump --single-transaction --routines --triggers \
--default-character-set=utf8mb4 \
-u backup_user -p mydatabase > mydatabase.sql
The --single-transaction flag gives you a consistent snapshot on transactional tables without taking the whole database down. --routines and --triggers keep stored procedures and triggers, which are easy to forget and painful to reconstruct. The character set flag matters because a dump restored under a different default can mangle text.
For the files, use an archive tool that preserves permissions, ownership, and symlinks, and that you can list and extract years from now without a proprietary client. tar is the safe default:
tar --create --gzip --file site-files.tar.gz \
--exclude='./cache' --exclude='./tmp' \
-C /var/www ./mysite
Excluding cache and temp directories keeps the archive small and avoids restoring stale generated content. Write down the exact command you used, because the exclusions are part of the backup's meaning and you will not remember them later.
Moving the archive off the machine
An archive on the same disk as the site is not a backup. Get it onto separate hardware. The classic approach is rsync over SSH to a machine you own, or to a removable drive you physically carry. If you use a remote path, keep the transfer resumable and verifiable, because large archives over a flaky link will fail partway and you want to know that rather than discover it at restore time.
Cold storage is the stronger version of this. A copy on a drive that is powered off and stored somewhere else is immune to ransomware that encrypts mounted filesystems, and immune to a provider wiping your account. Rotate two drives so one is always off site and the other is current. Label them with the date and the site name, because in an emergency you will not want to mount drives to find out which is which.
Whatever medium you choose, the archive should be self describing. Include a plain text file next to the tarball listing the database name, the document root, the command used to dump, and the software versions involved. If the restore happens months later, that note is worth more than the archive itself.
Verifying an offline website backup before you need it
An unverified backup is a guess. Verification has three levels, and you should do all three. First, check the archive is readable and complete by listing it:
tar --list --file site-files.tar.gz | head
gzip --test mydatabase.sql.gz
Second, restore into a scratch environment. A local virtual machine or a container is enough. Import the database into a fresh server and point a throwaway web server at the extracted files. If the site comes up and the content is there, the backup is real. This step is where you discover missing uploads, wrong file ownership, or a dump that referenced a storage engine your new server does not have.
Third, record how long the restore took and what broke. That timing tells you your realistic recovery window, and the failures tell you what to fix in the next backup run.
Keeping it current without babysitting it
Automate the capture, but keep the storage step deliberate. A cron job that dumps the database and tars the files is fine. The part worth thinking about is rotation: keep several generations, not just the latest, because corruption can be present in the most recent copy and absent in an older one. A simple scheme is a dated filename per run, with the oldest pruned after a fixed count.
Encrypt the archive before it leaves the machine if it will sit anywhere you do not fully control. gpg with a key you hold is the usual choice, and it means a stolen drive or a misconfigured bucket does not hand over your database. Store the key separately from the archive, or the encryption is just a longer way to lose your data.
Finally, test the restore path on a schedule, not once. A backup you have never restored from is a hypothesis. The only way to turn it into a fact is to do the restore, on hardware you own, with the network unplugged.
Start small this week: pick one site, run the two commands above, copy the output to a drive you can unplug, and write the restore steps on paper. Then restore it once into a scratch machine. Once that works, add the second site, then the rotation, then the encryption. The goal is not a clever pipeline. It is a copy you can rebuild from when nothing else is reachable.
