docs/dev/how_to/github-runner-setup-guide.md
This guide provides instructions for setting up self-hosted GitHub runners on both Windows (using PowerShell) and Linux (using Bash and Azure CLI). Self-hosted runners allow you to run GitHub Actions workflows on your own infrastructure.
Side Note: Internally on the Chef team, we use Github hosted Windows runners already. There is no need to spin up a new runner in that use case. However, for FIPS testing, we need to create our own Linux runners using an OS like Ubuntu with the Pro subscription and then configure it to be FIPS enabled.
repo scope (for repository-level runners) or admin:org scope (for organization-level runners)Github also allows you to create a token to execute the runner with that does not require your PAT. Do this to get a spiffy token:
gh api --method POST /repos/chef/chef/actions/runners/registration-token \
--header 'Accept: application/vnd.github+json' \
--header 'X-GitHub-Api-Version: 2022-11-28'
C:\actions-runner)# Create directory for the runner
New-Item -ItemType Directory -Path "C:\actions-runner" -Force
Set-Location "C:\actions-runner"
# Download the latest runner (replace with your desired version)
$runnerVersion = "2.317.0" # Check https://github.com/actions/runner/releases for latest
$url = "https://github.com/actions/runner/releases/download/v$runnerVersion/actions-runner-win-x64-$runnerVersion.zip"
Invoke-WebRequest -Uri $url -OutFile "actions-runner.zip"
# Extract the runner
Expand-Archive -Path "actions-runner.zip" -DestinationPath "." -Force
Remove-Item "actions-runner.zip"
# Configure the runner (replace with your actual values)
$repoUrl = "https://github.com/chef/chef" # For repo-level runner
# OR for organization-level: $orgUrl = "https://github.com/your-org"
$token = "YOUR_REGISTRATION_TOKEN_HERE"
$runnerName = "windows-runner-01"
# Run configuration
.\config.cmd --url $repoUrl --token $token --name $runnerName --work "_work" --labels "windows,self-hosted"
# Install as a service (requires admin privileges)
.\svc-install.ps1
# Start the service
Start-Service actions.runner.*
# Verify the service is running
Get-Service actions.runner.*
az login
az account set --subscription "your-subscription-id"
az group create --name "github-runners-rg" --location "eastus"
# Create VM with Ubuntu (recommended for GitHub runners)
az vm create \
--resource-group "github-runners-rg" \
--name "github-runner-linux" \
--image "Ubuntu2204" \
--admin-username "runneradmin" \
--generate-ssh-keys \
--size "Standard_B2s" \
--public-ip-sku "Standard" \
--tags "purpose=github-runner"
# Open SSH port (if not already open)
az vm open-port --resource-group "github-runners-rg" --name "github-runner-linux" --port 22
# Get VM public IP
VM_IP=$(az vm show --resource-group "github-runners-rg" --name "github-runner-linux" --show-details --query [publicIps] -o tsv)
echo "VM IP: $VM_IP"
# SSH into the VM (replace 'azureuser' with your actual VM admin username)
ssh azureuser@$VM_IP
# Update system and install dependencies
sudo apt update
sudo apt upgrade -y
sudo apt install -y curl wget unzip jq
# Create runner user (optional, for security)
sudo useradd -m -s /bin/bash runner
sudo usermod -aG sudo runner
# Note: Do not set a password for the runner account. Instead do this:
sudo visudo
# now add this to the list:
runner ALL=(ALL) NOPASSWD:ALL
# Ctrl-O, Ctrl-X to save and exit
# Switch to runner user for the rest of the setup
sudo -u runner mkdir -p /home/runner/actions-runner
sudo su - runner
# Download latest runner (run as runner user)
sudo -u runner bash << 'EOF'
cd /home/runner/actions-runner
# Get latest release version
RUNNER_VERSION=$(curl -s https://api.github.com/repos/actions/runner/releases/latest | jq -r '.tag_name' | sed 's/v//')
echo "Latest runner version: $RUNNER_VERSION"
# Download and extract
curl -o actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz -L https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz
tar xzf ./actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz
rm actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz
EOF
# SSH back to VM
ssh runneradmin@$VM_IP
# Configure runner (replace with your values)
REPO_URL="https://github.com/chef/chef"
<!-- cspell:disable -->
TOKEN="ABFBQT5WJE4YTDVFEL3EMBDJCX7CS"
<!-- cspell:enable -->
RUNNER_NAME="ubuntu-2404-pro-fips-tester"
sudo -u runner bash << EOF
cd /home/runner/actions-runner
./config.sh --url $REPO_URL --token $TOKEN --name $RUNNER_NAME --work _work --labels "ubuntu-2404-pro-fips-tester,linux,self-hosted" --unattended
EOF
# Install as service. Since we added the NOPASSWD settings to the runner user account, we pass the '-n' flag in when we start the service, otherwise bad things happen.
sudo -u runner bash << 'EOF'
cd /home/runner/actions-runner
sudo ./svc.sh install
sudo -n ./svc.sh start
EOF
# Verify service is running
sudo -u runner bash << 'EOF'
cd /home/runner/actions-runner
sudo ./svc.sh status
EOF
C:\actions-runner\_diag\*.log/home/runner/actions-runner/_diag/*.logFor more detailed troubleshooting, refer to the GitHub Actions documentation.