Comprehensive guide for installing, configuring, and managing GitHub Actions self-hosted runners.
- Introduction
- Linux Runner Installation
- Windows Runner Installation
- macOS Runner Installation
- Docker Runner Installation
- Runner Configuration
- Runner Management
- Runner Security
- Troubleshooting
- Best Practices
Self-hosted runners are servers that you set up and manage to execute GitHub Actions workflows. They provide:
- Custom hardware specifications
- Local network access
- Specific software dependencies
- Cost control for large workloads
- Data residency compliance
| Feature | Self-Hosted | GitHub-Hosted |
|---|---|---|
| Cost | You pay for infrastructure | Free for public repos |
| Customization | Full control | Limited |
| Maintenance | Your responsibility | Managed by GitHub |
| Security | Your responsibility | Managed by GitHub |
| Performance | Dependent on your hardware | Standardized |
- Need for specific hardware (GPU, specialized processors)
- Local network access requirements
- Data residency or compliance requirements
- Cost optimization for large workloads
- Need for pre-installed software dependencies
# System requirements
# - Ubuntu 20.04+ / Debian 11+ / CentOS 8+ / RHEL 8+
# - Minimum 2 CPU cores
# - Minimum 4 GB RAM
# - Minimum 20 GB disk space
# - Network access to GitHub
# Update system
sudo apt update && sudo apt upgrade -y # Ubuntu/Debian
# or
sudo yum update -y # CentOS/RHELmkdir actions-runner
cd actions-runner# Download the latest runner package
curl -o actions-runner-linux-x64-2.311.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz
# Or use wget
wget https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gztar xzf ./actions-runner-linux-x64-2.311.0.tar.gz# Run the configuration script
./config.sh --url https://github.com/YOUR_ORG/YOUR_REPO \
--token YOUR_TOKEN \
--name my-runner \
--labels self-hosted,linux,x64 \
--work _work# Install as a service
sudo ./svc.sh install
# Start the service
sudo ./svc.sh start
# Check status
sudo ./svc.sh status# Create systemd service file
sudo nano /etc/systemd/system/actions-runner.service[Unit]
Description=GitHub Actions Runner
After=network.target
[Service]
Type=simple
User=runner
WorkingDirectory=/home/runner/actions-runner
ExecStart=/home/runner/actions-runner/run.sh
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable actions-runner
sudo systemctl start actions-runner# System requirements
# - Windows 10/11 or Windows Server 2019/2022
# - Minimum 2 CPU cores
# - Minimum 4 GB RAM
# - Minimum 20 GB disk space
# - Network access to GitHub
# - .NET Framework 4.8 or latermkdir actions-runner
cd actions-runner# Download the latest runner package
Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-win-x64-2.311.0.zip -OutFile actions-runner-win-x64-2.311.0.zip# Extract the installer
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64-2.311.0.zip", "$PWD")# Run the configuration script
.\config.cmd --url https://github.com/YOUR_ORG/YOUR_REPO `
--token YOUR_TOKEN `
--name my-runner `
--labels self-hosted,windows,x64 `
--work _work# Install as a service
.\svc.sh install
# Start the service
.\svc.sh start
# Check status
.\svc.sh status# Configure service to run as specific user
# Navigate to: Services > GitHub Actions Runner > Properties
# Set "Log On As" to your service account# System requirements
# - macOS 11 (Big Sur) or later
# - Minimum 2 CPU cores
# - Minimum 4 GB RAM
# - Minimum 20 GB disk space
# - Network access to GitHub
# - Xcode Command Line Toolsxcode-select --installmkdir actions-runner
cd actions-runner# Download the latest runner package
curl -o actions-runner-osx-x64-2.311.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-osx-x64-2.311.0.tar.gztar xzf ./actions-runner-osx-x64-2.311.0.tar.gz# Run the configuration script
./config.sh --url https://github.com/YOUR_ORG/YOUR_REPO \
--token YOUR_TOKEN \
--name my-runner \
--labels self-hosted,macos,x64 \
--work _work# Install as a service
sudo ./svc.sh install
# Start the service
sudo ./svc.sh start
# Check status
sudo ./svc.sh statusFROM ubuntu:22.04
# Install dependencies
RUN apt-get update && apt-get install -y \
curl \
git \
jq \
&& rm -rf /var/lib/apt/lists/*
# Create runner user
RUN useradd -m runner
# Set working directory
WORKDIR /home/runner
# Download and install runner
RUN curl -o actions-runner-linux-x64-2.311.0.tar.gz -L \
https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz && \
tar xzf ./actions-runner-linux-x64-2.311.0.tar.gz && \
rm actions-runner-linux-x64-2.311.0.tar.gz
# Set permissions
RUN chown -R runner:runner /home/runner
# Switch to runner user
USER runner
# Configure runner (will be done at runtime)
ENTRYPOINT ["/home/runner/entrypoint.sh"]#!/bin/bash
set -e
# Configure runner
/home/runner/actions-runner/config.sh \
--url ${RUNNER_URL} \
--token ${RUNNER_TOKEN} \
--name ${RUNNER_NAME} \
--labels ${RUNNER_LABELS} \
--work _work
# Run runner
/home/runner/actions-runner/run.sh# Build image
docker build -t github-runner:latest .
# Run container
docker run -d \
--name github-runner \
-e RUNNER_URL=https://github.com/YOUR_ORG/YOUR_REPO \
-e RUNNER_TOKEN=YOUR_TOKEN \
-e RUNNER_NAME=docker-runner \
-e RUNNER_LABELS=self-hosted,docker,linux \
-v /var/run/docker.sock:/var/run/docker.sock \
github-runner:latest# docker-compose.yml
version: '3.8'
services:
runner:
image: github-runner:latest
container_name: github-runner
environment:
RUNNER_URL: https://github.com/YOUR_ORG/YOUR_REPO
RUNNER_TOKEN: YOUR_TOKEN
RUNNER_NAME: docker-runner
RUNNER_LABELS: self-hosted,docker,linux
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- runner-work:/home/runner/_work
restart: unless-stopped
volumes:
runner-work:# Start runner
docker-compose up -d
# View logs
docker-compose logs -f./config.sh --labels self-hosted,linux,x64,docker,gpu# Navigate to: Settings > Actions > Runners > Select runner > Settings
# Add labels through the UIjobs:
build:
runs-on: [self-hosted, linux, x64, docker]
steps:
- uses: actions/checkout@v4- Navigate to organization Settings > Actions > Runner groups
- Click "New runner group"
- Configure:
- Name: production-runners
- Visibility: Private
- Repositories: Select repositories
# Configure runner with group
./config.sh --runnergroup production-runnersjobs:
check-capabilities:
runs-on: self-hosted
steps:
- name: Display capabilities
run: |
echo "Runner OS: ${{ runner.os }}"
echo "Runner Arch: ${{ runner.arch }}"
echo "Runner Name: ${{ runner.name }}"# Install additional software on runner
sudo apt install -y docker-compose
sudo apt install -y nodejs npm
sudo apt install -y python3 python3-pip# Stop runner
sudo ./svc.sh stop
# Download new version
curl -o actions-runner-linux-x64-NEW_VERSION.tar.gz -L \
https://github.com/actions/runner/releases/download/vNEW_VERSION/actions-runner-linux-x64-NEW_VERSION.tar.gz
# Extract new version
tar xzf ./actions-runner-linux-x64-NEW_VERSION.tar.gz
# Start runner
sudo ./svc.sh start# Stop runner
sudo ./svc.sh stop
# Unconfigure runner
./config.sh remove --token YOUR_TOKEN
# Remove service
sudo ./svc.sh uninstall
# Remove files
cd ..
rm -rf actions-runner# Check service status
sudo ./svc.sh status
# Check runner logs
sudo ./svc.sh log
# Check runner in GitHub
# Navigate to: Settings > Actions > Runners#!/bin/bash
# health-check.sh
# Check if runner service is running
if sudo systemctl is-active --quiet actions-runner; then
echo "Runner service is running"
else
echo "Runner service is not running"
exit 1
fi
# Check if runner can reach GitHub
if curl -s -o /dev/null -w "%{http_code}" https://github.com | grep -q "200"; then
echo "GitHub is reachable"
else
echo "GitHub is not reachable"
exit 1
fi
echo "All checks passed"# Create dedicated user for runner
sudo useradd -m -s /bin/bash github-runner
sudo usermod -aG docker github-runner
# Run as dedicated user
sudo -u github-runner ./config.sh --url ...# Configure firewall
sudo ufw allow from 192.168.1.0/24 to any port 22
sudo ufw allow from 192.168.1.0/24 to any port 443
sudo ufw deny incoming
sudo ufw enable# Update system regularly
sudo apt update && sudo apt upgrade -y
# Install security tools
sudo apt install -y fail2ban ufw
# Configure fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban# Configure runner with security options
./config.sh \
--url https://github.com/YOUR_ORG/YOUR_REPO \
--token YOUR_TOKEN \
--ephemeral \
--disableupdate# Only allow specific workflows to use runner
# Navigate to: Settings > Actions > Runner groups > Select group > Settings
# Configure access control# Create separate runner groups for different environments
# - dev-runners: Development environments
# - staging-runners: Staging environments
# - prod-runners: Production environments# Check service status
sudo systemctl status actions-runner
# Check logs
sudo journalctl -u actions-runner -n 50
# Check configuration
cat .runner# Test network connectivity
curl -I https://github.com
# Check DNS resolution
nslookup github.com
# Check firewall rules
sudo ufw status# Check runner logs
sudo ./svc.sh log
# Check workflow logs in GitHub
# Navigate to: Actions > Select workflow run > View logs# Run runner in debug mode
./run.sh --debug
# Enable verbose logging
./config.sh --url ... --debug# Remove existing configuration
./config.sh remove --token YOUR_TOKEN
# Reconfigure
./config.sh --url ... --token NEW_TOKEN- Use runner groups for organization
- Implement regular updates
- Monitor runner health
- Use ephemeral runners when possible
- Implement auto-scaling for variable workloads
- Isolate runners from production systems
- Use dedicated service accounts
- Regularly update runner software
- Implement network segmentation
- Monitor runner logs for suspicious activity
- Allocate sufficient resources
- Use SSD storage for better performance
- Implement caching for dependencies
- Clean up workspace regularly
- Monitor resource usage
- Regular system updates
- Log rotation
- Disk space monitoring
- Regular security patches
- Backup runner configuration
