GitHub Actions : Deploy Self-Hosted runners using Azure Bicep

Amine Charot
4 min readJul 3, 2022

Hey everyone ! I hope you are doing well !

Today’s post is about GitHub Actions and Azure Bicep.

GitHub Actions is a continuous integration and continuous delivery platform that allows you to create and automate your integration and deployment pipelines.

GitHub Actions pipelines run on what we call “Runners” which are servers that run a triggered workflow. We have two types of runners :

  • GitHub-Hosted runners :

GitHub provides Ubuntu Linux, Microsoft Windows and macOS runners to run a workflow; Each workflow executes in a fresh, newly-provisioned virtual machine. Using GitHub Hosted runners has some benefits :

  • Are managed and maintained by GitHub.
  • Provide a clean instance for every job execution.
  • Use free minutes on your GitHub plan, with per-minute rates applied after surpassing the free minutes.

However, when we work in a secure environment, having a GitHub-Hosted runner is not an option since we don’t have a highly configurable way to run workflows in our own custom environment. Here the self-hosted runners come in the game.

  • Self-Hosted Runners :

by using Self-Hosted Runners :

  • You are responsible for updating the operating system and all other software.
  • Can use cloud services or local machines that you already pay for.
  • Are customizable to your hardware, operating system, software, and security requirements.
  • Don’t need to have a clean instance for every job execution.
  • Are free to use with GitHub Actions, but you are responsible for the cost of maintaining your runner machines.

In this article, we are going to see how to deploy Self-Hosted Runners using Azure Bicep.

How to deploy Self Hosted Runners using Azure Bicep

We can configure GitHub Self Hosted Runners at three levels :

  • GitHub Enterprise
  • GitHub Organization
  • GitHub Repository

For this post, we will deploy the Self Hosted Runners at GitHub Organization level. Before starting on this journey, we will need an Organization :

If you navigate to Settings=> Actions => Runner Groups. You will find a default one and it will be our main Runner Group.

Now we will deploy the following architecture :

A Virtual Machine that contains the agent and a Key Vault that contains the required secrets :

  • vmPassword : The Password of the Virtual Machine
  • githubToken : The token used to add and configure the Runner

the challenge is to have a way to dynamioally create runners, a configuration file that will contains several information about it, something like :

The important part is the runnerConfigurations . It is an array of objects, each instance will reprensent a group of runners inside an organization.

In this example, we want to deploy for the Organization githubRunner001 a runner of version 2.294.0.

Then, we have the secretConfiguration object which represent the information about the Key Vault where we stored the secrets that we talked about earlier.

Note : you may improve this JSON configuration, it is just an example.

Let’s talk Bicep, we are using a Module that deploys the Vnet, subnet and the Virtual Machines :

We also have a main bicep that calls this module using the configuration above.

You may find the code in my GitHub Repos : githubRunner001/selfHostedRunner

In order to the deploy the agent, we are using a cloud-init so we can download it, install it and configure it :

We have some variables :

{0} : The version of the agent that we got from the configuration file

{1} : The organization name that we got from the configuration file.

{2} : The token that we got from the Key Vault, using the function GetSecret

vaultUtilities[i].getSecret(runnerConfiguration.secretConfiguration.tokenSecretName)

We are replacing these variables using the format function.

var customData = loadTextContent('../config/cloudInit')var finalCustomData = format(customData,runnerVersion,organizationName,githubToken)

Create a CICD pipeline to deploy the Self-Hosted Runners

Now that our code is ready, when to create a pipeline so we can enable the continuous deployment. To do so, we are using GitHub Actions with the following pipeline :

The first step is used to connect to Azure then the second step to deploy the Self Hosted Runner :

Once the workflow is finished, we should see a new Resource Group called : rgSelfHostedAgent as the configuration mention it, inside this Resource Group, you will find all the resources that we talked about :

Finally, by checking the Self Hosted Runners at GitHub side, we should see it enabled :

That’s all for today, this post will have a second part which will show you how to use this Self Hosted Runner.

Thank you all !

--

--