GitHub-hosted Runners with Azure Private Networking
- Nathan
- May 26
- 5 min read
Updated: Jun 1
GitHub-hosted Runners have a few key advantages over self-hosted runners. Things like Operating System updates, security patches, and software installations are managed for you automatically. Also, they make scaling incredibly easy (both scaling out and up). Finally, the GitHub-hosted Runners are ephemeral. So, you know that after every Job the Runner is deleted, cleaning up any temporary files, logs, or sensitive data left behind by your workflow.
However, one of the biggest drawbacks of GitHub-hosted Runners is that they only have access to network resources that are available on the public internet. If you have resources in your Azure Virtual Network that use only private IP addresses, then traditionally these can not be accessed from GitHub-hosted Runners.
This problem is solved by using GitHub-hosted Runners with Azure Private Networking. With this solution, you delegate a Subnet in one of your Azure Virtual Networks and GitHub will automatically inject its GitHub-hosted Runners into that Subnet. This means the GitHub-hosted Runners will have access to all private resources that are available to that Virtual Network, including other private networks that are linked by peering, VPN Gateways, or Express Route circuits.
Note: This can be configured at the GitHub Organization level or at the GitHub Enterprise level. This post will focus solely on the GitHub Organization level. Let's discuss how to configure this below.
Architecture

Azure Configuration
There are few things that we have to do on the Azure side of things:
First, you must have a Virtual Network. You can either create a new one, or use an existing one. Note: only certain Azure regions are supported.
Second, on the Subscription that holds the Virtual Network, you must register the Resource Provider for "GitHub.Network". You can do this via the Azure Portal, or use a simple Az CLI command: az provider register --namespace GitHub.Network
Third, you must have a Subnet. You can either create a new one, or use an existing one (but it must be empty).
The Subnet must be delegated to "GitHub.Network/networkSettings" meaning it can not be used for anything else.
Keep in mind the size of the Subnet, as this will determine your maximum scale / concurrency. Note: whatever size you choose, GitHub has its own maximum concurrent jobs limit based on your plan.
If you would like to apply an NSG to this Subnet in order to limit Outbound internet access, then please see the docs for the required NSG rules.
Lastly, you must create a GitHub Network Settings resource in your Azure Subscription. It must be created in the same region as your Virtual Network. The documentation provides you with an Az CLI command that you can use to create this resource.
If you prefer Bicep instead of Az CLI, then I have created a Bicep template that you can download on my GitHub. This template only deploys the Network Settings resource, and it assumes that you already have a Subscription, Virtual Network, and Subnet created and configured, as outlined above.
In order to create this resource, you must pass in your GitHub Organization's "databaseId". You can find this value by running a GraphQL query, as outlined in the docs.
Note: by default, you will not be able to see this resource in the Azure Portal, as this is a "hidden" resource. You must select the option to 'view hidden resources' before this will show up in the Portal.
Important: once created, this Azure resource will have a special Azure Tag named "GitHubId". You must make a note of this hashed value, as it is required for the GitHub setup below. If you used my Bicep template from above, then this value will be shown to you as an "Output" of the deployment.
GitHub Configuration
For the second part of this setup, we will move over to the GitHub side of things. It is important to note that the GitHub Team or GitHub Enterprise plan is required for GitHub-hosted Runners using Private Networking. Unfortunately, GitHub Organizations that use the Free plan are not supported.
1. Network Configuration
First, we need to create a new Network Configuration in your Organization.
Go to your Organization's Settings page, then click on "Hosted compute networking" (screenshot 1).
Then, click on "New network configuration" (screenshot 2).
Next, give your configuration a name and then click on "Add Azure Virtual Network" (screenshot 3).
Finally, enter the special "GitHubId" Azure Tag that we grabbed earlier and put that into the field labeled "Network settings resource ID" (screenshot 4). The rest of the virtual network settings will be automatically filled out based on the hash value you entered.
Click "Add virtual network" and then on the next screen click "Create configuration" to complete the setup.
If you would like to automate this step, the GitHub API docs can be found here.
2. Runner Group
Next, we'll create a new Runner Group in your Organization, and we'll tie it to the Network Configuration that we just created.
Go to your Organization's Settings page, then click on "Runner groups" (screenshot 1).
Click on "New runner group". Give the Runner Group a name. Select which repos and workflows will have access to the new Runner Group. Finally, select the newly created Network Configuration (screenshot 2).
When you are done, click "Create group".
If you would like to automate this step, the GitHub API docs can be found here.
3. GitHub-Hosted Runner

The last thing we need to do is create a new GitHub-hosted Runner and attach it to the newly created Runner Group.
Go to your Organization's Settings page, then click on "Runners".
Click on "New runner" and select "New GitHub-hosted runner" (screenshot 1).
Give the Runner a name.
Select which platform to use, your options are Linux x64, Linux ARM64, Windows x64, or Windows ARM64.
Select the image to use, your options are dependent on the platform that was chosen, and can be GitHub-owned images, or partner images.
Select a size, your options are dependent on the platform, and can range from 2-core/8 GB RAM all the way up to 96-core/384 GB RAM.
Under "Permissions" make sure to select the newly created Runner Group.
Finally, click on "Create runner".
If you would like to automate this step, the GitHub API docs can be found here.
That's everything! You should now have a new Runner Group in your GitHub Organization that you can attach to your repositories. This Runner Group is made up of a GitHub-Hosted Runner which utilizes networking from your private Azure Virtual Network.
Comments