# Selenium Grid testing

Source: https://docs.quake.ai/resources/iac-templates/selenium-grid-testing
Markdown: https://docs.quake.ai/resources/iac-templates/selenium-grid-testing.md

---

# Selenium Grid testing

This pattern composes Compute and Network into a self-hosted browser-testing grid for WebDriver-based UI test suites, on infrastructure you control.

## What this template does

Provisions a single instance running a [Selenium Grid 4](https://www.selenium.dev/documentation/grid/) hub plus three browser nodes (two Chrome, one Firefox), a self-hosted alternative to BrowserStack or Sauce Labs for CI test runs:

- Compute instance that runs the hub and every node as Docker containers on 8 vCPU and 8 GiB RAM, sized for the memory headroom three browser containers need
- Private network, subnet, router, port, and security group; a floating IP for reaching the grid from a CI runner outside the private network
- No block volume and no bundled database: sessions are ephemeral by design, so only the default boot disk is used
- cloud-init installs Docker Engine and starts the hub and all three nodes automatically; there is no credential to generate and no manual configuration step

## No built-in authentication

A Selenium Grid ships with no login and no API token. Anyone who can reach port 4444 can drive a browser session, and anyone who can reach 4442 or 4443 can register a rogue node with the hub. This template restricts all three ports to `grid_allowed_cidr`, which defaults to the private network only, and never fronts the grid with a public HTTPS domain the way the other self-hosted tools in this library are. Reach the grid from a CI runner on the private network, or scope `grid_allowed_cidr` to your CI runner IPs or VPN CIDR.

## Parameters

| Parameter | Description | Default |
| --- | --- | --- |
| `key_name` | SSH keypair name (must already exist) | No default |
| `flavor_name` | Instance size (hub plus three browser nodes needs 8 vCPU / 8 GiB) | `s1a.large` |
| `image_name` | Operating system image | `Ubuntu-24.04` |
| `app_name` | Display name prefix for resources | `selenium-grid` |
| `external_network` | External network for floating IP allocation | `PublicStatic` |
| `private_cidr` | CIDR for the private subnet | `10.54.0.0/24` |
| `grid_allowed_cidr` | CIDR allowed to reach the grid ports (4442-4444) | `10.54.0.0/24` |
| `selenium_version` | Image tag pinned across the hub and every node | `4.45.0-20260606` |

## Finish setup after apply

cloud-init starts the hub and all three nodes immediately; the grid is reachable on port 4444 within a few seconds of the containers starting, once the nodes register with the hub over the event bus:

1. Open `grid_url` from the outputs (or tunnel over SSH) and confirm the Grid UI shows three registered nodes.
2. Point a WebDriver client at `<grid_url>/wd/hub` or the bare `grid_url`; both endpoints work identically against Grid 4.

## Scale nodes

Add more Chrome or Firefox capacity with `docker compose up -d --scale chrome-1=N` from `/opt/selenium`, or add a `selenium/node-edge` service to the compose file for a third browser. Give each additional node its own `shm_size: 2gb` and the same `SE_EVENT_BUS_HOST` environment variables as the existing nodes.

## Access and security

The security group restricts ports 4442-4444 to `grid_allowed_cidr`. Never widen this to `0.0.0.0/0`: the grid has no built-in authentication, so an open port exposes an unauthenticated WebDriver endpoint that anyone can use to drive a browser or register a rogue node.

## When to use this pattern

Run WebDriver-based UI test suites from CI without a per-minute device-farm bill. Sessions are ephemeral: nothing a test run produces persists across a container restart, so there is nothing to back up beyond the pinned image tag and the compose file itself.

## Estimated cost

<PricingCompanion
  components={[
    { kind: "template", slug: "selenium-grid-testing", required: true },
  ]}
/>

## Template source

<TemplateSource slug="selenium-grid-testing" />

<TemplateResourceMap template="selenium-grid-testing" format="opentofu" />

## Customize this pattern

- [Customize a template's image and flavor](/docs/automation/how-to/customize-template-image-flavor)
- [Parameterize a template with a tfvars file](/docs/automation/how-to/parameterize-template-tfvars)

## See also

- [Forgejo Git and CI](/resources/iac-templates/forgejo-git-ci)
- [Simple VM deployment](/resources/deployments/deploy-simple-vm-template)
