Managing Self-Hosted Runners
1. Installing Runner Application
Example: Install GitHub Actions Runner on Linux
# Download the latest runner package
curl -O -L https://github.com/actions/runner/releases/latest/download/runner-linux-x64-2.300.1.tar.gz
# Extract the package
tar xzf ./runner-linux-x64-2.300.1.tar.gz
# Configure the runner
./config.sh --url https://github.com/OWNER/REPO --token TOKEN
# Run the runner in the background
nohup ./run.sh && echo $! > pid.txt
| Step | Description | Notes |
|---|---|---|
| Download Package | curl -O -L https://github.com/actions/runner/releases/latest/download/runner-linux-x64-2.300.1.tar.gz |
Use the latest stable version for security |
| Extract Package | tar xzf ./runner-linux-x64-2.300.1.tar.gz |
Ensure sufficient disk space for extraction |
| Configure Runner | ./config.sh --url https://github.com/OWNER/REPO --token TOKEN |
Token must be generated from repo settings or organization |
| Run Runner | nohup ./run.sh && echo $! > pid.txt |
Background process ensures continuous operation |
Note: Ensure the runner has appropriate permissions and network access to communicate with GitHub.
2. Configuring Runner
Example: Runner Configuration File
name: my-runner
labels:
- linux
- x64
- self-hosted
workflows: /home/user/actions-runner/_work
| Property | Description | Default Value |
|---|---|---|
| name | Unique identifier for the runner | None |
| labels | List of labels to assign to the runner | None |
| workflows | Path to the workflows directory | /home/user/actions-runner/_work |
Note: Runner labels must match the
runs-on values in your workflow YAML files.Warning: Ensure the runner has sufficient permissions to access required resources and execute workflows.
3. Running as Service
GitHub Actions self-hosted runners can be configured to run as a service on Linux systems, allowing them to start automatically when the system boots and manage their lifecycle without requiring manual intervention.
| Configuration | Description | Notes |
|---|---|---|
| service name | github-runner |
Name of the systemd service unit file |
| service file location | /etc/systemd/system/github-runner.service |
Path where the service unit file is created |
| runner executable | /home/runner/runners/2.300.0/run.sh |
Path to the runner executable (version may vary) |
Example: systemd service configuration
[Unit]
Description=GitHub Actions Runner
After=network.target
[Service]
Type=simple
User=runner
WorkingDirectory=/home/runner/runners/<runner-name>
ExecStart=/home/runner/runners/<runner-name>/run.sh
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Note: Ensure the
runner user has appropriate permissions to execute the runner binary and access required resources.
Warning: The service must be configured to run as the same user that installed and registered the runner.
Service Management Commands
sudo systemctl daemon-reload— Reload systemd configuration after changessudo systemctl enable github-runner— Enable the service to start at bootsudo systemctl start github-runner— Start the service manuallysudo systemctl status github-runner— Check current status of the service
4. Using Runner Labels
| Label | Description | Usage |
|---|---|---|
| runner.label | Assigns a label to a self-hosted runner | |
| runner.group | Groups runners under a label for organization | |
Example: Assigning Labels to Runners
name: Label Runner Example
on:
push:
branches: [ main ]
jobs:
setup:
runs-on: [ self-hosted, linux, x64 ]
steps:
- name: Setup Runner
run: |
echo "Runner configured with labels"
Note: Labels must be unique within a runner group and can include alphanumeric characters, hyphens, underscores, and periods.
5. Setting Up Runner Groups
Example: Create a Runner Group
gh runner-group create "my-runner-group" \
--organization "my-org" \
--labels "linux,ubuntu" \
--visibility "all"
| Option | Values | Description |
|---|---|---|
| --name | runner-group-name |
Name of the runner group to create |
| --organization | org-name |
Organization name to associate the group with |
| --labels | label1,label2 |
Comma-separated list of labels for runners in this group |
| --visibility | all | selected |
Who can use this runner group: all or selected |
Note: Runner groups are scoped to organizations and can contain multiple runners. Labels help categorize runners for job assignment.
Example: Add a Runner to a Group
gh runner add-to-group "my-runner" \
--runner-group "my-runner-group" \
--organization "my-org"
Runner Group Management
- Runner groups allow you to organize runners by labels and visibility.
- Groups can be assigned to specific repositories or made available organization-wide.
- Use
gh runner-groupcommands to manage groups via CLI.
6. Configuring Proxy
| Property | Value | Description |
|---|---|---|
| http_proxy | http://proxy.example.com:8080 |
HTTP proxy URL for outbound requests |
| https_proxy | http://proxy.example.com:8080 |
HTTPS proxy URL for outbound requests |
| no_proxy | localhost,127.0.0.1,.local |
Comma-separated list of hosts to bypass proxy |
Example: Setting proxy in runner configuration
runner:
http_proxy: http://proxy.example.com:8080
https_proxy: http://proxy.example.com:8080
no_proxy: localhost,127.0.0.1,.local
Note: Proxy settings must be configured before starting the runner process.
7. Using Ephemeral Runners
Ephemeral runners are self-hosted runners that are automatically provisioned and destroyed for each job. They provide a clean, isolated environment for each workflow execution.
| Property | Description | Default |
|---|---|---|
| runner.name | Name of the runner instance | Generated automatically |
| runner.id | Unique identifier for the runner | Generated automatically |
| runner.tags | Tags to identify the runner in workflows | None |
Example: Configuring Ephemeral Runner
name: Ephemeral Runner Example
on:
workflow_dispatch:
jobs:
test:
runs-on: [self-hosted, ephemeral]
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Run Test
run: |
echo "Running test on ephemeral runner"
Note: Ephemeral runners are ideal for CI/CD pipelines where each job requires a clean environment and no state persistence.
Warning: Ephemeral runners are not suitable for long-running jobs or those requiring persistent storage.
8. Setting Runner Work Directory
| Property | Value | Description |
|---|---|---|
| work | ./_work |
Directory where jobs are executed and artifacts are stored |
Example: Configuring Work Directory
name: Example Workflow
on: [push]
jobs:
build:
runs-on: self-hosted
steps:
- name: Checkout
uses: actions/checkout@v4
with:
repository: my-repo
path: ./custom-work-dir
Note: The work directory can be customized via the
ACTIONS_RUNNER_WORK_DIRECTORY environment variable or by setting the work property in the runner configuration file.
9. Managing Runner Updates
| Update Method | Description | Notes |
|---|---|---|
| Runner Version | 2.300.0 |
Latest stable version as of 2026 |
| Update Command | ./config.sh --update |
Run from runner directory |
| Update Frequency | As needed | Recommended to update runners regularly for security |
Example: Update Runner
# Navigate to runner directory
cd /home/user/runner
# Run update command
./config.sh --update
Note: Ensure runner is stopped before updating to prevent conflicts.
Warning: Updating runners may require reconfiguration if major version changes.
| Update Type | Impact | Requirements |
|---|---|---|
| Minor Update | Backward compatible | Restart runner after update |
| Major Update | May require config changes | Reconfigure runner settings |
10. Removing Runners
| Runner | Status | Action |
|---|---|---|
| runner.name | self-hosted-runner-01 |
Identifier for the runner instance |
| runner.id | 12345 |
Unique ID assigned by GitHub |
| runner.status | online |
Current operational state |
Example: Remove a Self-Hosted Runner via API
curl -X DELETE \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer <token>" \
https://api.github.com/actions/runners/12345
Note: The runner must be offline before deletion. If it's currently running a job, wait for the job to complete or cancel it first.
Warning: Deleting a runner permanently removes it from the organization or repository. Ensure all necessary data is backed up before proceeding.
11. Monitoring Runner Status
Example: Check runner status via API
curl -H "Authorization: Bearer <TOKEN>" \
https://api.github.com/actions/runners?per_page=100
| Field | Description | Example Value |
|---|---|---|
| id | Unique identifier for the runner | 12345 |
| name | Name of the runner | my-runner-1 |
| status | Current status of the runner (online/offline) | online |
| busy | Whether the runner is currently executing a job | false |
| os | Operating system of the runner | linux |
Note: Runners must be registered with a valid token to appear in the API response.
Workflow: Monitor runner health
- Use
curlto fetch runner list from GitHub API - Parse JSON response for
statusandbusyfields - Alert if any runner is
offlineor stuck on a job longer than threshold
12. Cleaning Up After Jobs
Example: Using cleanup scripts in workflow
name: Cleanup Example
on: [push]
jobs:
build:
runs-on: self-hosted
steps:
- name: Setup
run: echo "Setting up environment"
- name: Run Job
run: |
echo "Running job tasks"
# Simulate some work
- name: Cleanup
run: |
echo "Cleaning up temporary files"
rm -rf /tmp/temp-files
| Step | Description | Action |
|---|---|---|
| Post-job cleanup | Automatically clean up after each job completes | rm -rf /tmp/* |
| Manual cleanup | Explicitly define cleanup steps in workflow | echo "Cleanup complete" |
Note: Self-hosted runners may require additional permissions to clean up files in system directories.
Warning: Ensure cleanup steps do not interfere with other jobs running on the same runner.