This project proposes and documents a comprehensive solution for creating and managing local mirrors of WordPress core, plugins, and themes. This is crucial for users in regions experiencing frequent internet disconnections, global routing limitations, or censorship, ensuring continuous operation and maintainability of WordPress websites.
While WordPress.org cannot host mirrors for every region, this project provides the blueprint, tooling, and documentation for communities and hosting providers to build and maintain their own reliable WordPress mirrors.
In many regions, particularly Iran, prolonged internet outages (lasting weeks or months) are common due to political or infrastructural reasons. This prevents users from accessing essential WordPress resources:
- Core updates (
wordpress.org/latest.zip) - Plugin and theme downloads (from
wordpress.org/plugins/andwordpress.org/themes/) - API metadata (
api.wordpress.org) for checks and installations - Translation files
This renders WordPress websites unmanageable during these periods, impacting businesses, developers, and the entire digital ecosystem reliant on WordPress.
This project outlines a replicable system that allows any entity to host a local mirror of WordPress resources. The core idea is to:
- Mirror WordPress.org: Periodically download and store WordPress core, plugins, themes, and related metadata.
- Provide Local Access: Serve these resources via a local HTTP server.
- Enable Fallback: Configure WordPress installations to use the local mirror automatically when official servers are unreachable.
The proposed system consists of three main layers:
This layer is responsible for storing the mirrored files. It should mimic the structure of WordPress.org as closely as possible for compatibility.
- Storage: Local file system, object storage (e.g., S3-compatible), or any HTTP-accessible server.
- Directory Structure Example:
/var/www/wp-mirror/ βββ core/ β βββ latest.zip β βββ versions/ β βββ 6.5.2.zip β βββ 6.5.3.zip βββ plugins/ β βββ akismet/ β β βββ versions/ β β βββ 5.8.0.zip β βββ woocommerce/ β β βββ versions/ β β βββ 8.9.0.zip β βββ ... βββ themes/ β βββ twentytwentyfour/ β β βββ versions/ β β βββ 1.3.zip β βββ ... βββ translations/ β βββ en_US/ β β βββ core-2024-04-B.json β βββ fa_IR/ β βββ ... βββ api-cache/ # For API metadata responses βββ plugins/info/slug=woocommerce.json
This layer handles fetching updates from WordPress.org and populating the Mirror Repository.
- Tools:
wp-cli: Highly recommended. Custom commands or scripts can automate downloads and syncs.rsync/wget: For basic file transfer and mirroring.- Custom Python/Bash scripts: For more advanced logic, API calls, and error handling.
- Synchronization Strategy:
- Scheduled Tasks: Use
cron(Linux) or Task Scheduler (Windows) to run sync scripts daily or hourly. - Delta Sync: Only download changed files or new versions to save bandwidth and time.
- API Mirroring: Cache responses from
api.wordpress.orgfor plugins/themes info, translations, etc.
- Scheduled Tasks: Use
- Suggested
wp-clicommands (conceptual):wp mirror init --path=/var/www/wp-mirror wp mirror sync --core --plugins --themes --translations --api --path=/var/www/wp-mirror wp mirror status --path=/var/www/wp-mirror
This layer involves configuring WordPress installations to use the local mirror.
- Configuration:
wp-config.php: Define constants to point WordPress to the local mirror.// Example for a local mirror running on the same server define('WP_MIRROR_BASE_URL', 'http://localhost:8080'); // Or 'http://wp-mirror.local' if using hosts file/DNS define('WP_USE_MIRROR', true); // Optional: Define specific mirror base URLs if needed // define('WP_CORE_MIRROR_URL', 'http://localhost:8080/core'); // define('WP_PLUGINS_MIRROR_URL', 'http://localhost:8080/plugins'); // define('WP_THEMES_MIRROR_URL', 'http://localhost:8080/themes');
- Network Configuration:
hostsfile: Manually mapapi.wordpress.organddownloads.wordpress.orgto127.0.0.1(or the mirror server's IP).- DNS Server: Configure a local DNS server to resolve WordPress.org domains to the mirror IP.
- Reverse Proxy: Use Nginx, Traefik, or Apache as a reverse proxy that intercepts requests and redirects them to the local mirror when the internet is down.
- WordPress Hooks:
- The
pre_http_requestfilter can be used to intercept and redirect HTTP requests. - A custom function can check internet connectivity (e.g., via
fsockopenor a simplecurlcheck toapi.wordpress.org). If offline, it can enable mirror mode. - Example PHP snippet (to be placed in a must-use plugin or theme's
functions.php):function wp_mirror_check_and_redirect( $preempt, $r, $url ) { // Check if WP_USE_MIRROR is defined and true, or if we are offline if ( ! defined('WP_USE_MIRROR') || ! WP_USE_MIRROR ) { // If we want automatic detection, add connectivity check here // if (!wp_is_online()) { define('WP_USE_MIRROR', true); } else { return $preempt; } return $preempt; // Not using mirror or not offline } $mirror_base = defined('WP_MIRROR_BASE_URL') ? WP_MIRROR_BASE_URL : 'http://wp-mirror.local'; // Redirect core requests if ( strpos($url, 'wordpress.org/latest.zip') !== false || strpos($url, 'wordpress.org/wp-includes/version.json') !== false ) { $r['url'] = str_replace('https://wordpress.org', $mirror_base . '/core', $url); // Important: Ensure HTTPS is handled or switched to HTTP if mirror is HTTP $r['sslverify'] = false; // Or handle SSL properly $r['headers']['Host'] = parse_url( 'https://wordpress.org', PHP_URL_HOST ); // Pass original host header if needed return $r; } // Redirect plugin/theme requests if ( strpos($url, 'wordpress.org/plugins/') !== false || strpos($url, 'wordpress.org/themes/') !== false ) { $r['url'] = str_replace('https://downloads.wordpress.org', $mirror_base . '/plugins', $url); // Adjust /plugins/ or /themes/ path as needed $r['sslverify'] = false; $r['headers']['Host'] = parse_url( 'https://downloads.wordpress.org', PHP_URL_HOST ); return $r; } // Redirect API requests (e.g., for plugin/theme info) if ( strpos($url, 'api.wordpress.org') !== false ) { $r['url'] = str_replace('https://api.wordpress.org', $mirror_base . '/api', $url); // Assuming your mirror has an /api endpoint for cached responses $r['sslverify'] = false; $r['headers']['Host'] = parse_url( 'https://api.wordpress.org', PHP_URL_HOST ); return $r; } return $preempt; // Let WordPress handle the request normally } // Add filter only if WP_USE_MIRROR is defined and true if (defined('WP_USE_MIRROR') && WP_USE_MIRROR) { add_filter('pre_http_request', 'wp_mirror_check_and_redirect', 10, 3); } // Optional: Function to check online status function wp_is_online( $host = 'api.wordpress.org', $port = 80, $timeout = 5 ) { $fp = @fsockopen( $host, $port, $errno, $errstr, $timeout ); if ( !$fp ) { return false; } fclose( $fp ); return true; }
- The
- Server Environment:
- Docker +
docker-compose: Ideal for containerizing the mirror server, sync scripts, and proxy. - Linux Server: Ubuntu, Debian, or CentOS are suitable.
- Docker +
- Mirror Server Software:
- Nginx: As a high-performance web server and reverse proxy.
- Apache: Alternative web server.
- Simple HTTP Server: Python's
http.serverfor testing or very basic setups.
- Synchronization Tools:
wp-cli: Essential for managing WordPress.rsync: For efficient file synchronization.wget: For downloading files.cron/systemd timers: For scheduling synchronization tasks.
- Caching:
- Redis: For caching API responses or transient data.
- SQLite: Could potentially store metadata if performance is not critical.
The total size of free WordPress resources is substantial:
- WordPress Core: ~50-100 MB per release.
- Plugins: Tens of thousands of plugins, each averaging 5-20 MB. Total estimated: ~300 GB - 600 GB.
- Themes: Thousands of free themes, averaging 5-15 MB. Total estimated: ~100 GB - 200 GB.
- Translations: Relatively small, likely a few GBs.
Total Estimated Mirror Size: ~450 GB to 1 TB+ (This is a rough estimate and can fluctuate).
Recommendation: Start by mirroring essential plugins and themes, then expand as needed.
- Fork this repository.
- Set up a local mirror based on the documentation.
- Test the synchronization and provide feedback.
- Contribute
wp-clicommands or synchronization scripts. - Improve the PHP integration code and documentation.
- Share your experience and findings.
This project is intended to complement the WordPress open-source philosophy. All documentation and proposed code snippets are provided under a permissive license (e.g., MIT or GPLv2, aligning with WordPress).
This repository is a proposal and design documentation, not a ready-to-run production implementation.
Real-world implementation is non-trivial: it requires careful work across WordPress update flows (core + plugins + themes), security/verification of mirrored artifacts, robust fallback logic, and long-term maintenance of the sync/repository formats.
To make this truly βofficialβ and reliable, it would need collaboration with the WordPress core team (and likely WP-CLI/Infrastructure stakeholders) to align with upstream architecture, compatibility guarantees, and security expectations.