How to manage many WordPress sites: updates, backups, security
Ten WordPress sites are a hobby; fifty are a job. Here is a repeatable routine for keeping a whole fleet updated and secure: wp-cli instead of clicking, a safe update order, a backup before every change, and the plugin hygiene that prevents most hacks.
Managing three WordPress sites is easy: you log in to each dashboard, click "Update all", and move on. Somewhere between ten and fifty sites that routine falls apart. Updates pile up, one client's site breaks after a plugin release and you only hear about it from their customers, and a forgotten install with a two-year-old slider plugin quietly becomes a spam relay. The fix is not working harder; it is a repeatable routine that treats your sites as a fleet instead of fifty separate chores. Here is the routine that holds up in practice.
Why WordPress fleets get out of hand
- Updates are frequent and uneven. Core ships minor security releases several times a year, and an average site carries 15 to 30 plugins, each on its own release schedule. Multiply that by your site count and there is something to update almost every day.
- Most compromises come from plugins, not core. Year after year, the overwhelming majority of WordPress vulnerabilities disclosed are in plugins and themes. The site that gets hacked is usually the one nobody has looked at in months.
- Dashboards do not scale. Logging in to fifty admin panels is slow, it is easy to skip one, and you get no single view of what is outdated where.
Use wp-cli, not the dashboard
wp-cli is the official command-line tool for WordPress, and it is the single biggest time saver for anyone managing more than a handful of sites. Every routine task becomes a command you can script:
# What version is core on, and is there an update?
wp core version
wp core check-update
# Which plugins and themes are outdated?
wp plugin list --update=available --fields=name,version,update_version
wp theme list --update=available
# Update one plugin, or everything
wp plugin update woocommerce
wp plugin update --all
wp theme update --all
wp core update
wp core update-db
Two rules make wp-cli safe on a multi-site server:
- Run it as the site's user, never as root. If each site has its own Linux user (it should), run
sudo -u siteuser wp --path=/var/www/siteuser/public_html .... Running as root means files written by an update end up owned by root, which breaks the next update and the site's own uploads. wp-cli even refuses to run as root unless you add--allow-root, and there is a good reason for that warning. - Always pass
--path. In a loop over many sites, an explicit path guarantees each command hits the site you meant.
With that in place, an inventory of your whole fleet is a short loop:
for dir in /var/www/*/public_html; do
user=$(stat -c %U "$dir")
[ -f "$dir/wp-config.php" ] || continue
echo "== $dir"
sudo -u "$user" wp --path="$dir" plugin list --update=available --format=csv
done
Run that weekly and you know exactly where the risk sits before you touch anything.
The safe update order
Updating everything at once on every site at the same time is how a bad release takes down twenty clients in one afternoon. A calmer order:
- Back up first. Files and database, every time (more on this below).
- Update plugins before core when a major core release lands, so plugins that add compatibility for the new core are already in place. For routine minor releases the order matters less, but keep it consistent.
- Update themes last, and never edit a theme you also update; put customisations in a child theme.
- Run
wp core update-dbafter a core update so database migrations do not wait for the next admin login. - Check the site. At minimum, fetch the home page and one inner page and look at the HTTP status and the PHP error log. A white screen that nobody notices for a day is worse than one you catch in thirty seconds.
Stagger by risk. Update your own low-traffic sites first, wait a day, then roll out to client sites. For high-traffic shops, test on a copy before production.
Back up before every update, and store it elsewhere
An update without a backup is a gamble. Make the backup part of the update command, not a separate habit:
wp db export /var/backups/siteuser/before-update-$(date +%F).sql
tar -czf /var/backups/siteuser/files-$(date +%F).tar.gz -C /var/www/siteuser public_html
Then apply the basic rules of backups that actually save you:
- Off the server. A backup on the same disk dies with the disk or the attacker. Push a copy to S3-compatible storage or another machine. (We covered this in detail in encrypted website backups to S3.)
- Retention, not just one copy. Keep several generations. Malware that went unnoticed for a week also lives in last night's backup.
- Test a restore every so often. A backup you have never restored is a hope, not a backup.
Plugin hygiene: the cheapest security you will ever buy
- Delete what you do not use. Deactivated plugins still sit on disk and can still be exploited if their files are directly reachable.
wp plugin list --status=inactive, thenwp plugin delete. - Prefer fewer, maintained plugins. A plugin with no update in two years, or one that was removed from the wordpress.org directory, is a liability. Replace it.
- Never install nulled plugins or themes. "Free" copies of premium plugins are one of the most common ways backdoors get onto WordPress sites.
- Lock down file editing. Add
define('DISALLOW_FILE_EDIT', true);towp-config.phpso a stolen admin login cannot be turned into PHP code execution through the theme editor. - Isolate sites from each other. One Linux user and one PHP-FPM pool per site, so a compromise on one site cannot read the next one's files or database credentials. (See hosting multiple client sites on one VPS.)
- Scan regularly. Run a malware scanner such as ClamAV over each site's files on a schedule, not only after something looks wrong.
Common traps
- Auto-updating everything blindly. WordPress background updates for minor core releases are sensible. Auto-updating every plugin on every client shop with no backup and no check is not.
- Forgetting
update-db. After some core and WooCommerce updates the site works but the database upgrade is pending, and the next admin to log in triggers it at a random moment. - Shared users across sites. If all sites run as
www-data, one vulnerable plugin exposes every site on the server. - Backups on the same server. Ransomware and disk failure do not care that you had a backup folder.
- No inventory. You cannot patch what you do not know exists. Keep a list of every install, its owner and its plugins.
How ShadowPanel takes the busywork out
ShadowPanel is a self-hosted hosting control panel, and on the Pro and Agency plans it covers the routine above without giving up the isolation rules:
- WordPress Toolkit. Each WordPress site gets a view that detects the install and lists the core version, available core update, and every plugin and theme with its installed and available version. You can update core, a single plugin or theme, or all plugins or themes at once, and the panel shows you the wp-cli output.
- Runs as the site user. Behind the scenes it uses wp-cli as the site's own Linux user, never as root, with the target path checked against that user's home directory. Updated files keep the correct owner.
- Backups before changes. On-demand backups of files and databases are available on every plan; Pro and Agency add scheduled automatic backups (daily, weekly or monthly) uploaded to S3-compatible storage or an SFTP server, with a retention count you choose and an email if a run fails. Archives can be GPG-encrypted with AES-256.
- Malware scans. Pro and Agency can run a full-site ClamAV scan from the panel, optionally moving infected files to quarantine, with the scan history kept per site and a notification when it finishes.
- Isolation by default. Every site has its own Linux user and its own PHP-FPM pool with
open_basedir, so one outdated plugin stays one site's problem.
The bottom line
Fifty WordPress sites stay healthy when the work is routine: inventory with wp-cli, back up off-site before every change, update in a consistent order, check the result, and remove plugins you do not need. None of it is difficult; it just has to happen every week, for every site. ShadowPanel puts the inventory, the updates, the scheduled backups and the malware scans in one place, while keeping each site sealed off from the others.
curl -fsSL https://shadowpanel.de/install.sh | bash
Related articles
How to set up a staging site for WordPress and Laravel
Testing changes on the live site works until the day it does not. A proper staging environment is a copy you can break s...
SPF, DKIM and DMARC: stop your server's email going to spam
Your contact form works, but the messages land in spam, or never arrive at all. Mailbox providers judge mail on proof of...
Security advisory: critical PHP vulnerabilities CVE-2026-109618 and CVE-2026-109619
Two critical, unauthenticated remote code execution flaws in PHP core were disclosed on 21 October 2026. Every server th...