© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2021
C. Chandrasekara, P. HerathHands-on GitHub Actionshttps://doi.org/10.1007/978-1-4842-6464-5_6

6. Using Self-Hosted Runners

Chaminda Chandrasekara1   and Pushpa Herath2
(1)
Dedigamuwa, Sri Lanka
(2)
Hanguranketha, Sri Lanka
 

GitHub provides hosted runners, or in other words, Windows, Linux, and macOS machines, as workflow runners. Hosted runner information can be found at https://github.com/actions/virtual-environments/tree/main/images. A VM runner–supported software list is specified in the readme.md file in each repo folder.

You may have specific software needs to build and deploy your applications. You may want to deploy to an on-premises environment utilizing GitHub Actions workflows. To cater to your needs, you can set up your machines or virtual machines as runners for GitHub Actions.

Setting up a Windows Self-Hosted Runner

Self-hosted runners provide greater control of the hardware, operating systems, and installed software tools than GitHub hosted-runners. You can set up self-hosted runners in physical machines, virtual machines, on-premises networks, or cloud-hosted virtual machines, offering wide flexibility in tools and capabilities.

Self-hosted runners can be added at different levels in GitHub.
  • Repository level: Runners are dedicated to a given repo and cannot be used by other repos.

  • Organization level: You can run jobs in multiple repos within a GitHub organization.

  • Enterprise level: Runners can run jobs for multiple repos from multiple organizations in an enterprise GitHub account.

Let’s look at the steps required to add a self-hosted runner to a repository. However, be careful not to add a self-hosted runner to a public repository because it would be a risk to your machine or the network where your machine exists. Forks in your public repos can execute malicious code by utilizing a pull request.

To follow this exercise of setting up a self-hosted runner on a Windows 10 virtual machine and deploying it to an Azure web app, you need to have the following prerequisites.
  • A GitHub repo with a .NET Core web app

    The following example uses a .NET 5.0 web app.

    You can create a new .NET 5 web app by using the following command in a Visual Studio (VS) Code terminal if the .NET 5 SDK us available.

dotnet new webapp -f net5.0 --name mynet5app
  • A Windows 10 VM in Azure

  • An Azure .NET 5 web app hosted on Windows (Linux is fine.)

In enterprise, organization, or repo settings, you have the Actions tab, where you can set up a self-hosted runner (see Figure 6-1).
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig1_HTML.jpg
Figure 6-1

Add runner

Once you click the “Add runner” button, you see instructions on how to download, configure, and use the runner in your workflows. Since we are using a Windows 10 virtual machine, we should follow the Windows instructions to set up a self-hosted runner. The first step is to create a folder to keep the runner files. It is recommended to use a folder in your drive root.
// Create a folder under the drive root
mkdir actions-runner; cd actions-runner
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig2_HTML.jpg
Figure 6-2

Create folder for runner files

Next, you need to download the runner files to your machine using the following command.
// Download the latest runner package
$ Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v2.274.2/actions-runner-win-x64-2.274.2.zip -OutFile actions-runner-win-x64-2.274.2.zip
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig3_HTML.jpg
Figure 6-3

Download runner

Next, extract the files of the runner. You can list the files by directory. Note that config.cmd and run.cmd are similar to Azure DevOps self-hosted agent installation files (see Figure 6-4).
// Extract the installer
$ Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD/actions-runner-win-x64-2.274.2.zip", "$PWD")
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig4_HTML.jpg
Figure 6-4

Extract installer

This completes the download phase.

The next phase configures the runner in the machine. Execute config.cmd. You are prompted for the required information.

Provide your GitHub repo’s URL. The registration token information is found in the Add runner documentation, as shown in Figure 6-5.
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig5_HTML.jpg
Figure 6-5

Runner register token

Next, provide a name for the work folder. You can configure the runner to run as a service. That is the best option because it gives the runner more robustness. Provide a user account and password for the runner service, and complete the self-hosted runner configuration (see Figure 6-6).
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig6_HTML.jpg
Figure 6-6

Configure runner

You can see that the runner is idle in Settings ➤ Actions (see Figure 6-7).
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig7_HTML.jpg
Figure 6-7

Self-hosted runner

Even if you skipped adding labels when creating your self-hosted runner, you can add them later in GitHub Repo Settings ➤ Actions (or in organization settings if you have set up the runner at the organization level) (see Figure 6-8).
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig8_HTML.jpg
Figure 6-8

Add label

Once you set up the label, you can use it to execute jobs using the self-hosted runner, as follows.
runs-on: win10demorunner
An example workflow job to build and deploy a .NET 5 web app using a self-hosted runner is shown next. To allow the workflow to successfully deploy the application, create a secret named MYNET5WEBAPPPUBLISHPROFILE in the repo. The content of the publish profile from the Azure web app is a prerequisite.
on: [workflow_dispatch]
name: Net5BuildDeploySelfHostedWindowsRunner
jobs:
  build-and-deploy:
    runs-on: win10demorunner
    steps:
    - uses: actions/checkout@master
    - name: Set up .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: '5.0.100'
    - name: Build with dotnet
      run: dotnet build  .\mynet5app\mynet5app.csproj --configuration Release
    - name: dotnet publish
      run: dotnet publish .\mynet5app\mynet5app.csproj -c Release -o ${{env.DOTNET_ROOT}}/myapp --no-build --no-restore
    - name: Deploy to Azure Web App
      uses: azure/webapps-deploy@v1
      with:
        app-name: 'app-githubact-demo'
        slot-name: 'production'
        publish-profile: ${{ secrets.MYNET5WEBAPPPUBLISHPROFILE }}
        package: ${{env.DOTNET_ROOT}}/myapp
You may encounter a script execution policy error in your workflow when you use a Windows self-hosted runner for the first time (see Figure 6-9).
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig9_HTML.jpg
Figure 6-9

Script run policy error

To fix this issue, execute a Set-ExecutionPolicy RemoteSigned command in an administrative PowerShell window in the self-hosted runner machine so that scripts downloaded from the Internet with a digital signature from a trusted publisher can run (see Figure 6-10).
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig10_HTML.jpg
Figure 6-10

Setting a script execution policy

Now it is possible to run the workflow in the self-hosted runner, as shown in Figure 6-11.
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig11_HTML.jpg
Figure 6-11

Workflow in the self-hosted runner

Setting up a Linux Self-Hosted Runner

Now that you know how to set up a self-hosted runner on the Windows platform, it is worth exploring setting up a runner on the Linux platform. The same .NET 5 application code and workflow should be usable in a Linux runner because .NET 5 can run on any platform. We strongly recommend that you reread the previous section before trying the steps in this section.

As prerequisites, get the following items ready.
  • A GitHub repo with a .NET Core web app

    The following example uses a .NET 5.0 web app. You can create a new .NET 5 web app by using the following command in a VS code terminal if you have .NET 5 SDK available.

dotnet new webapp -f net5.0 --name mynet5app
  • An Ubuntu 18.04 LTS VM in Azure

    Make sure that SSH is allowed and that you download the private key while creating the VM.

  • An Azure .NET 5 web app hosted on Windows or Linux

Use SSH to connect to the Linux VM. Next, download the files required to set up a self-hosted runner. Create a folder using a command similar to the following.
// Create a folder
$ mkdir actions-runner && cd actions-runner
Then download the package, as shown next.
// Download the latest runner package
$ curl -O -L https://github.com/actions/runner/releases/download/v2.274.2/actions-runner-linux-x64-2.274.2.tar.gz
The next step is to extract the package, as follows.
// Extract the installer
$ tar xzf ./actions-runner-linux-x64-2.274.2.tar.gz
All three steps are shown in Figure 6-12.
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig12_HTML.jpg
Figure 6-12

Download self-hosted runner installer

To begin the install, run ./config.sh

Provide the URL and the token found in Settings ➤ Actions ➤ Add runner (see Figure 6-13).
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig13_HTML.jpg
Figure 6-13

Configuration token

Provide a name and any additional labels, then complete the runner’s configuration (see Figure 6-14).
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig14_HTML.jpg
Figure 6-14

Configure self-hosted runner in Linux

The self-hosted runner is registered. It is still offline because it has not started yet (see Figure 6-15).
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig15_HTML.jpg
Figure 6-15

Self-hosted Linux runner

To start the runner, run the following command.
./run.sh
Once the runner is online, it is possible to add a label, if required (see Figure 6-16).
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig16_HTML.jpg
Figure 6-16

Adding a label

Even though we can run the runner by using./run, it is better to install it as a service and run it as a service. First, stop the runner, if it is already running, by pressing Ctrl C (see Figure 6-17).
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig17_HTML.jpg
Figure 6-17

Running the runner and stopping the runner

To install the runner as a service on Linux, run the following command.
sudo ./svc.sh install
Next, run the following command to start the runner as a service (also see Figure 6-18).
sudo ./svc.sh start
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig18_HTML.jpg
Figure 6-18

Install and run the runner as a service

To check the runner’s state, use the following command.
sudo ./svc.sh status
If you need to stop and uninstall the runner service, use the following commands.
sudo ./svc.sh stop
sudo ./svc.sh uninstall

While the runner is running as a service, it is available as idle to the repo, organization, or enterprise, based on the level you set up.

Like a Windows runner, you can set up a build and deployment workflow on a self-hosted Linux runner using a label to point to the runner.
runs-on: linuxdemorunner
The following is the full workflow code. The secret is defined to keep the Azure web app’s publish-profile content.
on: [workflow_dispatch]
name: Net5BuildDeploySelfHostedLinuxRunner
jobs:
  build-and-deploy:
    runs-on: linuxdemorunner
    steps:
    - uses: actions/checkout@master
    - name: Set up .NET Core
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: '5.0.100'
    - name: Build with dotnet
      run: dotnet build  **/mynet5app.csproj --configuration Release
    - name: dotnet publish
      run: dotnet publish **/mynet5app.csproj -c Release -o ${{env.DOTNET_ROOT}}/myapp --no-build --no-restore
    - name: Deploy to Azure Web App
      uses: azure/webapps-deploy@v1
      with:
        app-name: 'app-githubact-demo'
        slot-name: 'production'
        publish-profile: ${{ secrets.MYNET5WEBAPPPUBLISHPROFILE }}
        package: ${{env.DOTNET_ROOT}}/myapp
The build and deployment runs on a self-hosted Linux runner when the workflow is run (see Figure 6-19).
../images/502534_1_En_6_Chapter/502534_1_En_6_Fig19_HTML.jpg
Figure 6-19

Running a workflow on self-hosted Linux runner

This section discussed the steps required to set up a self-hosted Linux runner on GitHub and build and deploy a .NET 5 application using a self-hosted Linux runner. Setting up on macOS is almost the same as a Linux setup.

Summary

This chapter explored self-hosted runners, which you can use for GitHub Actions workflows. Self-hosted runners are useful for running workflows when specific software is needed to build and deploy projects. Like Azure DevOps self-hosted agents, self-hosted runners can deploy to on-premise environments behind a corporate firewall, where there is no line of sight for GitHub-hosted runners.

The next chapter discusses publishing packages from GitHub workflows.