Automate WordPress backups with a Linux bash script

Automated backups are the single most important safety net for any WordPress site, yet many site owners rely solely on hosting-provider snapshots that may not restore cleanly or may not run frequently enough. Writing your own bash backup script gives you full control: you choose what to back up, how often, where to store it, and how long to keep old copies. A complete WordPress backup consists of two parts — the file system (core, themes, plugins, uploads) and the database — and both are equally important. The script below compresses the files with tar and dumps the database with mysqldump, then stores both archives in a timestamped folder. You can schedule it with a cron job to run every night at 2 AM. Storing backups on the same server as your site is better than nothing, but off-site storage (an S3 bucket, a remote server via rsync, or a mounted network share) is strongly recommended. If you are new to Linux commands, the essential Linux commands guide covers the basics of navigation, permissions, and SSH that you will need. For SSH key setup and remote server access, review the Git and SSH commands guide. The script uses variables at the top so you can adapt it to any WordPress installation with minimal edits. After setting it up, always do a test restore in a staging environment to confirm the backups are actually usable.

Problem: You want a reliable, automated backup of your WordPress files and database without depending on hosting snapshots or paid plugins.

Solution: Create the file /usr/local/bin/wp_backup.sh with the following content, then add it to cron:

#!/bin/bash
# ─── WordPress Backup Script ───────────────────────────────────────────────
# Usage: bash /usr/local/bin/wp_backup.sh
# Schedule: crontab -e  →  0 2 * * * bash /usr/local/bin/wp_backup.sh

# ── Configuration ──────────────────────────────────────────────────────────
WP_ROOT="/var/www/html"          # Absolute path to WordPress root
BACKUP_DIR="/backups/wordpress"  # Destination directory for archives
DB_NAME="your_db_name"
DB_USER="your_db_user"
DB_PASS="your_db_password"
KEEP_DAYS=14                     # Delete backups older than N days
# ───────────────────────────────────────────────────────────────────────────

TIMESTAMP=$(date +"%Y-%m-%d_%H-%M")
DEST="${BACKUP_DIR}/${TIMESTAMP}"
mkdir -p "$DEST"

echo "[$(date)] Starting WordPress backup..."

# 1. Dump the database
mysqldump -u"$DB_USER" -p"$DB_PASS" "$DB_NAME"   --single-transaction   --quick   | gzip > "${DEST}/db_${TIMESTAMP}.sql.gz"

echo "[$(date)] Database dump complete."

# 2. Archive WordPress files (exclude cache and log directories)
tar -czf "${DEST}/files_${TIMESTAMP}.tar.gz"   --exclude="${WP_ROOT}/wp-content/cache"   --exclude="${WP_ROOT}/wp-content/upgrade"   "$WP_ROOT"

echo "[$(date)] File archive complete."

# 3. Delete old backups
find "$BACKUP_DIR" -maxdepth 1 -type d -mtime +${KEEP_DAYS} -exec rm -rf {} \;

echo "[$(date)] Backup finished. Stored in: $DEST"

NOTE: Avoid storing the database password in plain text inside a script that is world-readable. Either restrict permissions with chmod 700 /usr/local/bin/wp_backup.sh and chown root:root, or use a MySQL option file (~/.my.cnf) with a [mysqldump] section so the credentials never appear on the command line. If your hosting provider supports it, pipe the backup directly to an S3-compatible bucket using the AWS CLI (aws s3 cp ...) instead of writing to local disk first.