Without wading too much into the Automattic + WPEngine feud it has become evident that the availability of the WordPress plugin repository that allows and facilitates plugin updates across the entire WordPress ecosystem has become a vendetta tool.
Being blocked by WordPress likely means that their systems are checking the source IP address of a web request initiated by a WordPress website when checking for available plugin and core updates. In the case of WordPress blocking all WPEngine customers from updating their plugins, they would likely have included an entire IP address block in order to accomplish this.
There could be other things happening like host header validation and perhaps even environment checking that is happening but for the purposes of this post, I thought I’d outline a few workaround options that would help you bypass these sorts of blocks even as an interim short term solution, or perhaps part of a longer term strategy if confidence in the reliability and professionalism of the people making decisions for an open source project such as WordPress is shaken.
Option 1 : Use nginx as a transparent proxy
The idea with this option is that you are either managing the web hosting environment or have similar root level access in order to facilitate a DNS change to resolve api.wordpress.org to another IP address (the destination of the transparent proxy.)
Here’s how you can configure Nginx to act as a transparent proxy for routing requests from your web host to api.wordpress.org
. The goal is to make all requests from your server destined for api.wordpress.org
pass through the Nginx proxy before reaching their final destination.
Steps to Set Up a Transparent Proxy to Route Requests to api.wordpress.org
Prerequisites
- A Linux server with Nginx installed.
- Root or sudo access to configure Nginx.
- Your server should be set up to handle outbound requests to
api.wordpress.org
. - Ensure
api.wordpress.org
is not directly accessible from your server to verify the effectiveness of the proxy (e.g., via firewalls or DNS adjustments).
Step 1: Install Nginx
If Nginx is not installed on your server, you can install it using the package manager for your Linux distribution.
For Debian/Ubuntu:
sudo apt update
sudo apt install nginx
For CentOS/RHEL:
sudo yum install nginx
Step 2: Edit Nginx Configuration
We will configure Nginx to intercept requests to api.wordpress.org
and proxy them to the actual destination.
- Navigate to the Nginx configuration directory:bashCopy code
cd /etc/nginx/sites-available/
- Create a new Nginx configuration file specifically for this proxy: For example, you can create a new file called
wordpress_proxy.conf
.bashCopy codesudo nano /etc/nginx/sites-available/wordpress_proxy.conf
- Configure the server block to intercept and forward requests to
api.wordpress.org
:In this configuration, any request that comes to this server forapi.wordpress.org
will be forwarded transparently to the realapi.wordpress.org
endpoint.Example configuration:nginxCopy codeserver { listen 80; server_name api.wordpress.org; # Proxy settings location / { proxy_pass https://api.wordpress.org; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # Additional headers can be added here if needed for SSL or other purposes } }
Key points:proxy_pass https://api.wordpress.org;
: This directive tells Nginx to forward the requests to the actualapi.wordpress.org
domain over HTTPS.proxy_set_header Host $host;
: Passes the original host header so thatapi.wordpress.org
knows it was the intended host.proxy_set_header X-Real-IP $remote_addr;
: Passes the original client’s IP address toapi.wordpress.org
.proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
: Forwards the original client’s IP address through any proxies.proxy_set_header X-Forwarded-Proto $scheme;
: Passes the original protocol (HTTP/HTTPS).
- Save the file and exit (Ctrl+O, Enter, Ctrl+X in nano).
Step 3: Enable the Proxy Configuration
If you’re using the /sites-available
and /sites-enabled
structure, you need to enable this configuration by creating a symbolic link:
sudo ln -s /etc/nginx/sites-available/wordpress_proxy.conf /etc/nginx/sites-enabled/
Step 4: Test the Nginx Configuration
Before reloading or restarting Nginx, check if the configuration is valid:
sudo nginx -t
If the test is successful, you should see a message indicating that the configuration is valid.
Step 5: Restart Nginx
After configuring the proxy, restart Nginx to apply the changes:
sudo systemctl restart nginx
Step 6: Update the /etc/hosts
File (Optional but Recommended for Testing)
To ensure your server routes all requests for api.wordpress.org
through the Nginx proxy (instead of directly reaching the destination), you can modify the /etc/hosts
file to resolve api.wordpress.org
to the local server’s IP.
Edit the /etc/hosts
file:
sudo nano /etc/hosts
Add the following line, replacing YOUR_SERVER_IP
with your actual server’s IP address where Nginx is running:
YOUR_SERVER_IP api.wordpress.org
This forces your server to resolve api.wordpress.org
to the Nginx proxy server instead of directly reaching the real API endpoint.
Step 7: Verify the Proxy is Working
To verify the setup, try making requests to api.wordpress.org
using curl
or another HTTP client:
curl http://api.wordpress.org
You should see the response from api.wordpress.org
, but it will have gone through your Nginx proxy first.
Optional: Set Up HTTPS for the Proxy
To make the proxy more secure, you may want to set up SSL on your Nginx proxy so that it accepts HTTPS requests. You can use Let’s Encrypt to obtain a free SSL certificate for api.wordpress.org
on your proxy server:
- Install Certbot:
sudo apt install certbot python3-certbot-nginx
- Obtain and install the SSL certificate:
sudo certbot --nginx -d api.wordpress.org
Certbot will automatically configure your Nginx server to use HTTPS.
Conclusion
With this configuration, your Nginx server acts as a transparent proxy that intercepts all requests to api.wordpress.org
and forwards them to the real api.wordpress.org
server. This setup is useful in situations where you want to control or log the traffic going to specific external destinations, or route traffic through a specific gateway.
It should be worth noting that the nginx proxy can live on a cloud provider such as AWS. If this is the case then you can utilize VPC -> ELB routing of requests to truly have access to a vast array of IP addresses to avoid future blocks.
Option 2: Redirect WordPress Update Requests to Another Hostname with a custom WordPress plugin
In this approach, you modify WordPress’s core functionality by intercepting update requests that normally go to api.wordpress.org
and redirecting them to another server that mirrors the same functionality. You can achieve this by creating a custom plugin.
Steps for Creating a Custom Plugin to Redirect Updates:
- Create a Custom Plugin: Inside your WordPress installation, create a new folder in
wp-content/plugins/
calledcustom-update-redirect
. Inside this folder, create a file calledcustom-update-redirect.php
. - Edit the Plugin File: Add the following code to the file, which will intercept and modify the API request for plugin updates:
<?php
/*
Plugin Name: Custom Update Redirect
Description: Redirect WordPress plugin updates to a custom update server.
Version: 1.0
Author: Your Name
*/
// Hook into the update request filter to modify the update API endpoint
add_filter('pre_http_request', 'redirect_plugin_updates', 10, 3);
function redirect_plugin_updates($pre, $parsed_args, $url) {
// Check if the request is going to the WordPress plugin update API
if (strpos($url, 'https://api.wordpress.org/plugins/update-check/1.1/') !== false) {
// Redirect the update request to your custom update server
$custom_update_url = 'https://your-custom-update-server.com/plugins/update-check/1.1/';
$url = $custom_update_url;
}
// Allow the request to proceed with the modified URL
return array(
'url' => $url,
'method' => $parsed_args['method'],
'body' => $parsed_args['body'],
'headers' => $parsed_args['headers'],
'timeout' => $parsed_args['timeout'],
'redirection' => $parsed_args['redirection'],
'httpversion' => $parsed_args['httpversion'],
'user-agent' => $parsed_args['user-agent'],
);
} - Explanation of the Code:
- The
add_filter('pre_http_request', ...)
hook intercepts outgoing HTTP requests before they are sent. - The
strpos($url, 'https://api.wordpress.org/plugins/update-check/1.1/')
checks if the request is destined for the WordPress plugin update API. - If the update URL is detected, the request is redirected to a custom update server (in this case,
https://your-custom-update-server.com/
). - This will only work if the custom server is capable of responding with update information in the expected format.
- The
- Activate the Plugin: After saving the file, go to your WordPress admin dashboard, navigate to Plugins, and activate the Custom Update Redirect plugin.
- Custom Update Server Requirements:
- The custom server that you point the update requests to must replicate the functionality of
api.wordpress.org
for plugin updates. - This server must return valid responses to plugin update requests in a format that WordPress expects, including plugin version information and download URLs.
- The custom server that you point the update requests to must replicate the functionality of
Drawbacks:
- Setting up a custom server to mimic
api.wordpress.org
is a complex task, as WordPress requires specific responses in terms of plugin updates. - You will have to regularly update the server with new plugin versions manually or set up automation to pull updates from another source.
Option 3: Use a Private Plugin Repository
An alternative method is to set up a private plugin repository, which you control. You can host your plugins in this repository and have WordPress retrieve updates from this custom repository instead of api.wordpress.org
.
Steps for Creating a Private Plugin Repository:
- Set Up a Private Plugin Repository:
- Create a private repository for your plugins on a web server you control. The repository should host
.zip
files for each plugin version and provide metadata (such as the plugin version and description).
- Create a private repository for your plugins on a web server you control. The repository should host
- Modify the WordPress Plugin Update Check:
- You can hook into WordPress’s plugin update check process and point it to your private repository instead of
api.wordpress.org
. This is done by using thesite_transient_update_plugins
filter to modify the update response for specific plugins.
- You can hook into WordPress’s plugin update check process and point it to your private repository instead of
- Example Plugin for Private Repository: Create a new plugin that modifies the update endpoint for your private plugins:
<?php
/*
Plugin Name: Private Plugin Updates
Description: Use a custom plugin repository for updates.
Version: 1.0
Author: Your Name
*/
// Hook into plugin update check
add_filter('pre_set_site_transient_update_plugins', 'check_for_private_plugin_update');
function check_for_private_plugin_update($transient) {
if (empty($transient->checked)) {
return $transient;
}
// Define your private plugin details $plugin_slug = 'your-plugin-slug/your-plugin-file.php'; $repository_url = 'https://your-private-repo.com/plugin-info.json'; // Fetch update information from your private repository $response = wp_remote_get($repository_url); if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) == 200) { $plugin_info = json_decode(wp_remote_retrieve_body($response)); // Check if a new version is available if (version_compare($plugin_info->version, $transient->checked[$plugin_slug], '>')) { $transient->response[$plugin_slug] = (object) array( 'slug' => $plugin_slug, 'new_version' => $plugin_info->version, 'url' => $plugin_info->homepage, 'package' => $plugin_info->download_link, ); } } return $transient;
} - Explanation of the Code:
- The
pre_set_site_transient_update_plugins
hook modifies the update check process for plugins. - It fetches update information from your private repository (
$repository_url
). - If a new version is available, it tells WordPress to display the update.
- The
- Plugin Info File (
plugin-info.json
): You need to host aplugin-info.json
file in your private repository, containing information about your plugin updates:{
"version": "1.2.0",
"homepage": "https://your-private-repo.com",
"download_link": "https://your-private-repo.com/plugins/your-plugin.zip"
} - Activate the Custom Plugin: After saving and activating the custom plugin in WordPress, your private plugins will receive updates from your private repository instead of
api.wordpress.org
.
Conclusion:
This approach works well if you control or have access to the plugin repository, and it allows you to bypass the api.wordpress.org
server by routing updates through a private or alternative repository.
All of these options offer potential solutions to api.wordpress.org
blocking your hosting provider, though the third option (private plugin repository) is generally more sustainable and avoids the complexity of mimicking the WordPress API.