At RunCloud, our mission is to provide you with the most powerful and flexible server management platform possible. For many, this means enjoying the simplicity and clarity of our dashboard, which provides a streamlined interface for deploying, managing, and securing your applications with just a few clicks.

But what if you need more?

What if you manage dozens of web applications and need to apply a single change across all of them?

This is where RunCloud’s API becomes useful. The dashboard provides convenience, but the API provides control and automation. The API makes it easy to create scripts that automate repetitive tasks and manage your infrastructure at scale.

For example, you might need to:

  • Increase the PHP memory_limit for all sites.
  • Switch all your apps from development to production mode for a major launch.
  • Disable a specific set of PHP functions to tighten security.
  • Update the open_basedir path on all your apps to grant access to a shared resource, such as when you followed our guide on using GeoLite2 with RunCloud.

Performing these tasks manually is tedious and prone to error. With the script below, you can do it all in seconds.

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.

Prerequisites

  • Python 3 installed
  • A valid RunCloud API Token
  • Your Server ID

Step 1: Setting Up Your Script

Before you can use the provided script, you need to configure it with a few key pieces of information. This tells the script which server to target, how to authenticate, and what changes to make.

(i) Set Your Server ID

First, you need to tell the script which server you want to modify. When viewing a server in the RunCloud dashboard, you can find the SERVER_ID in your browser’s address bar.

https://manage.runcloud.io/servers/123456/summary

Open the Python script and replace “123456” with your actual Server ID.

SERVER_ID = 123456

(ii) Add Your Authentication String

To communicate securely with the API, you need to provide your credentials. You can generate an API Key and a Secret or Bearer Token from your RunCloud account settings. For detailed instructions, see our documentation on Generating API Keys and Enabling API Access.

Once you have your credentials, replace the placeholder text in the auth_string variable.

(iii) Customize Your Web App Settings

Next, you need to define the changes you want to apply. In this script, we have created a WEBAPP_SETTINGS_PAYLOAD object that is a template for your new settings. You can modify any value here to suit your needs.

For a complete list of all available settings and their possible values, please refer to the official documentation: “Update PHP-FPM, NGINX settings”.

# Define the settings you want to apply to all web applications.
WEBAPP_SETTINGS_PAYLOAD = {
   "stackMode": "production",
   "clickjackingProtection": True,
   "xssProtection": True,
   "mimeSniffingProtection": True,
   "memoryLimit": 512,
   "postMaxSize": 256,
   "uploadMaxFilesize": 256,
   # ... and any other settings you wish to change
}

Tip: Handling App-Specific Settings

Some settings, like openBasedir, vary between apps.

To handle this, create a modified copy of WEBAPP_SETTINGS_PAYLOAD per app.

Step 2: Running the Script

With your script configured, you’re ready to execute it. Follow these simple steps to update all your web applications at once.

(i) Save the Script to Your Computer

First, copy the entire Python script from the section below, paste it into a text editor, and save it as a file on your computer. We recommend naming it something easy to remember, like update_runcloud_apps.py.

import http.client
import json
import sys
# --- Configuration ---
RUNCLOUD_API_HOST = "manage.runcloud.io"
# IMPORTANT: Replace None with your actual Server ID (as an integer or string).
# You can find this in your server's URL in the RunCloud dashboard.
SERVER_ID = 123456  # Replace with your actual Server ID
# IMPORTANT: Replace with your actual Bearer Token from your RunCloud API settings.
auth_string = 'See RunCloud API documentation for generating API credentials. (https://runcloud.io/docs/generating-api-keys-enabling-api-access)'
# Define the settings you want to apply to all web applications.
# For detailed list, view RunCloud documentation at https://runcloud.io/docs/api/v3/api-8617100 
WEBAPP_SETTINGS_PAYLOAD = {
   "stackMode": "development", # Can be "production" or "development"
   "timezone": "UTC",
   "disableFunctions": "getmyuid,passthru,leak,listen,diskfreespace,tmpfile,link,ignore_user_abort,shell_exec,dl,set_time_limit,exec,system,highlight_file,source,show_source,fpassthru,virtual,posix_ctermid,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix,_getppid,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_times,posix_ttyname,posix_uname,proc_open,proc_close,proc_nice,proc_terminate,escapeshellcmd,ini_alter,popen,pcntl_exec,socket_accept,socket_bind,socket_clear_error,socket_close,socket_connect,symlink,posix_geteuid,ini_alter,socket_listen,socket_create_listen,socket_read,socket_create_pair,stream_socket_server",
   "maxExecutionTime": 30,
   "maxInputTime": 60,
   "maxInputVars": 1000,
   "memoryLimit": 256,
   "postMaxSize": 256,
   "uploadMaxFilesize": 256,
   "sessionGcMaxlifetime": 1440,
   "allowUrlFopen": True
}


AUTH_HEADER = {"Authorization": f"Bearer {auth_string}", "user-agent": "My Python App"}


# --- Helper Function for API Requests ---
def make_api_request(method, path, payload=None, extra_headers=None):
    conn = None # Initialize conn to None
    try:
        conn = http.client.HTTPSConnection(RUNCLOUD_API_HOST)
        
        # Prepare headers
        headers = AUTH_HEADER.copy() # Start with base auth headers
        if extra_headers:
            headers.update(extra_headers)
        # Ensure Content-Type is set for requests with a payload
        if payload and 'Content-Type' not in headers:
            headers['Content-Type'] = 'application/json'
            
        # Prepare payload
        body = json.dumps(payload) if payload else b''
        
        conn.request(method, path, body=body, headers=headers)
        
        res = conn.getresponse()
        status = res.status
        data = res.read()
        response_body_str = data.decode("utf-8")
        
        # Try to parse JSON, but return raw string if not JSON or if error
        try:
            response_json = json.loads(response_body_str)
            return status, response_json
        except json.JSONDecodeError:
            print(f"     Warning: Response was not valid JSON.")
            print(f"     Raw Response Body: {response_body_str[:200]}...") # Print start of body
            if 200 <= status < 300:
                 return status, {"raw_response": response_body_str} 
            else:
                return status, {"error": "Invalid JSON response", "details": response_body_str}


    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 update_nginx_settings():
    print(f"\nFetching all web applications for Server ID: {SERVER_ID}...")
    list_apps_path = f"/api/v3/servers/{SERVER_ID}/webapps"
    status, response = make_api_request("GET", list_apps_path)


    if not status or status >= 400:
        print(f"[Error] Failed to fetch web applications. Status: {status}")
        print(f"       Response: {response}")
        sys.exit(1)
    
    webapps_list = response.get('data', [])
    if not webapps_list:
        print("No web applications found on this server. Exiting.")
        sys.exit(0)
    
    print(f"Found {len(webapps_list)} web application(s).")
    print("\n--- Starting update process ---")
    # --- 4. Loop Through and Update Each Web Application ---
    for app in webapps_list:
        app_id = app['id']
        app_name = app['name']
        
        print(f"\nUpdating settings for '{app_name}' (ID: {app_id})...")
        
        update_path = f"/api/v3/servers/{SERVER_ID}/webapps/{app_id}/settings/fpmnginx"
                
        status, response = make_api_request("PATCH", update_path, payload=WEBAPP_SETTINGS_PAYLOAD)
        
        if status and 200 <= status < 300:
            print(f"  [SUCCESS] Successfully updated settings for '{app_name}'.")
        else:
            print(f"  [FAILURE] Failed to update settings for '{app_name}'. Status: {status}")
            print(f"            Response: {json.dumps(response, indent=2)}")


    print("\n--- Script finished. ---")


update_nginx_settings()

(ii) Open Your Terminal

Next, you need to open a command-line interface.

  • On macOS or Linux, this is called Terminal.
  • On Windows, you can use Command Prompt or PowerShell.

(iii) Navigate to the Script’s Location

Use the cd (change directory) command in your terminal to navigate to the folder where you saved the script. For example, if you saved it in a Scripts folder on your Desktop, you would type the following and press Enter:

cd Desktop/Scripts

(iv) Execute the Script

Now, run the script by typing ‘python’ followed by the name of your file and pressing Enter.

python update_runcloud_apps.py

(Note: You must have Python 3 installed on your system for this command to work.)

(v): Review the Output

Once you run the command, the script will start making API requests and provide real-time feedback directly in your terminal.

Behind the scenes, the script first makes a GET API call to fetch a list of all web applications on your specified server. Then, it will loop through each app and send a PATCH API request to apply the exact settings you defined in the WEBAPP_SETTINGS_PAYLOAD.

You should see an output similar to this:    

You’ve transformed a potentially long and repetitive task into an automated, error-free process in a few simple steps.

How are you using the RunCloud API? Have you built a cool script or found a unique way to automate your workflow? Share your projects, ask questions, and connect with fellow RunCloud users on our community channels.

We can’t wait to see what you build.