Skip to content
Deployments

Deploy Selenium Grid with the selenium-grid-testing template

Deployment

Deploy Selenium Grid with the selenium-grid-testing template

Stand up a Selenium Grid 4 hub and three browser nodes on a single Quake AI instance using the validated OpenTofu template selenium-grid-testing. You apply the template, confirm the nodes register with the hub, run one sample WebDriver test against Chrome and one against Firefox, and scale the number of Chrome nodes.

The grid runs on infrastructure you own; this is a self-hosted tool you operate for CI, not a managed multi-tenant device farm.

CI runner or workstationFloating IPUbuntu instanceSelenium hubChrome node 1Chrome node 2Firefox node registers over event busregisters over event busregisters over event busWebDriver session (4444), restricted CIDR
Click to zoom
What you'll build: a stateless Selenium Grid hub and three browser nodes on a single instance, reached over an SSH tunnel or a CIDR-restricted CI runner

Monthly cost estimate

Pricing calculator ↗

Sized as a custom package on shared vCPU.

Starting template$63.40/mo

Monthly total for the required template above. Use the configurator below to add optional pieces and see the total update.

What each resource is for

Selenium Grid host

s1a.large · 8 shared vCPU, 8 GiB RAM, 0.5 Gbps

Runs a stateless Selenium Grid hub plus two Chrome nodes and one Firefox node, all ephemeral with no attached data volume.

The hub plus three browser node containers need real memory headroom to avoid crashes under load; 8 vCPU and 8 GiB RAM is the floor. Size up further for more nodes or heavier test suites.

$66.00/mo

Compute shown per role at custom-package rates ($29/dedicated vCPU, $7.25/shared vCPU, $1/GiB RAM). The headline above is the billed total: the cheaper of a named plan and the custom package, plus add-ons.

Included in baseline

s1a.large

8 shared vCPU, 8 GiB RAM, 0.5 Gbps

$66.00

Compute + RAM rate basis

8 vCPU + 8 GiB RAM at $29/dedicated vCPU, $7.25/shared vCPU, $1/GiB RAM (regular). Totals apply the flat −$5/mo package promotion.

—

Block storage (30 GiB)

30 GiB at $0.08/GiB/mo

$2.40

Public IP (included)

1 included with the custom package

$0.00

Package promotional discount

Flat −$5.00/mo on the custom package (same promotion as named plans).

$-5.00

Included at no charge

These line items are zero on Quake AI. Many other providers meter them separately.

Data transfer (inbound and outbound)

Unlimited data transfer on every plan; Quake AI does not meter per-GB egress.

AWS, GCP, and Azure meter outbound transfer per GB. DigitalOcean and Hetzner include an allowance on compute plans, then charge overage.

Learn more
$0.00

Private networking

Private networks, subnets, Neutron routers, and security groups are included with the plan.

VPC objects are usually free to create elsewhere, but NAT gateways bill hourly plus per-GB processed. Quake AI uses router SNAT with no separate NAT line item.

$0.00

Control-plane API requests

OpenStack API calls for provisioning and management are included.

Some managed services on other clouds meter API calls or charge for premium control-plane features.

$0.00

Pricing data last validated: . For current rates, check quake.ai/pricing.

Prerequisites#

You need:

  • OpenTofu 1.6.0 or later (or Terraform 1.6.0 or later) installed locally.
  • Your OpenStack credentials sourced into the shell (source openrc.sh). See the OpenStack CLI guide.
  • An SSH keypair that already exists in your project. Record its name for the key_name variable.
  • A copy of the selenium-grid-testing template directory from the template reference page.
  • Python 3 installed locally, to run the sample WebDriver scripts in this walkthrough.

Step 1: Apply the template#

Copy the template's example variables file and set key_name. If you plan to reach the grid directly from your workstation rather than tunneling over SSH, also set grid_allowed_cidr to your workstation's CIDR:

bash
cp terraform.tfvars.example terraform.tfvars
HCL
key_name = "YOUR_KEY_NAME"
# grid_allowed_cidr = "YOUR_WORKSTATION_IP/32"

Initialize, preview, and apply:

bash
tofu init
tofu plan
tofu apply

OpenTofu provisions a private network, a router, a security group, an instance, and a floating IP. On first boot, cloud-init installs Docker Engine and starts the hub and all three nodes: no credential to generate and no manual configuration step blocks first use.

Read the outputs and record floating_ip and grid_url:

bash
tofu output

Step 2: Confirm the nodes registered with the hub#

Open grid_url from the previous step (http://YOUR_FLOATING_IP:4444) in a browser. If you have not opened grid_allowed_cidr to your workstation, tunnel over SSH instead:

bash
ssh -L 4444:localhost:4444 ubuntu@YOUR_FLOATING_IP

Then open http://localhost:4444. The Grid UI shows the hub's status. Confirm three nodes are listed: two Chrome and one Firefox. Nodes usually finish registering within a few seconds of the containers starting.

Step 3: Run a sample WebDriver test against Chrome and Firefox#

Install the Python Selenium client locally:

bash
pip install selenium

Save the following as grid_test.py, then run it once with BROWSER=chrome and once with BROWSER=firefox:

Python
import os

from selenium import webdriver
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions

grid_url = "http://localhost:4444/wd/hub"  # or your floating IP if grid_allowed_cidr permits
browser = os.environ.get("BROWSER", "chrome")

options = ChromeOptions() if browser == "chrome" else FirefoxOptions()
driver = webdriver.Remote(command_executor=grid_url, options=options)

try:
    driver.get("https://example.com")
    print(f"{browser}: page title is '{driver.title}'")
finally:
    driver.quit()
bash
BROWSER=chrome python grid_test.py
BROWSER=firefox python grid_test.py

Each run prints the page title, confirming the grid dispatched the session to a registered node of the requested browser type.

Step 4: Scale the number of Chrome nodes#

SSH to the instance and add more Chrome capacity:

bash
cd /opt/selenium
sudo docker compose up -d --scale chrome-1=3

The Grid UI now shows additional Chrome nodes registered alongside the original two. Any new node needs the same shm_size: 2gb and SE_EVENT_BUS_HOST environment variables as the existing services in /opt/selenium/docker-compose.yml, which --scale reuses automatically since it replicates the same service definition.

What you built#

  • Applied the selenium-grid-testing template to provision a network, security group, instance, and floating IP, with the hub and three browser nodes started automatically by cloud-init
  • Confirmed the nodes registered with the hub over the Grid UI
  • Ran a sample WebDriver test against both a Chrome node and a Firefox node
  • Scaled the number of Chrome nodes with docker compose up -d --scale

Scope of this deployment#

This template runs a single-VM Selenium Grid, not a managed device farm. The instance is CPU-only and runs in one region, has no built-in authentication, and holds no persistent state: sessions are ephemeral and nothing survives a container restart. You operate the instance, Docker, the hub, and every node yourself: patch the pinned selenium_version tag periodically and watch memory use as you add nodes or run heavier test suites.

Next steps#

Clean up#

When you no longer need the deployment, destroy everything the template created:

bash
tofu destroy

Because every container in this stack is stateless, tofu destroy removes the grid entirely with no data to export first.

Before this
Was this page helpful?