Back to articles
Technology Insight

Scaling Automation Testing: Building a Headless Chrome Cluster with Selenoid on VPS

May 30, 2026

Introduction to Modern Testing Infrastructure Challenges

In the era of continuous integration and continuous deployment (CI/CD), software development velocities have reached unprecedented speeds. However, traditional QA processes often bottleneck these pipelines due to slow, brittle, and unscalable automated testing environments. Running sequential UI tests can take hours, delaying deployments and exhausting engineering resources.

To overcome this, modern DevOps and QA teams must pivot toward parallel test execution. The challenge then shifts from writing test scripts to infrastructure orchestration. Local selenium grids or heavy virtual machine setups are notoriously difficult to maintain, consume massive amounts of RAM, and frequently suffer from configuration drift. This is where a Headless Chrome Cluster managed by Selenoid on a Virtual Private Server (VPS) emerges as an enterprise-grade, cost-effective solution.

Why Choose Selenoid for Large-Scale Automation?

Selenoid is a powerful, lightweight implementation of the Selenium hub protocol that utilizes Docker containers to launch browsers. Unlike the traditional Java-based Selenium Grid, Selenoid provides several distinct advantages for large-scale operations:

  • Speed and Efficiency: Written in Go, Selenoid is incredibly fast and consumes minimal CPU and memory overhead compared to traditional Java hubs.
  • Isolated Environments: Every single test session runs in a fresh, isolated Docker container. This guarantees zero interference between parallel tests and eliminates configuration drift.
  • Automated Lifecycle Management: Selenoid automatically spins up a container when a session is requested and terminates it immediately upon completion, freeing up server resources instantly.
  • Advanced Features: Out-of-the-box support for video recording, VNC live viewing, and seamless logging makes debugging failed tests straightforward.

By pairing Selenoid with Headless Chrome—where the browser runs without a graphical user interface—we can squeeze maximum performance out of VPS hardware, allowing dozens of concurrent browser sessions to run smoothly on modest specifications.

Prerequisites and Infrastructure Planning

Before diving into the configuration, ensure your VPS meets the foundational requirements for hosting a production-grade cluster. Browser testing is heavily dependent on RAM and CPU cores. As a general rule of thumb, allocate approximately 1 CPU core and 1.5 GB to 2 GB of RAM for every 4-5 concurrent Headless Chrome sessions.

Your VPS should be provisioned with:

  1. A clean installation of Ubuntu 22.04 LTS or 24.04 LTS.
  2. Docker Engine (version 20.10 or higher) and Docker Compose installed.
  3. A static public IP address and properly configured firewall rules (allowing inbound traffic on ports 4444 for Selenoid and 8080 for the Selenoid UI).

Step-by-Step Guide: Configuring Selenoid and Headless Chrome

Step 1: Preparing the Configuration Directories

Connect to your VPS via SSH and create a dedicated directory structure to keep your configuration organized:

mkdir -p ~/selenoid/config
cd ~/selenoid

Step 2: Defining Browsers in browsers.json

Selenoid relies on a configuration file named browsers.json to know which Docker images map to specific browser versions. Create this file inside the config directory:

nano config/browsers.json

Paste the following JSON structure to configure multiple versions of Headless Chrome. We use official Selenoid images which are highly optimized:

{
    "chrome": {
        "default": "122.0",
        "versions": {
            "122.0": {
                "image": "selenoid/vnc:chrome_122.0",
                "port": "4444",
                "path": "/"
            },
            "121.0": {
                "image": "selenoid/vnc:chrome_121.0",
                "port": "4444",
                "path": "/"
            }
        }
    }
}
Note: Even though we are running tests in headless mode via our automation scripts, using the Selenoid VNC-enabled images allows QA engineers to connect live via the dashboard and visually debug sessions when required.

Step 3: Setting Up Docker Compose

To manage Selenoid and its accompanying dashboard (Selenoid UI) systematically, we define them in a docker-compose.yml file in the root of your ~/selenoid directory:

version: '3.8'

services:
  selenoid:
    image: aerokube/selenoid:latest-release
    container_name: selenoid
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "./config:/etc/selenoid:ro"
      - "./video:/opt/selenoid/video"
      - "./logs:/opt/selenoid/logs"
    ports:
      - "4444:4444"
    command: ["-conf", "/etc/selenoid/browsers.json", "-limit", "20", "-video-output-dir", "/opt/selenoid/video", "-log-output-dir", "/opt/selenoid/logs"]
    restart: unless-stopped

  selenoid-ui:
    image: aerokube/selenoid-ui:latest-release
    container_name: selenoid-ui
    ports:
      - "8080:8080"
    command: ["--selenoid-uri", "http://selenoid:4444"]
    depends_on:
      - selenoid
    restart: unless-stopped

In the command flags above, the -limit 20 parameter is critical. It defines the maximum number of concurrent browser containers that Selenoid is allowed to spin up simultaneously. Adjust this number based on your VPS hardware specifications.

Step 4: Launching the Cluster

Before launching, pull the required browser images manually to ensure fast startup times for your initial test suites:

docker pull selenoid/vnc:chrome_122.0
docker pull selenoid/vnc:chrome_121.0

Now, bring the cluster online using Docker Compose:

docker compose up -d

Verify that both containers are running properly by checking their status with docker compose ps. You can now access the Selenoid UI dashboard by navigating to http://your-vps-ip:8080 in your web browser.

Optimizing Test Scripts for Headless Execution

To utilize your new infrastructure efficiently, your automation framework (whether written in Java, Python, JavaScript, or C#) needs to be configured to connect to the remote cluster and invoke headless mode. Below is an enterprise-pattern implementation using Python and Selenium WebDriver:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

def create_remote_headless_session():
    chrome_options = Options()
    
    # Enforce performance optimizations for headless operations
    chrome_options.add_argument("--headless=new")
    chrome_options.add_argument("--no-sandbox")
    chrome_options.add_argument("--disable-dev-shm-usage")
    chrome_options.add_argument("--disable-gpu")
    chrome_options.add_argument("--window-size=1920,1080")

    # Selenoid-specific capabilities for debugging
    selenoid_capabilities = {
        "browserName": "chrome",
        "browserVersion": "122.0",
        "selenoid:options": {
            "enableVNC": True,
            "enableVideo": False
        }
    }
    
    chrome_options.set_capability("selenoid:options", selenoid_capabilities["selenoid:options"])
    
    # Point to your VPS Selenoid hub endpoint
    vps_hub_url = "http://your-vps-ip:4444/wd/hub"
    
    driver = webdriver.Remote(
        command_executor=vps_hub_url,
        options=chrome_options
    )
    return driver

By enforcing --disable-dev-shm-usage and --no-sandbox, you prevent Chrome from crashing inside small Docker shared-memory environments, which is the single most common cause of failure in massive parallel test executions.

Security and Production Considerations

Running a headless browser cluster exposes powerful computing resources. To protect your setup from malicious exploitation, ensure you implement these security measures before moving to production:

  • Network Restrictions: Use a firewall (like UFW) to restrict access to ports 4444 and 8080. Only allow connections from your CI/CD runners (e.g., Jenkins nodes, GitHub Actions runners) and internal corporate VPN IPs.
  • Reverse Proxy and Authentication: Place your Selenoid UI and Hub behind an Nginx reverse proxy configured with Let's Encrypt SSL certificates and Basic HTTP Authentication.
  • Log and Video Rotation: High-volume testing generates gigabytes of video records and logs daily. Setup a cron job or logrotate script to prune files older than 7 days to avoid filling up your VPS disk space.

Conclusion

Setting up a Headless Chrome Cluster with Selenoid on a VPS transitions your QA workflow from a bottleneck into a highly scalable asset. By decoupling execution from local setups and leveraging lightweight Docker orchestration, you achieve faster feedback loops, absolute testing stability, and significant infrastructure cost savings. As your test suite grows, scaling up is as simple as upgrading your VPS plan and modifying the concurrency limit—laying a resilient foundation for your enterprise automated testing pipeline.

Scaling Automation Testing: Building a Headless Chrome Cluster with Selenoid on VPS | DPTCloud