macOS Self-Hosted GitHub Runner

Looking to cut down on CI/CD costs? Setting up self-hosted runners on macOS 15+ for GitHub Actions can significantly reduce your reliance on expensive GitHub-hosted runners. This guide walks you through the entire process: configuring runners as background services, optimizing workflows to prioritize self-hosted runners, and troubleshooting common setup issues. Whether you're managing large-scale pipelines or running resource-intensive jobs, this approach helps you take full control of your infrastructure while keeping expenses in check. Ideal for developers focused on efficiency and cost-effectiveness.

Pascal Bayer

Pascal Bayer

10 min read
Migrating to GitHub offers numerous advantages, but it also presents opportunities to optimize your workflow environment. In our journey, we aimed to reduce operational costs without sacrificing the flexibility required for our continuous integration and deployment (CI/CD) processes. By setting up self-hosted runners on macOS 15+, we gained control over our build environment while managing expenses effectively. This guide will walk you through the steps we took, the challenges we faced, and how you can implement a similar setup.

Introduction

In an effort to optimize costs while maintaining the flexibility of our CI/CD pipelines, we decided to set up self-hosted runners on macOS after migrating from Bitbucket to GitHub. Self-hosted runners allow us to use our own infrastructure (using all the idle capacity of our powerful developer MacBooks) for running GitHub Actions workflows, which can lead to significant cost savings, especially when dealing with resource-intensive tasks or macOS-specific builds.
However, the process wasn't without its hurdles. We encountered several challenges, particularly with setting up the runners as services on macOS 15+. This guide aims to help you navigate these challenges and set up your own self-hosted runners efficiently.

General Setup of a Self-Hosted Runner

Setting up a self-hosted runner involves adding the runner to your GitHub organization and configuring it on your macOS machine.

Adding a Self-Hosted Runner to Your Organization

  1. Navigate to Your Organization on GitHub :

    • Go to the main page of your GitHub organization.
    • Under your organization name, click on Settings .

  2. Access Runners Settings :

    • In the left sidebar, click Actions .
    • Then, click on Runners .

  3. Add a New Runner :

    • Click New runner , then select New self-hosted runner .

  4. Choose Operating System and Architecture :

    • Select macOS as the operating system.
    • Choose the appropriate architecture (usually x64 ).

  5. Follow Setup Instructions :

    • GitHub will provide you with a series of shell commands.
    • Open a terminal on your macOS machine.
    • Run each command in order to download and configure the runner application.

Verifying the Runner

After completing the setup:
  • Ensure the runner is listed under Runners in your organization's settings.
  • The terminal should display:
  • Code kopieren
  • √ Connected to GitHub [Timestamp]: Listening for Jobs
This means your runner is active and ready to accept jobs.

Configuring the Runner as a Service on macOS 15+

Running the self-hosted runner as a service ensures it starts automatically and runs in the background.

Installing the Service

Stop the Runner Application :

If the runner is currently running, stop it by pressing Ctrl + C in the terminal.

Install the Service

Navigate to your runner's directory in the terminal.
Run the following command:
    
./svc.sh install

Starting the Service

Start the service with:
    
./svc.sh start

Checking the Service Status

Check if the service is running correctly:
    
./svc.sh status

Stopping and Uninstalling the Service

Stop the Service

    
./svc.sh stop

Uninstall the Service

    
./svc.sh uninstall

Prioritizing Self-Hosted Runners in Workflows

To optimize resource usage, you can configure your workflows to prioritize self-hosted runners but fall back to GitHub-hosted runners if none are available.

Modifying Your Workflow YAML

Add the following jobs to your workflow file:
    
jobs: check-runner: runs-on: ubuntu-latest outputs: runner-label: ${{ steps.set-runner.outputs.runner-label }} env: GH_TOKEN: ${{ secrets.ORG_RUNNER_STATUS_ACCESS_TOKEN }} steps: - name: Set runner id: set-runner run: | runners=$(gh api -H "Accept: application/vnd.github+json" /orgs/${{ github.repository_owner }}/actions/runners) available=$(echo "$runners" | jq '.runners[] | select(.status == "online" and .busy == false and .labels[] .name == "self-hosted")') if [ -n "$available" ]; then echo "runner-label=self-hosted" >> $GITHUB_OUTPUT else echo "runner-label=ubuntu-latest" >> $GITHUB_OUTPUT fi your-job: needs: check-runner runs-on: ${{ needs.check-runner.outputs.runner-label }} steps: # Your job steps here

Explanation

Check-Runner Job

Checks if any self-hosted runners are online and not busy. Sets runner-label to self-hosted if available, otherwise ubuntu-latest .

Your-Job :

Specifies runs-on dynamically based on runner-label . Ensures your job uses a self-hosted runner if available.

Setting Up Organization Secrets

Create an Access Token :

Generate a Personal Access Token (PAT) with read access to organization self hosted runners : https://github.com/settings/tokens?type=beta . This token is used to authenticate GitHub CLI commands in your workflow.

Add the Token to Organization Secrets :

Go to your organization settings on GitHub. Navigate to Secrets and variables > Actions > New organization secret . Name it ORG_RUNNER_STATUS_ACCESS_TOKEN and paste your PAT.

Common Pitfalls and Solutions

During our setup, we faced several issues. Here's how to solve them.

1. Permission Issues with Installing the Service

Problem :

Running ./svc.sh install fails due to permission issues with LaunchAgents .

Solution :

Grant read/write permissions to your user for the LaunchAgents directory:
    
sudo chown -R $(whoami) ~/Library/LaunchAgents/

2. Runner Not Showing as "Online"

Problem :

The runner remains offline, and the stderr.log file shows:
    
shell-init: error retrieving current directory: getcwd: cannot access parent directories: Operation not permitted /bin/bash: /path/to/actions-runner/runsvc.sh: Operation not permitted

Solution :

Grant Full Disk Access to Bash :
  1. Open System Preferences > Security & Privacy > Privacy tab.

  2. Scroll down and select Full Disk Access .

  3. Click the lock icon to make changes and authenticate.

  4. Click the + button to add an application.

  5. Press Command + Shift + . to reveal hidden folders.

  6. Navigate to /bin and select bash .

Reinstall the Service :
Stop and uninstall the service:
    
./svc.sh stop ./svc.sh uninstall
Reinstall and start the service:
    
./svc.sh install ./svc.sh start

Conclusion

By setting up self-hosted runners on macOS 15+, we achieved significant cost savings without compromising on the flexibility of our CI/CD pipelines. This hybrid approach allows us to utilize our own infrastructure when available and seamlessly fall back to GitHub-hosted runners when necessary.
Key takeaways:
  • Cost Optimization : Self-hosted runners reduce reliance on paid GitHub-hosted runners, lowering operational costs.
  • Flexibility : Maintaining the ability to run workflows on GitHub-hosted runners ensures builds are not stalled due to unavailable resources.
  • Control Over Environment : Self-hosted runners provide full control over the software and hardware environment.

You Might Also Like

Discover more posts that dive deeper into similar topics. Curated to match your interests and help you explore further.

Tanja BayerAnimated character with red hair and blue eyes smiling, wearing a black top, with a potted plant in the background.

Tanja Bayer

2 min read

Introducing Nocodo

Join the Nocodo early beta and unleash your creativity with our no-code AI platform. Create applications effortlessly with our drag-and-drop interface, no programming required. Transform your ideas into reality today. Sign up now and shape the future of AI application development

Tanja Bayer

Tanja Bayer

3 min read

Building Efficient AI Chains

Discover the key differences and best use cases between LLM Chains and Retrieval Chains for efficient data insights. Learn how to build, implement, and optimize your AI chains for better information retrieval and processing.

A clean, modern interface displaying a workflow diagram on a digital dashboard. The diagram features interconnected nodes  illustrating the process of audio transcription and error correction. Icons or visuals representing audio transcription, AI technology, and no-code platforms are in the background. The color scheme should be professional and tech-oriented, with blues, whites, and grays.
Tanja BayerAnimated character with red hair and blue eyes smiling, wearing a black top, with a potted plant in the background.

Tanja Bayer

10 min read

Streamlining and Error-Correcting Audio Transcription

Streamline audio transcription with no-code workflows using OpenAI Whisper and AWS Bedrock's Claude 3. Achieve high accuracy and efficiency in transcribing and error-correcting spoken content seamlessly through Nocodo.ai's powerful integration.

Boost your productivity.
Start using Nocodo AI today.

Simplify workflows, automate tasks, and enhance productivity.
All without a single line of code.