self-host →

Flex configuration

Complete reference for configuring RunsOn Flex — every CloudFormation parameter and every Terraform module input.

RunsOn Flex installs into your AWS account either through the built-in CloudFormation stack (the default, recommended for most installs) or through the Terraform / OpenTofu module. This page is the full reference for both. The two surfaces overlap heavily but are not identical: the Terraform module deploys into an existing VPC (requiring vpc_id and public_subnet_ids) and exposes additional inputs that the CloudFormation stack — which creates its own VPC — does not.

To change a value, follow the Upgrade guide — update the parameter in the CloudFormation interface, or change the input in your Terraform configuration and re-apply.

For advanced infrastructure usage such as GHES, existing VPCs, or deeper networking control, use the Terraform / OpenTofu module.

CloudFormation parameters

The CloudFormation stack RunsOn creates when installing the service exposes the following parameters.

Main configuration [required]

GithubOrganization

  • Type: String
  • MinLength: 1
  • Description: If your GitHub organization lives at github.com/my-org, then enter: my-org. IMPORTANT: this field is case-sensitive.

LicenseKey

  • Type: String

  • MinLength: 1

  • Description: License key for RunsOn, either as a string or SSM parameter ARN (with the format arn:aws:ssm:REGION:ACCOUNT:parameter/STACK_NAME/license-key). Get one at https://runs-on.com/pricing.

  • NoEcho: true

EmailAddress

  • Type: String
  • MinLength: 1
  • Description: Email address for cost and alert reports. You will receive a confirmation email from AWS at this address during the installation (check your spam folder if needed) so make sure to use a valid address. You must confirm it if you want to receive cost and alert reports.

Environment

  • Type: String
  • Default: production
  • MinLength: 1
  • Description: Make RunsOn only listen to jobs with an env job label matching this value. Only change this if you know what you are doing. See https://runs-on.com/configuration/environments/ for more details.

Networking and security [optional]

VpcCidrBlock

  • Type: String
  • Default: 10.1.0.0/16
  • Description: CIDR block for the embedded RunsOn VPC. Set this to a range that does not overlap with your existing VPCs when creating the stack. Changing this after the VPC exists requires replacing the VPC and dependent resources.

Private

  • Type: String
  • Default: false
  • AllowedValues: only, always, true, false
  • Description: Enable (‘true’, ‘always’, ‘only’) or disable (‘false’) private networking. If ‘true’, your jobs can opt-in to launch in private subnets with the private=true label, and they will get a static egress IP. If ‘always’, all jobs will run in private subnets, and they will all get a static egress IP, unless you manually opt-out in your job definition with the private=false label. If ‘only’, then jobs can only launch in private subnets. Note that enabling it will create 1 managed NAT gateway, with the corresponding costs. More details at https://runs-on.com/networking/static-ips/.

Ipv6Enabled

  • Type: String
  • Default: false
  • AllowedValues: true, false
  • Description: Enable or disable IPv6 for runners. Disabling ipv6 might help with Docker Hub rate limiting issues.

SSHAllowed

  • Type: String
  • Default: true
  • AllowedValues: true, false
  • Description: Allow inbound SSH connections from the specified CIDR range to the runners.

SSHCidrRange

  • Type: String
  • Default: 0.0.0.0/0
  • MinLength: 1
  • Description: CIDR range for inbound SSH access. By default, only repository collaborators with admin permission will be able to SSH into the runner instances.

EnableWAF

  • Type: String
  • Default: false
  • AllowedValues: true, false
  • Description: Enable AWS WAF for the public ingress.

EnableAdminRoutes

  • Type: String
  • Default: true
  • AllowedValues: true, false
  • Description: Enable the admin Lambda routes (/, /setup, /setup/{proxy+}, /readyz) on the public ingress.

EncryptEbs

  • Type: String
  • Default: false
  • AllowedValues: true, false
  • Description: Encrypt the EBS volumes of the runner instances. Encryption will slow the boot time of runner instances by ~10s.

RunnerCustomPolicy

  • Type: String
  • Default:  
  • Description: Optional managed IAM Policy ARN to assign to the EC2 runner instances. Can be used to give runners access to AWS resources that you manage.

AppCustomPolicy

  • Type: String
  • Default:  
  • Description: Optional managed IAM Policy ARN to assign to the RunsOn service role. Can be used to e.g. allow access to KMS decryption keys for AMIs.

NetworkFirewallPolicyArn

  • Type: String
  • Default:  
  • AllowedPattern: ^$|^arn:aws[a-zA-Z-]*:network-firewall:[a-z0-9-]+:[0-9]{12}:firewall-policy/.+$
  • Description: Optional ARN of an AWS Network Firewall policy used for IPv4 egress filtering. Manage the policy and its rule groups outside this stack. When provided, RunsOn creates firewall endpoints in both AZs and routes IPv4 egress from public subnets, plus private-subnet egress after NAT, through the firewall. S3 gateway endpoint traffic still bypasses the firewall. IPv6 traffic is not filtered; set Ipv6Enabled=false if you need comprehensive egress filtering.

Runner behavior and storage [optional]

EnableBedrock

  • Type: String
  • Default: false
  • AllowedValues: true, false
  • Description: Enable Amazon Bedrock access for EC2 runner instances. When enabled, runners can use their instance profile credentials with Bedrock-compatible AI agents such as Claude Code or OpenCode.

EnableEfs

  • Type: String
  • Default: false
  • AllowedValues: true, false
  • Description: Enable EFS shared filesystem for runners. If enabled, an EFS volume will be created and made available to runners. Runners will need appropriate permissions and tools (e.g., nfs-utils) to mount it.

EnableEphemeralRegistry

  • Type: String
  • Default: false
  • AllowedValues: true, false
  • Description: If enabled, create an ECR ephemeral registry that can be used as a type=registry cache backend for Docker BuildKit. The registry will be created with a 10-day lifecycle policy, and runners will automatically be granted push/pull access.

RunnerCustomTags

RunnerMaxRuntime

  • Type: Number
  • Default: 720
  • MinValue: 30
  • Description: Maximum runtime in minutes for runners. After this time, the runner will be forcefully terminated.

RunnerConfigAutoExtendsFrom

  • Type: String
  • Default: .github-private
  • MinLength: 1
  • Description: When set to a repository name (e.g., ‘.github-private’), forces all repository configurations to extend from that repository. The config will be read from <repo-name>/.github/runs-on.yml. This allows you to provide a base configuration that applies to all repositories, even if they don’t have a local runs-on.yml file. Set to ’.’ to disable auto-extend and use each repository’s local extends (if any). Make sure the GitHub App has access to the specified repository.

S3CacheExpirationInDays

  • Type: Number
  • Default: 10
  • Description: Number of days to keep cache entries in the S3 cache bucket.

App runtime and maintenance [optional]

AppSize

  • Type: String
  • Default: small
  • AllowedValues: small, medium, high, xhigh
  • Description: Preset for the RunsOn control plane. This sets the worker service CPU/memory, queued-job concurrency, and the default EC2 launch/termination rate-limit assumptions together. Higher concurrency presets assume you have raised the relevant EC2 quotas (https://docs.aws.amazon.com/AWSEC2/latest/APIReference/throttling.html).

AppCapacityProvider

  • Type: String
  • Default: FARGATE
  • AllowedValues: FARGATE, FARGATE_SPOT
  • Description: ECS Fargate capacity provider for the RunsOn control plane. FARGATE_SPOT lowers idle cost but can briefly stop the single control-plane task until Spot capacity is available; interrupted in-flight queue messages retry after the SQS visibility timeout.

AppGithubApiStrategy

  • Type: String
  • Default: normal
  • AllowedValues: normal, conservative
  • Description: Use normal or conservative GitHub API strategy. The conservative strategy will attempt to save GitHub API tokens by not automatically de-registering runners from the GitHub API after they are no longer needed. It’s more elegant to clean them up (recommended), but in any case GitHub will eventually clean them up on their side after 24h. Especially useful if you launch tens of thousands of jobs every day.

AppRegistry

  • Type: String
  • Default: public.ecr.aws/c5h5o9k1/runs-on/runs-on
  • Description: Docker image (public) registry for the RunsOn service.

LoggerLevel

  • Type: String
  • Default: info
  • AllowedValues: trace, debug, info, warn
  • Description: Log level for the RunsOn server. Options: trace (most verbose), debug, info (default), warn (least verbose).

SpotCircuitBreaker

  • Type: String
  • Default: 2/15/30
  • AllowedPattern: ^(false|[0-9]+/[0-9]+/[0-9]+)$
  • Description: Enable (COUNT/WINDOW_MINUTES/RECOVERY_MINUTES) or disable (false) the spot instance circuit breaker. If enabled, the circuit breaker will prevent the stack from launching new spot instances during RECOVERY_MINUTES if there was at least COUNT spot interruptions during the last WINDOW_MINUTES. For instance 2/15/30 will prevent the stack from launching new spot instances during 30 minutes if there was at least 2 spot interruptions during the last 15 minutes.

MaintenanceMode

  • Type: String
  • Default: false
  • AllowedValues: true, false
  • Description: Enable maintenance mode (scales the worker service to zero)

Observability, cost, and integrations [optional]

OtelExporterEndpoint

OtelExporterHeaders

  • Type: String
  • Default:  
  • Description: Headers for OTLP endpoint in W3C Baggage format: ‘key1=value1,key2=value2’ (e.g., ‘signoz-ingestion-key=ABCD1234’). Leave empty if not required.
  • NoEcho: true

OtelExporterTemporality

  • Type: String
  • Default: cumulative
  • AllowedValues: cumulative, delta
  • Description: OTLP metrics temporality. Use cumulative (default) or delta (required by Datadog).

CostReportsEnabled

  • Type: String
  • Default: true
  • AllowedValues: true, false
  • Description: Enable or disable cost reports sent by email.

AlertTopicSlackWebhookUrl

  • Type: String
  • Default:  
  • Description: Slack incoming webhook URL for alert notifications.
  • NoEcho: true

AppBudgetDailyUsd

  • Type: Number
  • Default: 10
  • Description: Create a daily AWS cost budget in USD for this stack, filtered by the configured cost allocation tag. Set to 0 to disable the budget. The budget evaluates UTC billing periods rather than real-time operational usage. For AWS Organizations member accounts, activate the cost allocation tag in the management account’s Billing settings.

CostAllocationTag

  • Type: String
  • Default: stack
  • Description: Cost allocation tag key to use for all the deployed resources. The value for this tag will be set to the stack name. Updating this after creation will require deleting the stack and recreating it.

IntegrationStepSecurityApiKey

Terraform inputs

The Terraform module (runs-on/runs-on/aws//modules/flex) exposes the following inputs.

Required inputs

github_organization

  • Type: string
  • Required: yes
  • Description: GitHub organization or username for RunsOn integration

license_key

  • Type: string
  • Required: yes
  • Sensitive: yes
  • Description: RunsOn license key obtained from runs-on.com

vpc_id

  • Type: string
  • Required: yes
  • Description: VPC ID where RunsOn infrastructure will be deployed

public_subnet_ids

  • Type: list(string)
  • Required: yes
  • Description: List of public subnet IDs for runner instances. Required unless private_mode is “only”.

email

  • Type: string
  • Required: yes
  • Description: Email address for alerts and notifications (requires confirmation)

Optional inputs

stack_name

  • Type: string
  • Default: "runs-on"
  • Description: Name for the RunsOn stack (used for resource naming)

environment

  • Type: string
  • Default: "production"
  • Description: Environment name used for resource tagging and RunsOn job filtering. RunsOn will only process jobs with an ‘env’ label matching this value. See https://runs-on.com/configuration/environments/ for details.

cost_allocation_tag

  • Type: string
  • Default: "stack"
  • Description: Name of the tag key used for cost allocation and tracking

tags

  • Type: map(string)
  • Default: {}
  • Description: Tags to apply to all resources. Note: ‘runs-on-stack-name’ is added automatically for resource discovery.

github_enterprise_url

  • Type: string
  • Default: ""
  • Description: GitHub Enterprise Server URL (optional, leave empty for github.com)

private_subnet_ids

  • Type: list(string)
  • Default: []
  • Description: List of private subnet IDs for runner instances (required if private_mode is not ‘false’)

private_mode

  • Type: string
  • Default: "false"
  • Allowed values: false, true, always, only
  • Description: Private networking mode: ‘false’ (disabled), ‘true’ (opt-in with label), ‘always’ (default with opt-out), ‘only’ (forced, no public option)

private_mode_delay

  • Type: string
  • Default: "0s"
  • Description: Delay before starting the worker service in private mode, to allow NAT gateways to become ready. Set to ”60s” or higher for fresh NAT gateway deployments.

security_group_ids

  • Type: list(string)
  • Default: []
  • Description: Security group IDs for runner instances and the worker service. If empty list provided, security groups will be created automatically.

ssh_allowed

  • Type: bool
  • Default: true
  • Description: Allow SSH access to runner instances

ssh_cidr_range

  • Type: string
  • Default: "0.0.0.0/0"
  • Description: CIDR range allowed for SSH access to runner instances (only applies if ssh_allowed is true)

cache_expiration_days

  • Type: number
  • Default: 10
  • Description: Number of days to retain cache artifacts in S3 before expiration

cache_bucket_namespace

  • Type: string
  • Default: "global"
  • Allowed values: global, account-regional
  • Description: S3 namespace for the cache bucket. Use account-regional when an organization SCP requires account-regional S3 bucket names.

force_destroy_buckets

  • Type: bool
  • Default: false
  • Description: Allow S3 buckets to be destroyed even when not empty. Set to false for production environments to prevent accidental data loss.

log_retention_days

  • Type: number
  • Default: 7
  • Allowed values: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653
  • Description: Number of days to retain CloudWatch logs for EC2 instances

permission_boundary_arn

  • Type: string
  • Default: ""
  • Description: IAM permissions boundary ARN to attach to all IAM roles (optional)

ipv6_enabled

  • Type: bool
  • Default: false
  • Description: Enable IPv6 support for runner instances

ebs_encryption_key_id

  • Type: string
  • Default: ""
  • Description: KMS key ID for explicit EBS volume encryption. Leave empty to omit explicit EBS encryption fields, use alias/aws/ebs for the AWS-managed EBS key, or provide a customer-managed key ID, alias, or ARN. Prefer a full ARN for customer-managed keys, especially cross-account keys. Customer-managed keys must also trust the generated RunsOn worker task role in their key policy.

app_image

  • Type: string
  • Default: "public.ecr.aws/c5h5o9k1/runs-on/runs-on:v3.1.0@sha256:55d023bc07480956a7bae4d2218f78fdf79ca0f8027da11efdad99589b8c9954"
  • Description: Container image for the RunsOn worker service. Published module releases inject a pinned public default during mirror publication.

app_tag

  • Type: string
  • Default: "v3.1.0"
  • Description: Application version tag for RunsOn service. Published module releases inject the released default during mirror publication.

bootstrap_tag

  • Type: string
  • Default: "v0.1.12"
  • Description: Bootstrap script version tag

maintenance_mode

  • Type: bool
  • Default: false
  • Description: Enable maintenance mode (disables queue processing and leader election)

app_size

  • Type: string
  • Default: "small"
  • Allowed values: small, medium, high, xhigh
  • Description: Preset for the worker service, default EC2 launch concurrency, and default registration concurrency. Allowed values: small, medium, high, xhigh.

app_capacity_provider

  • Type: string
  • Default: "fargate"
  • Allowed values: fargate, fargate_spot
  • Description: Fargate capacity provider for the RunsOn worker service. Use fargate_spot to lower idle cost for small installs; interrupted in-flight queue messages retry after the SQS visibility timeout.

app_force_new_deployment

  • Type: bool
  • Default: false
  • Description: Force a new ECS deployment of the RunsOn control-plane service. Set to true for one apply when migrating existing installs across the v3.0.6 ECS capacity provider change or when changing app_capacity_provider.

app_ecr_repository_url

  • Type: string
  • Default: ""
  • Description: Private ECR repository URL for RunsOn image (e.g., 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-repo:tag). When specified, the worker service will pull from this private ECR instead of public ECR.

app_custom_policy_arn

  • Type: string
  • Default: ""
  • Description: Optional managed IAM policy ARN to attach to the RunsOn service role.

github_app_id

  • Type: number
  • Default: null
  • Description: GitHub App ID. If provided along with other github_app_* variables, creates a Secrets Manager secret and skips the web-based GitHub App setup flow.

github_app_private_key

  • Type: string
  • Default: ""
  • Sensitive: yes
  • Description: GitHub App private key (PEM format)

github_app_webhook_secret

  • Type: string
  • Default: ""
  • Sensitive: yes
  • Description: GitHub App webhook secret

github_app_client_id

  • Type: string
  • Default: ""
  • Description: GitHub App client ID

github_app_client_secret

  • Type: string
  • Default: ""
  • Sensitive: yes
  • Description: GitHub App client secret

github_api_boost_apps

  • Type: map(object({ github_app_id = number github_app_private_key = string github_app_client_id = string github_app_client_secret = string github_app_label = optional(string, "") }))
  • Default: {}
  • Sensitive: yes
  • Description: Additional same-org GitHub Apps used only for API boost capacity. These entries omit webhook secrets and are written under the shared GitHub apps secret.

github_api_strategy

  • Type: string
  • Default: "normal"
  • Allowed values: normal, conservative
  • Description: Strategy for GitHub API calls (normal, conservative)

runner_max_runtime

  • Type: number
  • Default: 720
  • Description: Maximum runtime in minutes for runners before forced termination

runner_custom_policy_arn

  • Type: string
  • Default: ""
  • Description: Optional managed IAM policy ARN to attach to the EC2 runner instance role.

runner_config_auto_extends_from

  • Type: string
  • Default: ".github-private"
  • Description: Auto-extend runner configuration from this base config

runner_custom_tags

  • Type: list(string)
  • Default: []
  • Description: Custom tags to apply to runner instances (comma-separated list)

enable_cost_reports

  • Type: bool
  • Default: true
  • Description: Enable automated cost reports sent to alert email

spot_circuit_breaker

  • Type: string
  • Default: "2/15/30"
  • Description: Spot instance circuit breaker configuration (e.g., ‘2/15/30’ = 2 failures in 15min, block for 30min)

app_budget_daily_usd

  • Type: number
  • Default: 10
  • Description: Daily AWS cost budget in USD for this stack, filtered by the configured cost allocation tag. Set to 0 to disable the budget. For AWS Organizations member accounts, activate the cost allocation tag in the management account’s Billing settings.

enable_default_dashboard

  • Type: bool
  • Default: true
  • Description: Create the default RunsOn CloudWatch dashboard. Set to false when managing a custom dashboard separately.

integration_step_security_api_key

  • Type: string
  • Default: ""
  • Sensitive: yes
  • Description: API key for StepSecurity integration (optional)

otel_exporter_endpoint

  • Type: string
  • Default: ""
  • Description: OpenTelemetry exporter endpoint for observability (optional)

otel_exporter_headers

  • Type: string
  • Default: ""
  • Sensitive: yes
  • Description: OpenTelemetry exporter headers (optional)

otel_exporter_temporality

  • Type: string
  • Default: "cumulative"
  • Allowed values: cumulative, delta
  • Description: OTLP metrics temporality: cumulative (default) or delta

otel_logs_enabled

  • Type: bool
  • Default: true
  • Description: Enable OpenTelemetry log export

otel_traces_enabled

  • Type: bool
  • Default: true
  • Description: Enable OpenTelemetry trace export

logger_level

  • Type: string
  • Default: "info"
  • Allowed values: debug, info, warn, error
  • Description: Logging level for RunsOn service (debug, info, warn, error)

extra_env_vars

  • Type: map(string)
  • Default: {}
  • Description: Additional environment variables to set on the worker service

alert_slack_webhook_url

  • Type: string
  • Default: ""
  • Sensitive: yes
  • Description: Slack webhook URL for alert notifications (optional)

enable_efs

  • Type: bool
  • Default: false
  • Description: Enable EFS file system for shared storage across runners

enable_ecr

  • Type: bool
  • Default: false
  • Description: Enable ECR repository for ephemeral Docker image storage

ecr_pull_through_cache_rules

  • Type: map(object({ ecr_repository_prefix = string upstream_registry_url = string upstream_repository_prefix = optional(string) }))
  • Default: {}
  • Description: Existing ECR pull-through cache rules to reference for runner image pulls. Create or import the regional rules outside the RunsOn module.

enable_bedrock

  • Type: bool
  • Default: false
  • Description: Enable Amazon Bedrock access for EC2 runner instances.

prevent_destroy_optional_resources

  • Type: bool
  • Default: true
  • Description: Prevent destruction of durable optional resources such as EFS. ECR contains ephemeral runner images and is force-deleted by default.

enable_waf

  • Type: bool
  • Default: false
  • Description: Enable AWS WAF for the public ingress

enable_admin_routes

  • Type: bool
  • Default: true
  • Description: Enable the admin Lambda routes (/, /setup, /setup/{proxy+}, /readyz) on the public ingress

public_ingress_web_acl_arn

  • Type: string
  • Default: ""
  • Description: Optional user-managed AWS WAFv2 Web ACL ARN to associate with the public ingress. When set, RunsOn will not manage webhook IP synchronization.