The quickest way to back up and restore a Linux server
Today, the PHP team disclosed two critical vulnerabilities that can allow unauthenticated remote code execution. The highest risk is mod_php, where an exploit can run before application code even starts.
A good percentage of the internet experienced some downtime as sysadmins figured out how to deal with the risk as quickly as possible.
Before you upgrade anything important, or hell, because you're a responsible system administrator and you know that data lost will eventually happen, you should have a strategy in place to ensure you don't have to reconstruct your server one configuration file at a time and lose out on ungodly amounts of sleep and money.
Amid the mad rush this morning, a colleague asked me what I did to guard against this eventuality. Because I'm me, I do not trust a hosting provider to keep my data safe, and I would rather as much control as possible over my own snapshots. My answer is a couple shell scripts that I wrote years ago. the simpler the better, and these haven't failed me yet.
I figured I would post these scripts online in case someone found them useful, or came across this post and thought "huh I should have backups."
The backup Script
This script connects as root over SSH, dumps every MySQL and PostgreSQL database it finds, then streams the server's root filesystem into a compressed archive on my home server. It will work just as well streaming back to a harddrive connected to your machine.
Download backup-server.sh, make it executable, and pass it the address of the server:
chmod +x backup-server.sh
./backup-server.sh 192.0.2.10
The archive is created on the computer where you run the script. I did it this way so that you do not need to worry about whether you have enough free space on the server to hold a second copy of itself.
You may want to do a quick search for "--exclude" and add any other directories that you don't want getting copied into your backup.
The restore script
My restore script expects a fresh Ubuntu server running the same Ubuntu release and CPU architecture as the backup. Just in case, it checks both before doing something potentially distructive. Then it will ask you to type the server address, preserve the new machine's network, boot, SSH host key, and machine identity files, then stream the archive back over SSH.
As before, you want to make this one executable:
chmod +x restore-server.sh
./restore-server.sh backup-192.0.2.10-2026-10-21.tar.gz 192.0.2.20
It will restore MySQL and PostgreSQL from the dumps stored in the backup. When it finishes, it reboots the server.
If you can, you should keep the old server around until you have checked the sites, databases, cron jobs, mail, and anything else that is mission critical on the replacement.
A few notes
These scripts make assumptions that I am OK with, but you might not be. Please read these before you use either one:
- The restore script is written for Debian and Ubuntu. Restoring a filesystem over a different distribution or Ubuntu release is a creative way to make an unbootable machine.
--one-file-systemskips separately mounted filesystems. If/home,/var, a Docker volume, or application data is present on another mount, back it up separately.- MySQL and PostgreSQL get proper logical dumps. SQLite databases, Docker volumes, mail stores, and other stateful applications do not. Stop those services first, use their own backup tools, or accept that their files may be captured halfway through a write.
- The archive contains passwords, private keys, environment files, and whatever other secrets are on the server. Encrypt it, store it somewhere sensible, and do not leave the only copy beside the machine it protects.
gzip -tproves that the compressed stream is intact. It does not prove that the backup contains what you meant to save. A restore test is the only useful proof.- A disconnect, full local disk, or failed database dump aborts the backup. Do not keep a partial archive.
- GNU tar does not preserve every extended attribute or access control list with these options. If your setup depends on file capabilities, ACLs, or SELinux labels, add the appropriate tar flags and test the result.
- The script uses root SSH access. If your server disables direct root login, connect with another account and arrange passwordless
sudo, adjust the script, or temporarily give root a random password. I do the latter, though I acknowledge that it is risky. - Two backups of the same server on the same day use the same filename. Rename the first one or add the time to
outbefore taking another.
There are fancier backup systems out there. But if you want something dirty that just works, this might be it.
I hope they help someone. Here's to peace of mind!