GitHub Actions Self-Hosted Runners Overview
Introduction to GitHub Actions Self-Hosted Runners Explained

Implementation Plan: Migrating to Self-Hosted GitHub Actions Runners on AWS
1.0 Introduction: Rationale for Transitioning to Self-Hosted Runners
This document outlines a phased implementation plan for migrating specific project workflows from GitHub-hosted runners to a self-hosted runner infrastructure on AWS. This transition is a strategic initiative to gain greater control, enhance security, and meet specialized performance requirements that are not addressable by the standard, GitHub-managed execution environments. For projects with stringent security protocols or unique resource needs, establishing a self-hosted runner is a critical step toward building a robust and compliant CI/CD pipeline.
The decision to adopt self-hosted runners is driven by three primary business and technical imperatives:
Enhanced Security: For applications handling sensitive data, such as those in the banking sector, executing code within a third-party, multi-tenant environment poses an unacceptable security risk. Self-hosted runners provide a dedicated, isolated environment where the team has full control over the infrastructure, network access, and data handling, ensuring that proprietary code and build artifacts remain within a trusted boundary.
Support for Private Repositories: Enterprise projects often involve proprietary codebases hosted in private GitHub repositories. These projects cannot utilize the free tier of GitHub-hosted runners available to public, open-source projects. A self-hosted runner provides the necessary secure and private execution environment for these repositories.
Custom Resource and Dependency Requirements: Many projects have requirements that exceed the specifications of standard GitHub-hosted runners. This can include the need for significant computational resources (e.g., "32GB RAM for end-to-end tests") or the installation of specialized software packages, libraries, and dependencies not included in the default runner images. Self-hosted runners offer complete control over the machine's configuration, allowing for customization to meet any project-specific needs.
Successfully implementing a self-hosted runner requires a properly configured cloud environment. The following section details the essential prerequisites for this plan.
2.0 Prerequisites
Before beginning the migration, the team must ensure a baseline environment is in place. Fulfilling these prerequisites will facilitate a smooth and predictable implementation process, minimizing potential configuration issues.
Existing GitHub Project: A project must already exist on GitHub containing a functional GitHub Actions workflow. This workflow should currently be configured to use a standard GitHub-hosted runner, such as ubuntu-latest. This ensures a working baseline from which to migrate.
AWS Account: An active AWS account is required, with IAM permissions sufficient to create and manage EC2 instances and their associated Security Groups.
Key Pair for EC2 Access: An existing AWS EC2 key pair must be available within the target AWS region. This key pair is essential for establishing a secure SSH connection to the provisioned instance to perform the runner installation.
With these prerequisites confirmed, the first phase of the implementation—provisioning the core infrastructure—can begin.
3.0 Phase 1: Infrastructure Provisioning and Security Configuration
The goal of this phase is to launch a new AWS EC2 instance that will serve as the dedicated runner and to configure its network security to permit essential communication with GitHub. This involves creating precise traffic rules to allow the runner to receive jobs and report status updates.
3.1. EC2 Instance Launch
Follow these steps to provision the virtual machine that will host the runner agent:
Navigate to the EC2 console in your AWS account and select Launch Instance.
Assign a descriptive name to the instance for easy identification (e.g., GitHub).
Select an appropriate Amazon Machine Image (AMI). An Ubuntu image is a suitable choice.
Accept the default instance type configuration for this initial setup.
In the "Key pair (login)" section, select your pre-existing key pair to enable SSH access.
3.2. Network Security Group Configuration
Correctly configuring the Security Group is critical for the runner's operation. The instance must be able to receive job requests from GitHub (inbound traffic) and send status, logs, and artifacts back (outbound traffic).
Create or modify the instance's Security Group to include the following rules. Note: While the source material mentions port 18 for HTTP, this is a non-standard assignment; we will use the correct, universally recognized port 80.
Required Security Group Rules | Traffic Type | Protocol/Port | Source/Destination | | :--- | :--- | :--- | | Inbound | HTTP (80) | Anywhere (0.0.0.0/0) | | Inbound | HTTPS (443) | Anywhere (0.0.0.0/0) | | Outbound | HTTP (80) | Anywhere (0.0.0.0/0) | | Outbound | HTTPS (443) | Anywhere (0.0.0.0/0) |
WARNING: Avoid using permissive rules like "All traffic" for the source or destination. While convenient, this practice exposes unnecessary ports and creates a significant security vulnerability. Restrict traffic exclusively to the HTTP and HTTPS ports required for communication with GitHub's services.
With the EC2 instance launched and its network security properly configured, the next phase is to install the GitHub Actions runner software on the instance.
4.0 Phase 2: Runner Installation and Registration
This phase involves connecting to the provisioned EC2 instance and executing a series of commands provided by GitHub. These commands will download the runner agent, configure it with a repository-specific token, and register it as an available self-hosted runner for the target repository.
Follow this step-by-step process to install and register the runner:
In your web browser, navigate to the target GitHub repository and go to Settings > Actions > Runners.
Click the New self-hosted runner button.
On the configuration page, select the appropriate operating system (Linux) and architecture (e.g., AMD64) that matches the EC2 instance.
Using an SSH client, connect to your newly created EC2 instance using its public IP address and the key pair selected during launch.
Once connected, carefully copy and execute the commands provided by GitHub one by one in the EC2 instance's terminal. These commands download the runner agent, verify its integrity, and configure it for your repository.
Execute the final script provided, ./run.sh, which starts the runner agent and connects it to GitHub.
Confirm that the terminal output on the EC2 instance displays the message "listening for jobs". This indicates a successful connection and that the runner is ready to receive workflow tasks.
Now that the runner is installed and listening, the final phase is to modify the workflow file to direct jobs to this new runner.
5.0 Phase 3: Workflow Migration and Verification
The final step is to update the project's CI workflow file, instructing GitHub Actions to use the newly configured self-hosted runner instead of a default GitHub-hosted one. This section also covers the end-to-end verification process to confirm the entire setup is functioning correctly.
5.1. Updating the Workflow File
Modify the workflow's YAML file to target the self-hosted runner:
In the GitHub repository, navigate to the .github/workflows/ directory.
Open the relevant action's .yml file for editing (e.g., first-actions.yml).
Locate the runs-on: key within the job definition.
Change the existing value from the GitHub-hosted runner label (e.g., ubuntu-latest) to self-hosted.
Commit the changes directly to the repository's main branch to trigger the workflow.
5.2. Verifying the Implementation
The commit made in the previous step will trigger the workflow, allowing for a complete verification of the migration.
Trigger: The on: push directive in the workflow file ensures that the commit automatically triggers a new workflow run.
Observe GitHub: A yellow dot will appear next to the commit hash in the GitHub repository UI, indicating that the job is queued and waiting for a runner.
Observe the Runner: Check the SSH terminal connected to the EC2 instance. You will see new log output as the runner picks up the job, such as "Running job: build...". This confirms the job was successfully dispatched to your self-hosted runner.
Confirm Completion: As the job completes, the runner agent sends a status notification back to GitHub. This communication is enabled by the outbound traffic rules configured in Phase 1.
Final Verification: The yellow dot in the GitHub UI will turn into a green checkmark, providing a clear visual confirmation that the job was executed successfully from end-to-end on the self-hosted runner.
This final green checkmark confirms the successful migration of the workflow to the self-hosted runner on AWS.