Skip to content

raphaelsuzuki/wordpress-scheduled-updates

Repository files navigation

WordPress Scheduled Updates

Automated WordPress Sites Update Script. Save time and reduce security risks scheduling updates at the best time for your sites, including core, plugin, and theme updates.

Overview

  1. Site Discovery: Finds all WordPress installations in the configured root directory (typically /var/www/).
  2. Pre-update Health Check: Runs basic health checks using wp-cli before updates.
  3. Core Update: Updates WordPress core if an update is available.
  4. Plugin Update: Updates plugins, skipping any listed in .wp-exclude-plugins for per-site exclusions.
  5. Theme & Language Update: Updates themes and language packs.
  6. Post-update Health Check: Verifies site health after updates.
  7. Rollback: If a plugin update fails or breaks the site, attempts rollback using wp-cli.
  8. Logging: Logs all actions and errors per site and to a central error log.
  9. Notifications: Sends email alerts for failures and rollbacks.
  10. Cache Flush: Flushes site caches after updates.

Requirements

  • wp-cli.
  • curl.
  • jq: The script relies on jq for parsing JSON data. If jq fails to parse the JSON data, the script may not function as expected. Ensure jq is installed and working correctly.
  • [Optional] Mail sending configured (for notifications).

Limitations

  • No backups performed (ensure you have a backup solution).
  • Plugin rollback only works for plugins in the WordPress.org repository. If a plugin rollback fails, it may leave the site in an unstable state. Ensure you have a backup solution in place to restore the site if a rollback fails.
  • No visual regression or browser testing.

Process per site

  1. Initial health check: Confirms the site is stable BEFORE any updates.
  2. Core & DB Updates: Updates WordPress core and its database.
  3. Plugin Updates:
    • Checks for available updates for each plugin.
    • Excludes plugins specified in the configuration of each site (e.g., /var/www/domain.com/.wp-exclude-plugins).
    • Updates one plugin at a time.
    • Performs a health check after each plugin update.
    • If health check fails OR update fails, automatically rolls back the plugin to its previous version.
    • Sends an email notification upon rollback (your server must be configured to send emails).
    • Continues to the next plugin, even if one failed.
  4. Theme & Language Updates: Updates all themes and language files.
  5. Cache Clearing: Flushes WordPress object and plugin caches.

Usage

  1. Place the script and configuration file in a secure location:

    sudo cp wordpress-scheduled-updates.sh /usr/local/bin/
    sudo cp wordpress-scheduled-updates.conf /etc/
  2. Make the script executable and set the ownership to www-data:

    sudo chmod +x /usr/local/bin/wordpress-scheduled-updates.sh
    sudo chown www-data:www-data /usr/local/bin/wordpress-scheduled-updates.sh
    sudo chown www-data:www-data /etc/wordpress-scheduled-updates.conf
    # If you are using a custom config file path, be sure set appropriate permissions to it
    # sudo chown www-data:www-data /usr/local/bin/wordpress-scheduled-updates.conf
  3. Create the log directory with appropriate permissions:

    sudo mkdir -p /var/log/wordpress-scheduled-updates
    sudo chown www-data:adm /var/log/wordpress-scheduled-updates
    sudo chmod 750 /var/log/wordpress-scheduled-updates
  4. Set up a cron job (recommended as www-data user):

    sudo crontab -u www-data -e

    Then add something like the example below, which schedules a task to run everyday at 3:00 AM:

    # Using automatic config detection (/etc/ then script directory)
    0 3 * * * /usr/local/bin/wordpress-scheduled-updates.sh >> /var/log/wordpress-scheduled-updates/cron.log 2>&1
    
    # Using custom config file
    0 3 * * * /usr/local/bin/wordpress-scheduled-updates.sh /path/to/custom.conf >> /var/log/wordpress-scheduled-updates/cron.log 2>&1
    

    The script will execute at that time, and its output (including errors) will be appended to /var/log/wordpress-scheduled-updates/cron.log.

  5. (Optional) Exclude specific plugins from updates by creating a .wp-exclude-plugins file in each site directory:

    # Example: Exclude plugins for example.com
    sudo nano /var/www/example.com/.wp-exclude-plugins

    Add plugin names (one per line):

    woocommerce
    classic-editor
    # This is a comment - lines starting with # are ignored
    custom-plugin-name
    

Configuration

The script uses sensible defaults and can optionally load settings from a configuration file. Configuration files are loaded in this priority order:

  1. Custom config file: Pass any config file path as the first argument to the script
  2. System config file: /etc/wordpress-scheduled-updates.conf (checked automatically if no argument provided)
  3. Script directory config: wordpress-scheduled-updates.conf in the same directory as the script
  4. Built-in defaults: Used if no config file is found

Create and edit the configuration file to customize the behavior:

  • Site root: Change SITES_ROOT if your WordPress sites are not in /var/www/.
  • Log directory: Set LOG_DIR for log storage.
  • Email notifications: Set NOTIFY_EMAIL to your address (leave empty to disable notifications).
  • Expected user: Set EXPECTED_USER to match your web server user.
  • Excluded sites: Add site names to EXCLUDED_SITES array.
  • Included sites: Set INCLUDED_SITES to process only specific sites (overrides EXCLUDED_SITES).
  • Skip smoke tests: Set DISABLE_URL_CHECKS=true to skip HTTP homepage checks (useful for under-construction or private sites).
  • Per-site plugin exclusions: Create a .wp-exclude-plugins file in a site's directory, listing plugin names to skip.
  • Site-specific configs: Create individual config files like example.com.conf with INCLUDED_SITES="example.com" for single-site updates.

Log Management

The script uses a two-tiered logging approach:

  • A main cron log file that captures the stdout and stderr of the entire script run. This is what you see in the cron job command.

  • A directory of per-site logs where the script writes detailed, timestamped logs for each WordPress installation it processes. This is what's configured by the $LOG_DIR variable.

You can use logrotate for automatic log rotation. Add the following lines to /etc/logrotate.d/wordpress-scheduled-updates:

Log Rotate

# Logrotate configuration for scheduled WordPress updates
# This handles the main cron log and all per-site logs

/var/log/wordpress-scheduled-updates/*.log {
    daily
    rotate 14
    compress
    missingok
    notifempty
    create 640 www-data adm
    postrotate
        /bin/killall -HUP syslogd
    endscript
}

Safety

Test in a non-production environment before deploying!

Troubleshooting

  • wp-cli not found: Ensure wp-cli is installed and in the user's PATH.
  • Permission errors: Run the script as a user with access to all site directories (typically www-data).
  • Email not sent: Check your mail configuration and logs for errors.
  • Log file not created: Verify that $LOG_DIR exists and is writable.

Roadmap

  • Implement a manual rollback feature that is independent of wpcli and could be used with any plugin.

Contributing

Pull requests and suggestions are welcome! Please open issues for bugs or feature requests.

License

MIT License. See LICENSE for details.

Disclaimer

This repository and its documentation were created with the assistance of AI. While efforts have been made to ensure accuracy and completeness, no guarantee is provided. Use at your own risk. Always test in a safe environment before deploying to production.

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages