On a VPS, you don’t need a plugin to back up WordPress. A short shell script can dump the database, archive the files, keep a rotation, and send copies off-site, running from cron outside PHP. That makes it faster, more reliable on large sites, and it works even when WordPress itself is broken.

Prefer a plugin? See WordPress backup plugins compared.

What to back up

Part Where Why
Database MySQL/MariaDB Posts, pages, settings, users, orders
wp-content/ Site directory Uploads, themes, plugins
wp-config.php Site root Database credentials, salts, settings
Server config (optional) /etc/nginx/sites-available/…, PHP pool Faster rebuilds

WordPress core files can be downloaded again, but backing up the whole site directory is simple and small enough for most sites.

1. Dump the database

With WP-CLI (reads credentials from wp-config.php):

cd /var/www/example.com
wp db export /backups/example-db-$(date +%F).sql --allow-root

Or with mysqldump:

mysqldump --single-transaction --quick --no-tablespaces \
  -u wpuser -p'secret' wordpress | gzip > /backups/example-db-$(date +%F).sql.gz

--single-transaction gives a consistent snapshot of InnoDB tables without locking the site. Avoid passwords on the command line in scripts: use a ~/.my.cnf file with chmod 600 instead. See mysqldump and WP-CLI guide.

2. Archive the files

tar --exclude='wp-content/cache' --exclude='wp-content/updraft' \
    -czf /backups/example-files-$(date +%F).tar.gz -C /var/www example.com

3. A complete backup script

#!/bin/bash
# /usr/local/bin/wp-backup.sh
set -euo pipefail

SITE=example.com
WEBROOT=/var/www/$SITE
DEST=/backups/$SITE
KEEP_DAYS=14
STAMP=$(date +%F-%H%M)

mkdir -p "$DEST"
cd "$WEBROOT"

# database (credentials from wp-config.php via WP-CLI)
sudo -u www-data wp db export - | gzip > "$DEST/db-$STAMP.sql.gz"

# files
tar --exclude='wp-content/cache' -czf "$DEST/files-$STAMP.tar.gz" -C /var/www "$SITE"

# local retention
find "$DEST" -type f -mtime +$KEEP_DAYS -delete

echo "Backup done: $STAMP"
sudo chmod 700 /usr/local/bin/wp-backup.sh
sudo mkdir -p /backups && sudo chmod 700 /backups

4. Schedule it with cron

sudo crontab -e
30 3 * * * /usr/local/bin/wp-backup.sh >> /var/log/wp-backup.log 2>&1

See crontab guide.

5. Send it off-site

A backup on the same VPS isn’t enough. Options:

  • rsync over SSH to another server (for example a storage VPS):
rsync -az --delete /backups/ [email protected]:/srv/backups/web1/
  • rclone to S3-compatible storage (Backblaze B2, Wasabi, AWS S3, MinIO):
rclone copy /backups remote:my-bucket/web1 --min-age 1m
  • restic or Borg: deduplicated, encrypted, versioned backups. That’s ideal for keeping months of history cheaply.

Add the off-site step to the end of the script. See rsync examples, off-site VPS backups, and storage VPS.

6. Restore

# files
sudo tar -xzf files-2026-10-01-0330.tar.gz -C /var/www
sudo chown -R www-data:www-data /var/www/example.com

# database
gunzip -c db-2026-10-01-0330.sql.gz | sudo -u www-data wp db import - --path=/var/www/example.com

If you restore to a different domain, run a search-replace afterwards. See change the WordPress site URL.

Test a restore on a staging site every few months. See WordPress staging site.

Monitoring

  • Check the log, or send yourself a message on failure (|| curl to a webhook, or a healthcheck service such as Healthchecks.io or Uptime Kuma push monitors). See Uptime Kuma.
  • Watch disk space in /backups. See disk full troubleshooting.

Quick reference

Task Command
DB dump (WP-CLI) wp db export - | gzip > db.sql.gz
DB dump (mysqldump) mysqldump --single-transaction db | gzip
Files tar -czf files.tar.gz -C /var/www example.com
Schedule cron, 30 3 * * *
Off-site rsync / rclone / restic
Restore DB gunzip -c db.sql.gz | wp db import -

Related: WordPress backup plugins and WordPress VPS hosting.

  • WordPress
  • Backup
  • Linux