首页 > Technology > 正文

How to Set Up Automatic Backups on Your Linux VPS

fenij 2026-07-31 7 Technology

You know that feeling when a database table gets corrupted at 2 AM and you realize the last manual backup was three weeks ago? I have been there. The fix is not buying a fancy backup service — it is a 15-minute cron job that runs while you sleep. Here is the setup I use on every VPS I manage.

Back up the database first

If you run MySQL or MariaDB, mysqldump is all you need. Create a small script at /usr/local/bin/db-backup.sh:

#!/bin/bash
DATE=$(date +%Y%m%d-%H%M)
mysqldump -u backup_user -p'YOUR_PASSWORD' --single-transaction --routines --triggers my_database > /backups/db-$DATE.sql
gzip /backups/db-$DATE.sql
find /backups -name 'db-*.sql.gz' -mtime +7 -delete

The --single-transaction flag gives you a consistent snapshot without locking tables, which matters if your app writes to the database during backup. The last line deletes copies older than 7 days so the disk does not fill up silently. Make the script executable: chmod +x /usr/local/bin/db-backup.sh.

Back up the files

For website files, rsync to a separate location works well. Add this to the same script or a second one:

rsync -a --delete /var/www/html/ /backups/www/
tar czf /backups/www-$(date +%Y%m%d).tar.gz -C /backups www
find /backups -name 'www-*.tar.gz' -mtime +7 -delete

The --delete flag removes files in the backup that no longer exist in the source. This keeps the backup mirror in sync. If you want to keep deleted files for a grace period, drop --delete and rely on the tar archives instead.

Schedule it with cron

Open the root crontab: crontab -e. Add two lines:

0 3 * * * /usr/local/bin/db-backup.sh
30 3 * * * /usr/local/bin/file-backup.sh

Database at 3 AM, files at 3:30. Staggering them avoids disk I/O contention on small VPS instances. If your server runs in a different timezone than your users, pick a slot when traffic is low.

Copy backups off-site

Local backups on the same VPS are better than nothing, but if the provider has a hardware failure, both your data and your backups are gone. Push a copy to object storage with rclone:

rclone copy /backups/db-*.sql.gz remote:my-bucket/backups/ --min-age 1h
rclone copy /backups/www-*.tar.gz remote:my-bucket/backups/ --min-age 1h

Add these to the cron as well, or append them to the backup scripts. Most S3-compatible storage charges cents per gigabyte — a week of database dumps is probably under 50 MB.

Test the restore

A backup you have never restored is a wish, not a backup. Once a month, spin up a test VPS, copy the latest dump over, and run:

gunzip < db-latest.sql.gz | mysql -u root -p my_database

If the import finishes without errors and your app connects, the backup works. This test takes five minutes and saves you from discovering a broken dump during an actual emergency.

Common mistakes

Putting the database password directly in the script is not ideal — use a .my.cnf file with 600 permissions instead. Forgetting to test the restore is the most common one. Another: cron runs with a minimal PATH, so always use full paths to binaries like /usr/bin/mysqldump and /bin/gzip.

For more server maintenance guides, visit fenij.com.

FAQ

Q: How much disk space do I need for backups?
A: Check the size of one database dump and one file archive, then multiply by the retention days. A typical WordPress database dump is 5-50 MB; site files can be 100 MB to several GB.

Q: Should I use Borg or restic instead?
A: Both are excellent for deduplicated, encrypted backups. If you are comfortable with the command line, Borg with a remote repo is a strong choice. The rsync + tar approach above is simpler and has zero dependencies.

Q: What if my VPS provider offers automated snapshots?
A: Use them as a safety net, but do not rely on them alone. Provider snapshots are whole-disk images — you cannot extract a single file from them easily. A database dump lets you restore one table in seconds.

Q: How often should backups run?
A: Daily is the minimum for most sites. If your database changes frequently, run the database dump every 6 hours and keep 2-day retention.