If you manage WordPress sites for clients, you know the drill.
Every month, you log into each site, click "Update All Plugins," wait, check if anything broke, run a backup, scan for issues, repeat. For one site it's fine. For eight sites it's 6 hours of your life gone - every single month.
I finally got annoyed enough to fix this properly.
What manual WordPress maintenance actually costs
Here's the math I was doing before I automated:
- 8 client sites
- ~45 minutes per site (login, updates, backup verification, security check, client email)
- = 6 hours/month
- At $65/hour = $390/month of non-billable time
That's $4,680/year. For clicking update buttons.
The automation stack
I settled on two tools: WP-CLI (runs WordPress commands from the terminal) and SSH (connects to client servers remotely). Both are free, both are standard.
The workflow per site:
- SSH into client server
- Database backup (before touching anything)
wp core updatewp plugin update --allwp theme update --all- Security audit
- Generate HTML report
Here's a simplified version of the core script:
`ash
!/bin/bash
WP_PATH="/var/www/html/client-site"
BACKUP_DIR="/backups"
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M")
1. Backup first
mkdir -p ""
wp --path="" --allow-root db export \
"/db_backup_.sql"
2. Update everything
wp --path="" --allow-root core update
wp --path="" --allow-root plugin update --all
wp --path="" --allow-root theme update --all
3. Flush cache
wp --path="" --allow-root cache flush
`
Simple. But the real value is running this across all client sites from a single config file.
The config approach
I keep a clients.json file:
json
{
"clients": [
{
"name": "Client A Ltd",
"slug": "client_a",
"ssh_host": "server.clienta.com",
"ssh_user": "root",
"ssh_key": "~/.ssh/id_rsa_clienta",
"wp_path": "/var/www/html/clienta",
"active": true
}
]
}
One command runs maintenance across every active client. Add a new client - edit one JSON file.
The security audit
After updates, the script checks:
`ash
Check for exposed debug.log
if [ -f "/wp-content/debug.log" ]; then
echo "WARNING: debug.log exists - may contain sensitive data"
fi
Check wp-config.php permissions
CONFIG_PERMS=$(stat -c "%a" "/wp-config.php")
if [[ ! "" =~ ^(400|440|600|640)$ ]]; then
echo "WARNING: wp-config.php permissions: (should be 600)"
fi
World-writable PHP files
WRITABLE=$(find "" -name "*.php" -perm /o+w 2>/dev/null | wc -l)
if [ "" -gt 0 ]; then
echo "WARNING: world-writable PHP files found"
fi
`
Each client gets flagged items in their report.
The HTML report
The script generates a per-client HTML report:
? WordPress 6.5.3 - up to date
? 12 plugins updated
? Database backup: 45 MB
? Security scan: clean
? wp-config.php permissions: 644 (should be 600)
I email this to clients monthly. It shows them the value of what I'm doing.
The uptime monitor
Separate script, runs every 10 minutes via cron:
`ash
!/bin/bash
SITES=("https://client1.com" "https://client2.com")
ALERT_EMAIL="you@yourcompany.com"
for SITE in "${SITES[@]}"; do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 15 "")
if [ "" != "200" ]; then
echo "DOWN: (HTTP )" | mail -s "SITE DOWN: " ""
fi
done
`
Results
After running this for 6 months:
- Monthly maintenance time: 6 hours ? ~20 minutes
- Zero missed updates
- Caught 2 sites with world-writable PHP files
- One client site went down at 3am - got the alert, fixed it before they noticed
The full toolkit
I packaged everything - the bulk update script (Bash + PowerShell), security audit, uptime monitor, clients.json template, HTML report template, and maintenance checklist.
WordPress Agency Automation Bundle - use code DEVTO for 20% off.
Or use the snippets above as a starting point. Either way, stop clicking "Update All" manually eight times a month.
Questions about the implementation? Drop them in the comments.
More in this series
- I automated WordPress maintenance across 8 client sites
- How I land WordPress maintenance clients with cold email
- WordPress site running slow? 30-minute diagnosis checklist
- The WordPress maintenance business: real numbers and pricing
- WooCommerce maintenance: 8 checks that keep payments alive
All tools: devautomation.gumroad.com
Top comments (0)