Deploy your AWS Runner using CloudFormation. This guide walks through creating the runner in Ona, configuring the CloudFormation template, deploying, and verifying connectivity.
Prerequisites
- AWS account with permissions to deploy CloudFormation stacks and create IAM resources. See detailed access requirements.
- Capacity planning for instance types and concurrency. See capacity planning. Ensure sufficient EC2 service quotas.
- AMI allowlisting if your organization restricts AMI usage. Allowlist owner account
995913728426 (AMI: gitpod/images/gitpod-next/ec2-runner-ami-*).
- VPC and subnets in 2-3 availability zones. EC2 subnets for environment instances, load balancer subnets routable from your users’ network. Review networking to choose a connectivity option.
- Domain name that you control with DNS modification capabilities.
- SSL/TLS certificate in ACM with SANs for
yourdomain.com and *.yourdomain.com.
Create runner in Ona
- In the Ona dashboard, go to Settings > Runners and click Set up a new runner
- Select AWS as the provider
- Enter a name, select the AWS region, and click Create
The dashboard generates a CloudFormation link with your Runner ID, Exchange Token, and API Endpoint pre-filled.
Runners are regional and can only launch environments in the AWS region they are deployed in. For multi-region support, set up multiple runners in different regions. The region cannot be changed after deployment.
Ensure you are signed into the correct AWS account, then click Open AWS CloudFormation in the runner details page. This opens the AWS console with the template pre-loaded.
Most parameters are auto-filled. The template is organized into the parameter groups described below.
Ona configuration
The Runner ID, Exchange Token, and API Endpoint are auto-generated. Do not modify these values.
| Parameter | Description | Required |
|---|
| Runner ID | Unique identifier for your runner | ✅ Yes (auto-filled) |
| Exchange Token | Authentication token for the runner | ✅ Yes (auto-filled) |
| API Endpoint | Ona management plane API URL | ✅ Yes (auto-filled) |
| Runner Size | Infrastructure size. Start with small for most deployments. Switch to large if you experience performance issues under heavy agent load. | ✅ Yes |
| Cache Engine | Data store for AI execution. MemoryDB (default) or ElastiCache. Use ElastiCache only if MemoryDB is unavailable in your region. | ✅ Yes |
Network configuration
VPC and subnet settings for the runner and environments.
| Parameter | Description | Example Value | Default | Required |
|---|
| VPC | The VPC where the runner will be deployed | vpc-12345abcd | — | ✅ Yes |
| Availability Zones | AZs for high availability (select 2-3) | us-east-1a, us-east-1b | — | ✅ Yes |
| EC2 Instances Subnet | Private subnets for EC2 environment instances. Should match the number of AZs. | subnet-123abc, subnet-456def | — | ✅ Yes |
| Load Balancer Subnets | Subnets for the load balancer, routable from your users’ network. Should match the number of AZs. | subnet-123abc, subnet-456def | — | ✅ Yes |
| Assign Public IP | Assign a public IP address to the runner tasks. Set to true if using an Internet Gateway for outbound connectivity. Set to false if using a NAT gateway or VPC endpoints. | true | false | ✅ Yes |
If your runner subnets use an internet gateway for outbound connectivity (no NAT gateway, no VPC endpoints), you must set Assign Public IP to true. Without a public IP, the runner tasks will have no outbound connectivity and the runner will fail to start.
Recommendations:
- Select 2-3 Availability Zones for high availability
- EC2 subnets: use private subnets sized for your expected workload
- Load balancer subnets: must have CIDR ranges routable from your users’ network
- Ensure connectivity from user locations via VPN, Direct Connect, or Transit Gateway
DNS configuration
Domain name, SSL certificate, and load balancer visibility.
| Parameter | Description | Example Value | Required |
|---|
| Load Balancer Visibility | internal or internet-facing | internal | ✅ Yes |
| Domain Name | Your domain name for runner access | yourdomain.com | ✅ Yes |
| Certificate ARN | ARN of your SSL certificate from ACM | arn:aws:acm:us-east-1:123456789012:certificate/abc123... | ✅ Yes |
Load balancer visibility options:
- internal: load balancer is only accessible from within your VPC (recommended for private deployments)
- internet-facing: load balancer is accessible from the public internet (requires public subnets)
Advanced configuration
The settings below are for organizations with additional network or security requirements. Most deployments do not need these.
Load balancer ingress control
| Parameter | Description | Example Value |
|---|
| Custom Security Group | Security group to attach to the load balancer. Must allow incoming traffic on port 443 (HTTPS). | sg-abcdef123 |
By default, the CloudFormation template creates a security group that allows all traffic (0.0.0.0/0) to ports 80 and 443 on the load balancer. To restrict ingress to specific source IP ranges or security groups, provide your own security group.
HTTP proxy configuration
For environments behind corporate firewalls or proxies:
| Parameter | Description | Example Value |
|---|
| HTTP Proxy | HTTP proxy server URL | http://proxy.company.com:8080 |
| HTTPS Proxy | HTTPS proxy server URL | https://proxy.company.com:8080 |
| All Proxy | All-protocol proxy server URL | http://proxy.company.com:8080 |
| No Proxy | Comma-separated list of hosts to bypass proxy | .internal,169.254.0.0/16,app.gitpod.io,.amazonaws.com |
When configuring a proxy, No Proxy must include at minimum: .internal, 169.254.0.0/16, app.gitpod.io, and .amazonaws.com.
When proxy changes take effect:
- Runner infrastructure: immediately after CloudFormation update
- Content initialization: after environment restart
- Devcontainer: after rebuild
- Docker in Docker: after container recreation
Custom CA certificate
If your network uses a corporate proxy or internal services with certificates signed by a private Certificate Authority, configure the runner to trust your CA.
| Parameter | Description | Example Value |
|---|
| Custom CA Trust Bundle | PEM-encoded CA certificate bundle, provided as an S3 URL, HTTPS URL, or SSM dynamic reference | s3://gitpod-myorg/shared/ca-bundle.pem |
Custom CA certificates work in runner, content init (SCM), and docker pull operations. However, they are not supported in devcontainer and devcontainer image build phases. You must add CA certificates to your images for these use cases.
There are three ways to provide the certificate:
1. Store the certificate in an S3 bucket (recommended)
This avoids the EC2 user data size limit and is the recommended approach for bundles with multiple certificates.
- Create an S3 bucket with a name starting with
gitpod- (e.g. gitpod-myorg)
- Upload your
.pem file to the bucket (e.g. s3://gitpod-myorg/shared/ca-bundle.pem)
s3://gitpod-myorg/shared/ca-bundle.pem
- Ensure the bucket is accessible by the runner’s IAM role (buckets prefixed with
gitpod- are allowed by default)
- Set the
CustomCATrustBundle parameter to the S3 URL
2. Reference the certificate from an HTTPS endpoint
If your CA bundle is hosted on an internal web server accessible from the runner’s VPC, provide the URL directly:
https://internal-pki.example.com/ca-bundle.pem
3. Store the certificate in SSM Parameter Store
Use CloudFormation dynamic references to retrieve certificates from AWS SSM Parameter Store. For syntax details, see SSM Parameter Store documentation.
{{resolve:ssm:/ona/ca-cert}}
Use an S3 URL if your CA bundle contains multiple certificates. SSM dynamic references embed the full certificate into EC2 user data, which has a 16 KB limit, and can fail with "User data is limited to 16384 bytes". See Custom CA certificate troubleshooting for related issues.
Deploy
- Review all parameters
- Check the box acknowledging CloudFormation will create IAM resources
- Click Create stack
Deployment typically takes 20-25 minutes. Monitor progress in the CloudFormation Events tab.
After deployment, get the load balancer DNS name from the CloudFormation Outputs tab (look for LoadBalancerDNS).
Create DNS records pointing to this value for both the root domain and wildcard.
Route 53
Create alias records pointing to your Network Load Balancer:
| Type | Name | Alias Target |
|---|
| A | yourdomain.com | Alias to Network Load Balancer in your region |
| A | *.yourdomain.com | Alias to Network Load Balancer in your region |
Other DNS providers
Create CNAME records pointing to your load balancer DNS:
| Type | Name | Value | TTL |
|---|
| CNAME | yourdomain.com | internal-LoadBa-XXXXX-123456789.us-east-1.elb.amazonaws.com | 300 |
| CNAME | *.yourdomain.com | internal-LoadBa-XXXXX-123456789.us-east-1.elb.amazonaws.com | 300 |
DNS changes typically propagate within 5-60 minutes.
Verify deployment
Once DNS propagates, verify the runner is healthy:
curl -k https://yourdomain.com/_health
nslookup yourdomain.com
Check the runner status in the Ona dashboard under Settings > Runners to confirm it shows as connected.
Next steps