testdriver:aws-setup

SkillCloud & infra

Deploy TestDriver on your AWS infrastructure using CloudFormation

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the testdriver:aws-setup skill

What this skill tells your AI

The instructions your AI receives, as published by testdriverai/testdriverai in ai/skills/testdriver-aws-setup/SKILL.md and read by ahel’s review.

This guide walks you through setting up self-hosted TestDriver instances on AWS. By the end, you'll have fully automated test infrastructure that spawns and terminates instances on-demand.

graph LR
    A[Vitest Test] --> B[setup-aws hook]
    B --> C[Spawns EC2]
    C --> D[Runs Test]
    D --> E[Terminates EC2]

How It Works

TestDriver automatically manages AWS EC2 instances for your tests:

  1. Deploy CloudFormation — One-time infrastructure setup
  2. Configure Vitest — Add one line to your config
  3. Run Tests — Instances spawn automatically, run tests, and terminate

That's it! No manual instance management needed.

Quickstart

Overview

The setup process is simple:

  1. Deploy CloudFormation — Creates VPC, security groups, IAM roles, and launch templates
  2. Configure Vitest — Add setup-aws to automatically manage instance lifecycle
  3. Run Tests — Set TD_OS=windows with AWS credentials and instances spawn/terminate automatically

Prerequisites

Before you begin, ensure you have:

  • AWS account with CloudFormation permissions
  • AWS CLI installed and configured (aws configure)
  • Access to the TestDriver AMI — Contact us with your AWS region
  • A GitHub repository for your tests

Step 1: Deploy CloudFormation Stack

Our CloudFormation template creates all the AWS infrastructure you need:

  • Dedicated VPC with public subnet
  • Security group with required port access
  • IAM roles and instance profiles
  • EC2 launch template for instance creation
<Card
  title="Launch Stack"
  icon="aws"
  href="https://console.aws.amazon.com/cloudformation/home#/stacks/create/review?templateURL=https://v7-cloudformation-template.s3.us-east-2.amazonaws.com/cloudformation.yaml"
  horizontal
  arrow
>
  Deploy TestDriver infrastructure with one click
</Card>

Configure the stack parameters:
- **Stack name**: `testdriver-infrastructure` (or your preferred name)
- **ProjectTag**: `testdriver`
- **AllowedIngressCidr**: Your IP range (e.g., `203.0.113.0/24`)
- **InstanceType**: `c5.xlarge` (recommended)
- **CreateKeyPair**: `true`

<Warning>
  **Security**: Replace `AllowedIngressCidr` with your specific IP ranges to restrict VPC access. Avoid using `0.0.0.0/0` in production.
</Warning>

### Get Your Launch Template ID

After the stack creation completes, navigate to the **Outputs** tab to find your `LaunchTemplateId`:

![Launch Template ID](/images/content/self-hosted/launchtemplateid.png)

<Tip>
  **Save this ID** — you'll need it for spawning instances and CI configuration.
</Tip>
```bash
aws cloudformation deploy \
  --template-file setup/aws/cloudformation.yaml \
  --stack-name testdriver-infrastructure \
  --parameter-overrides \
    ProjectTag=testdriver \
    AllowedIngressCidr=0.0.0.0/0 \
    InstanceType=c5.xlarge \
    CreateKeyPair=true \
  --capabilities CAPABILITY_IAM
```

<Warning>
  **Security**: Replace `AllowedIngressCidr=0.0.0.0/0` with your specific IP ranges to restrict VPC access.
</Warning>

### Get Your Launch Template ID

After deployment completes, retrieve the launch template ID:

```bash
aws cloudformation describe-stacks \
  --stack-name testdriver-infrastructure \
  --query 'Stacks[0].Outputs[?OutputKey==`LaunchTemplateId`].OutputValue' \
  --output text
```

<Tip>
  **Save this ID** — you'll need it for spawning instances and CI configuration.
</Tip>

Step 2: Configure Vitest

Add the AWS setup hook to your vitest.config.mjs:

import { defineConfig } from 'vitest/config';
import { config } from 'dotenv';
import TestDriver from 'testdriverai/vitest';

config(); // Load .env file

export default defineConfig({
  test: {
    testTimeout: 900000,
    hookTimeout: 900000,
    maxConcurrency: 3,
    reporters: [
      'default',
      TestDriver(),
      ['junit', { outputFile: 'test-report.junit.xml' }]
    ],
    setupFiles: ['testdriverai/vitest/setup', 'testdriverai/vitest/setup-aws'],
  },
});

Step 3: Write Your Tests

Tests should use context.ip || process.env.TD_IP for the IP configuration:

import { describe, it } from "vitest";
import { TestDriver } from "testdriverai/vitest/hooks";

describe("My Test", () => {
  it("should run on self-hosted instance", async (context) => {
    const testdriver = TestDriver(context, {
      ip: context.ip || process.env.TD_IP,
    });

    await testdriver.provision.chrome({ url: "https://example.com" });
    // ... your test steps
  });
});

Step 4: Run Tests

Locally

TD_OS=windows \
AWS_REGION=us-east-2 \
AWS_LAUNCH_TEMPLATE_ID=lt-xxx \
AMI_ID=ami-0504bf50fad62f312 \
vitest run

In GitHub Actions

Automate testing with self-hosted instances in your CI/CD pipeline. TestDriver automatically spawns a fresh instance for each test, runs the test, and terminates the instance.

name: TestDriver Self-Hosted Windows Tests

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run Windows tests with self-hosted instances
        run: npx vitest run examples/*.test.mjs
        env:
          TD_API_KEY: ${{ secrets.TD_API_KEY }}
          TD_OS: windows
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_REGION: us-east-2
          AWS_LAUNCH_TEMPLATE_ID: ${{ secrets.AWS_LAUNCH_TEMPLATE_ID }}
          AMI_ID: ${{ secrets.AMI_ID }}

      - name: Upload test results
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-results
          path: test-report.junit.xml

Required GitHub Secrets

SecretDescriptionExample
AWS_ACCESS_KEY_IDAWS access keyAKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEYAWS secret keywJalrXUtnFEMI/K7MDENG...
AWS_REGIONAWS regionus-east-2
AWS_LAUNCH_TEMPLATE_IDFrom CloudFormation outputlt-07c53ce8349b958d1
AMI_IDTestDriver AMI IDami-0504bf50fad62f312
TD_API_KEYYour TestDriver API keyFrom console.testdriver.ai

Example Workflows

For complete production examples, see:

Advanced Usage

Using an Existing Instance

If you already have a running instance, you can skip automatic spawning by providing TD_IP:

TD_OS=windows TD_IP=1.2.3.4 vitest run

The setup-aws hook will detect TD_IP is already set and skip spawning a new instance.

Manual Instance Management

For advanced use cases, you can manually spawn instances using the spawn-runner.sh script:

AWS_REGION=us-east-2 \
AMI_ID=ami-0504bf50fad62f312 \
AWS_LAUNCH_TEMPLATE_ID=lt-xxx \
bash setup/aws/spawn-runner.sh

Output:

PUBLIC_IP=1.2.3.4
INSTANCE_ID=i-1234567890abcdef0
AWS_REGION=us-east-2

Then manually terminate when done:

aws ec2 terminate-instances \
  --instance-ids i-1234567890abcdef0 \
  --region us-east-2

For complete production examples, see:

Connecting to an Instance

You can connect to running instances via:

  • RDP — Use the public IP on port 3389
  • VNC — Access via web browser at http://<public-ip>:5900
  • AWS Console — Use EC2 Instance Connect or Session Manager

AMI Customization

The TestDriver Golden Image comes pre-configured with:

  • Windows Server with desktop environment
  • VNC + web server for remote access
  • Python, Node.js, Git
  • TestDriver agent and dependencies

Creating a Custom AMI

You can customize the AMI to include additional software or configurations:

Security Best Practices

Network Security

  • Restrict CIDR blocks — Only allow access from known IP ranges
  • Use VPC endpoints — For private AWS service communication
  • Enable VPC Flow Logs — For network monitoring

AWS Authentication

Use OIDC instead of long-term credentials for GitHub Actions:

permissions:
  id-token: write
  contents: read

steps:
  - name: Configure AWS credentials
    uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
      aws-region: us-east-2

See GitHub's OIDC documentation for setup instructions.

Instance Security

  • Terminate immediately after tests complete
  • Monitor costs with AWS billing alerts
  • Use least-privilege IAM roles
  • Enable CloudTrail for audit logging

Troubleshooting

Instance Not Responding

  • Check security groups — Verify required ports are open (RDP 3389, VNC 5900, TestDriver ports)
  • Verify status checks — Ensure instance has passed AWS status checks
  • Check AMI compatibility — Some instance types don't support certain AMIs

Connection Timeouts

  • Verify network connectivity from CI runner to instance
  • Check VPC routing and internet gateway configuration
  • Confirm instance is in the correct subnet

AWS CLI Errors

  • Validate credentials and permissions
  • Check service quotas and limits
  • Verify region consistency across all resources

Signals

GitHub stars
242
Forks
35
Last commit
Sep 2026

ahel review

  • S4info
    community integration — published by testdriverai, not aws

Automated review, not a security audit. Ruleset v1.

Advanced
Catalog kind
skill
Gateway key
testdriver-aws-setup
Source
github.com/testdriverai/testdriverai