Managing multiple WordPress sites often means repeating the same performance tweaks over and over. RunCloud allows you to speed up this configuration task through its powerful and flexible API.

One of the most impactful automations is enabling server-side caching across your applications. RunCloud not only automates the installation of high-performance caching solutions like nginx FastCGI Cache and Redis but also configures them with good, secure settings out of the box.

When you enable Redis, for example, RunCloud can handle the complex setup of Redis ACLs (Access Control Lists), ensuring your cache is not only fast but also properly secured from unauthorized access. This is an important step that is often overlooked in manual setups.

We’ve developed the following Python script to make this process even easier.

Here’s how it works:

  1. Our script securely connects to your account and fetches all servers under your management.
  2. For each server, it automatically queries and finds all of your WordPress applications.
  3. It installs and activates RunCloud Hub using your chosen cache settings.
  4. The script is intelligent. If it discovers a site where RunCloud Hub is installed and active, it will notify you and move on to the next application.

By running this single script, you can enable optimized, server-level caching across dozens or even hundreds of WordPress sites in minutes.

Please note that access to the RunCloud API is an exclusive feature available on our Business and Enterprise subscriptions. This is because API keys are generated and managed within a Workspace, which is designed for team collaboration and advanced project management. By centralizing API key creation within a Workspace, we provide greater security, organizational control, and the ability to manage access for your entire team. To use the API and unlock these capabilities, you will need to upgrade your account to a plan that includes Workspaces.

Warning for OpenLiteSpeed Users

Please be aware that this script and the RunCloud Hub feature are incompatible with servers running the OpenLiteSpeed (OLS) web stack.

RunCloud Hub supports nginx FastCGI Cache and Redis. OpenLiteSpeed uses a separate system, LiteSpeed Cache (LSCache), so the Hub won’t work on OLS servers.

For any WordPress site hosted on an OpenLiteSpeed server, you must use the official LiteSpeed Cache plugin within your WordPress dashboard. Attempting to run this script against web applications on an OpenLiteSpeed server will result in an error, as the API will reject the request to install a feature incompatible with the server’s stack.

Python Script

import http.client
import json
import time


# --- Configuration ---
RUNCLOUD_API_HOST = "manage.runcloud.io"


# IMPORTANT: Replace with your actual Bearer Token from your RunCloud API settings.
auth_string = 'PLEASE_REPLACE_WITH_YOUR_RUNCLOUD_API_BEARER_TOKEN'


# --- RunCloud Hub Installation Configuration ---
# These settings will be applied to every WordPress site where the Hub is installed.
RUNCLOUD_HUB_PAYLOAD = {
   "cacheType": "native",
   "redisObjectCache": False,
   "cacheFolderSize": 50,    # 50 MB
   "cacheValidMinute": 480  # 8 hours
}


# --- Internal Setup (Do not change) ---
AUTH_HEADER = {
    "Authorization": f"Bearer {auth_string}",
    "Accept": "application/json",
    "user-agent": "RunCloud Hub Installer Script"
}


# --- Helper Function for API Requests ---
def make_api_request(method, path, payload_dict=None, extra_headers=None):
    conn = None
    try:
        conn = http.client.HTTPSConnection(RUNCLOUD_API_HOST)
        
        headers = AUTH_HEADER.copy()
        if extra_headers:
            headers.update(extra_headers)
        
        body_bytes = None
        if payload_dict:
            headers['Content-Type'] = 'application/json'
            body_bytes = json.dumps(payload_dict).encode('utf-8')
        else:
            body_bytes = b''
        conn.request(method, path, body=body_bytes, headers=headers)        
        res = conn.getresponse()
        status = res.status
        response_body_str = res.read().decode("utf-8")        
        try:
            response_json = json.loads(response_body_str)
            return status, response_json
        except json.JSONDecodeError:
            print(f"     [Warning] Response from {method} {path} was not valid JSON (Status: {status}).")
            print(f"     Raw Response Body (first 200 chars): {response_body_str[:200]}...")
            if 200 <= status < 300: # Success, but not JSON (e.g., 204 No Content)
                 return status, {"raw_response": response_body_str, "message": "Successful but non-JSON response"}
            else: # Error and not JSON
                return status, {"error": "Invalid JSON response", "details": response_body_str, "message": "Error with non-JSON response"}




    except http.client.HTTPException as e:
        print(f"[Error] HTTP Exception during {method} {path}: {e}")
        return None, {"error": "HTTP Exception", "details": str(e)}
    except ConnectionError as e:
        print(f"[Error] Connection Error during {method} {path}: {e}")
        return None, {"error": "Connection Error", "details": str(e)}
    except Exception as e:
        print(f"[Error] Unexpected error during {method} {path}: {e}")
        return None, {"error": "Unexpected Error", "details": str(e)}
    finally:
        if conn:
            conn.close()




def install_hub_on_all_wordpress_sites():
    """
    Main function to orchestrate the installation of RunCloud Hub.
    """
    # 1. Get all servers
    print("Fetching list of servers...")
    status, servers_response = make_api_request("GET", "/api/v3/servers")
    
    if not (status and 200 <= status < 300):
        print(f"[FATAL] Could not fetch servers. API responded with status {status}.")
        print(f"       Details: {servers_response.get('message', 'No message')}")
        return


    servers = servers_response.get('data', [])
    if not servers:
        print("No servers found in your RunCloud account.")
        return
        
    print(f"Found {len(servers)} server(s). Starting process...")




    # 2. Iterate through each server
    for server in servers:
        server_id = server['id']
        server_name = server['name']
        print(f"\n--- Processing Server: {server_name} (ID: {server_id}) ---")
        
        current_page = 1
        # 3. Paginate through WordPress web apps on the current server
        while True:
            print(f"   Fetching WordPress sites (Page {current_page})...")
            path = f"/api/v3/servers/{server_id}/webapps?type=wordpress&page={current_page}"
            status, webapps_response = make_api_request("GET", path)




            if not (status and 200 <= status < 300):
                print(f"   [Error] Could not fetch web apps for server {server_name}. Skipping this server.")
                print(f"           Details: {webapps_response.get('message', 'No message')}")
                break # Move to the next server




            webapps = webapps_response.get('data', [])
            if not webapps:
                print("   No more WordPress sites found on this server.")
                break # Exit the pagination loop for this server




            # 4. Iterate through each web app on the current page
            for webapp in webapps:
                webapp_id = webapp['id']
                webapp_name = webapp['name']
                print(f"   -> Found WordPress site: {webapp_name} (ID: {webapp_id})")
                
                # 5. Install RunCloud Hub
                print(f"      - Installing RunCloud Hub...")
                install_path = f"/api/v3/servers/{server_id}/webapps/{webapp_id}/runcloudhub"
                status, install_response = make_api_request("POST", install_path, payload_dict=RUNCLOUD_HUB_PAYLOAD)


                if 200 <= status < 300:
                    print(f"      - SUCCESS: RunCloud Hub installed on '{webapp_name}'.")
                else:
                    error_msg = install_response.get('message', 'Unknown error.')
                    print(f"      - FAILED: Could not install Hub for '{webapp_name}'. Status: {status}, Error: {error_msg}")
                time.sleep(2) # Add sleep to avoid rate limiting


            current_page += 1
    print("\n--- Installation finished ---")




install_hub_on_all_wordpress_sites()

How to Use the Script

  1. Save the Code: Save the code above into a file named main.py.
  2. Get Your API Token:
    • Log in to your RunCloud account.
    • Go to Settings -> API.
    • Create a new API Key if you don’t have one. Give it a descriptive name like “For Installer Script”.
    • Copy the generated Bearer Token.
  3. Configure the Script:
    • Open the above Python script in a text editor.
    • Find the line: auth_string = "PLEASE_REPLACE_WITH_YOUR_RUNCLOUD_API_BEARER_TOKEN"
    • Replace the placeholder text with the actual Bearer Token you copied.
    • Adjust the settings inside the RUNCLOUD_HUB_PAYLOAD dictionary to change the default cache size, type, or duration. The defaults provided are a sensible starting point.
  4. Run the Script:
    • You need Python 3 installed on your local machine (not on the server).
    • Open your terminal or command prompt.
    • Navigate to the directory where you saved the file.
    • Execute the script using the command:
python3 install_rc_hub.py
  1. Monitor the Output: The script will print its progress, showing which server and WordPress sites it is processing. It will tell you if an installation request was successful or failed.

The RunCloud Hub is now active and caching your WordPress sites. Pages are served from a high-performance cache, improving load times and user experience.

However, effective cache management is more than just flipping a switch.

For better results, especially on dynamic or e-commerce sites, check the following resources:

This script is just one example of the power and efficiency the RunCloud API offers. We are constantly inspired by the innovative ways our users manage their infrastructure, and we encourage you to share your #BuildWithRunCloud story.

How are you using the RunCloud API to streamline your server management workflow?

Share your scripts, ideas, and success stories with the RunCloud community.