Static IPs
Static egress IPs for RunsOn Flex and Fleet runners through private subnets, NAT gateways, and Elastic IPs.
RunsOn supports static egress IPs by launching runners in private subnets and routing outbound internet traffic through NAT gateways with Elastic IPs. Use this when third-party services require IP allow lists or when CI jobs must reach private network services.
For the shared networking model and tradeoffs, see Networking.
Usage
Flex
Enable private networking support on the Flex stack, then launch jobs in private subnets with the private=true label:
jobs: deploy: runs-on: runs-on=${{ github.run_id }}/runner=2cpu-linux-x64/private=trueFleet
Fleet private networking is configured in Terraform. Enable private networking support, provide private subnets, then mark the runner definitions that should launch in private subnets:
module "runs_on_fleet" { private_mode = "true" vpc_id = module.vpc.vpc_id public_subnet_ids = module.vpc.public_subnets private_subnet_ids = module.vpc.private_subnets
runners = { deploy-static-ip = { family = ["m7i.large"] image = "ubuntu24-full-x64" private = true } }
fleets = { deploy = { runner = "deploy-static-ip" } }}See Fleet networking and IAM for the full Terraform input reference.
How it works
With the default Flex CloudFormation template, enabling Private mode makes RunsOn create private subnets for your GitHub Actions runners and provision one managed NAT Gateway. In common AWS regions, a single NAT Gateway costs about $33/month for the hourly charge alone, plus NAT data processing and standard data transfer charges. Check the AWS VPC pricing page ↗ for current pricing in your region.
Fleet is Terraform-first. You provide the VPC, public subnets, private subnets, and NAT design. The module can then launch the Fleet worker and selected runner fleets in private subnets.
The NAT Gateway is assigned an Elastic IP (EIP), a static IP address provided by AWS. This EIP becomes the source IP for outbound traffic from private runners, so egress traffic has a consistent and allow-listable IP address.
Configuration
Flex
To take advantage of private networking and static IPs in RunsOn, you need to enable this feature during the setup process, or reconfigure your stack to enable it. RunsOn handles the provisioning and configuration of the necessary AWS resources, including the assignment of the Elastic IPs to the NAT Gateways.
You switch between Public and Private mode by changing the Private CloudFormation parameter. It accepts the same four values as Fleet private_mode:
false: public subnets (default).true: jobs opt in to private subnets with theprivate=truelabel.always: jobs run in private subnets by default, unless they opt out withprivate=false.only: all jobs run in private subnets, with no opt-out.
By default, RunsOn creates the Stack in Public mode (false), because NAT gateways incur additional costs and are not needed in most cases.
If you need a different network topology, such as an existing VPC, multiple NAT gateways, or your own egress design, use the Terraform / OpenTofu install path instead of the default CloudFormation template.
Fleet
private_mode controls whether the Fleet worker and runners use private subnets:
false: use public subnets.true: run the Fleet worker privately and allow private runner fleets.always: run the Fleet worker privately and make private runners the default, unless a runner fleet opts out.only: run the Fleet worker and runners privately.
With private_mode = "true", runner fleets stay public by default. Set private = true on each runner definition that needs static egress through your NAT gateway.