This article is part 2 of my series on GitHub self-hosted runners. In part 1 I created a Hyper-V virtual machine, installed Ubuntu Server 20.04, and set up the GitHub runner.

I then tested the runner by creating a new GitHub workflow that runs “Hello World”. Notice the “workflow_displatch” event. This supports manually running workflows.

At the virtual machine, the following output is displayed when running the workflow:

The output from the workflow is stored in GitHub and can be viewed in the GUI and the logs.

Now that I know that you can run a workflow in the self-hosted runner, what can we accomplish via runners? Let’s try patching Ubuntu.

Create a new GitHub Workflow and paste the following code. Name the file “.github/workflows/01-update-ubuntu.yml”. The reason for this name will be clear later in this article. Also note “workflow_call” in the “on” event.

In the GitHub GUI, go to Actions. Click on the workflow that you just created. Click on the button “Run workflow”. In the popup dialog click “Run workflow”. Notice that the run is “in progress” and does not complete”.

In the ssh session connected to the virtual machine, notice that the runner is displaying:

The running is prompting for the user’s password in order to run sudo. Enter the password. The runner now completes successfully after a minute or two.

Sudo Password Problem

The issue with the previous workflow pausing to receive password input is caused by sudo requiring the user to enter its password. This can be solved by removing the requirement for a password for this user to run sudo.

In the Ubuntu terminal session, start visudo:

Add the following line. Replace jhanley with your username:

Run the workflow again and verify that a password is not required.

This brings up an item to consider. I am running the GitHub runner as my user identity “jhanley”. Next time, I would create a new user named something like “ghrunner”. I have not yet configured the running as a Linux service, but the identity will probably be important for that step as well.

Installing Packages

I want my runner to be able to build, test and deploy applications written in .NET, Python and PHP as well as build applications in containers. Installing applications and packages can be tedious. Since we can create and run GitHub workflows on the runner, we can put these scripts and their execution under source code control.

If you create separate GitHub workflows for each application or package, you will quickly have a directory full of workflow files. Creating a naming convention to simplify what type of workflow but also the order that the workflows should run which configuring a new running.

I start the workflow file name with “0” to indicate runner setup workflows. For example “01-update_ubuntu.yml”, 02-docker-install.yml”, etc.

Installing Docker

Create a new GitHub Workflow and paste the following code. Name the file “.github/workflows/02-docker-install.yml”. The reason for this name will be clear later in this article. Also, note “workflow_call” in the “on” event.


  • The username is hardcoded in the workflow. This should be moved to a variable.

The Docker install workflow first checks if Docker is already installed, and if true updates it instead of trying to install again:

If Docker is not installed, then it is installed:

The user “jhanley” is added to the sudo group so that password prompts are not required to run Docker commands:

Calling Workflows from another Workflow

GitHub supports calling one workflow from another. You can create one workflow that then calls a series of workflows. This could be used to set up a GitHub self-hosted runner with the required packages for a particular type of runner. For example, a runner setup with Docker and PHP 8.0, another runner setup with .NET Core 5.

Reusing workflows

For a workflow to be reusable, the values for the “on” event must include workflow_call.

Let’s create a workflow that calls the previous two workflows. This will update Ubuntu and install Docker. This can then be extended to call additional workflows as we build our library of workflows.

Create a new GitHub Workflow and paste the following code. Name the file “.github/workflows/00-setup-runner.yml”.


  • I am not sure why GitHub requires the full path to the workflow which includes the repository owner and repository name. When calling one workflow from another workflow, it would make sense to be able to just specify the workflow file name.
  • The workflow has hardcode names. These should also be moved to variables.

More Information


This was an interesting exercise. The power of GitHub Workflows and Self-Host Runners is very interesting. There are many tools to automate building systems, such as Terraform which is now of my favorites. I can imagine GitHub extending its workflows and actions to step on the features by many third-party tools. Imagine if Microsoft bought HashiCorp and merged Terraform into the GitHub family. Would the market accept that monopoly? Would the two platforms be better together or separate?

Once I have more experience with self-hosted runners and have written more runner package installation workflows, I will publish them as a GitHub repository.

Photography Credit

I write free articles about technology. Recently, I learned about which provides free images. The image in this article is courtesy of Magda Ehlers at Pexels.