Migration Configuration Procedures for GitHub Actions Self-Hosted Runner Minimum Version Enforcement

Explains inventory audit and phased replacement procedures to address the minimum version 2.329.0 enforcement and brownout periods for GitHub Actions self-hosted runners.

In large-scale CI/CD pipeline operations, leaving self-hosted runner binary management unautomated creates a risk of sudden build outages caused by API specification changes on the control plane side. The enforcement of the minimum self-hosted runner version (2.329.0) and the introduction of the brownout phase in GitHub Enterprise Cloud introduce intentional connection throttling and simulated failures for pipelines running older versions. Relying solely on control plane registration logs to determine operational health leads to outages where pipelines stall due to network isolation or cache endpoint authentication errors during actual build job execution. This document details practical procedures from pre-brownout inventory auditing through phased replacement to rollback protocols in the event of failure.

🛠️ Technical Constraints and Version Requirements

Following this architectural change, the operational requirements for self-hosted runners in GitHub Enterprise Cloud are as follows:

  • Minimum Version Floor: 2.329.0 or higher
  • Registration Requirements: Runner binaries below 2.329.0 will experience intentional connection drops during the brownout period, and new registrations and job assignments will be blocked after full enforcement.
  • Lifecycle Window: Runners in production environments must be updated within 30 days of a new runner binary release. Exceeding this update window will result in rejections at the job execution layer.

4-Step Phased Migration Protocol

To prevent total downtime of CI/CD pipelines, proceed with the migration according to the following phases:

[ Phase 1: Inventory Audit ]
   (Version, Labels, OS, Workflows, Owner Identification)
      [ Phase 2: Canary Replacement Validation ]
  (v2.329.0+ Deployment ──► Read-Only Smoke Test ──► Gradual Workflow Migration)
     [ Phase 3: Rollback & Incident Response Definition ]
   (Threshold Configuration, Spare Pool Allocation, Fault Isolation)
     [ Phase 4: Complete Decommissioning of Legacy Versions ]

Step 1: Comprehensive Inventory Audit

Relying exclusively on static registration logs from the control plane carries the risk of missing ephemeral nodes dynamically generated by autoscaling mechanisms (KEDA, actions-runner-controller, AWS ASG, etc.). Create a consolidated matrix incorporating the following items:

  • Runner binary version information (runner.version)
  • Assigned custom tags and labels (labels)
  • Base OS image (Ubuntu, RHEL, Windows Server build number, custom AMI/Docker tag)
  • Workflow definitions specifying the runner (.github/workflows/*.yml)
  • Team responsible for managing the infrastructure node

Step 2: Verification of Execution Paths and Replacement Routes

Deploy the new runner version (>= 2.329.0) to an isolated verification pool and perform operational validation using read-only workflows.

# Example validation workflow (.github/workflows/runner-validation.yml)
name: Runner Environment Validation
on:
  workflow_dispatch:

jobs:
  validate-runner:
    runs-on: [self-hosted, linux, x64, validation-pool]
    steps:
      - name: Checkout Source Code
        uses: actions/checkout@v4

      - name: Test Dependency Cache Access
        uses: actions/cache@v4
        with:
          path: ~/.cache/pip
          key: ${{ runner.os }}-pip-validation
          restore-keys: |
            ${{ runner.os }}-pip-

      - name: Verify Environment Variables and Runtime
        run: |
          echo "Runner Version Check:"
          ./run.sh --version || true
          echo "Network Connectivity Check:"
          curl -Is https://pipelines.actions.githubusercontent.com | head -n 1

During validation, verify that the following components function correctly:

  1. Source code retrieval via proxy and Git credentials using actions/checkout
  2. Read/write permissions to storage endpoints (S3, GCS, Blob Storage) using actions/cache
  3. OIDC token exchange and IAM role assumption protocols

Step 3: Emergency Rollback and Brownout Response Criteria Formulation

Because intentional errors are injected during the brownout period, clearly segregate infrastructure version update tasks from active incident response.

  • Definition of escalation paths and designated personnel
  • Advance reservation of a fallback cloud runner pool in preparation for self-hosted runner registration failures
  • Pre-setting of work abort thresholds (Abort Threshold) in the event of a brownout

⚠️ Troubleshooting

Typical troubleshooting procedures for issues occurring during self-hosted runner updates and operations.

1. Proxy/SSL Certificate Error During config.sh Execution

When updating runners in a corporate network environment, environment variables may not be inherited, leading to connection timeouts to the registration API.

Cause: Proxy settings are not correctly specified in the .env and .path files within the runner directory.

Resolution: Create a .env file in the root directory of the runner and explicitly add the settings.

cat << 'EOF' > /opt/actions-runner/.env
HTTP_PROXY=http://proxy.internal.example.com:8080
HTTPS_PROXY=http://proxy.internal.example.com:8080
NO_PROXY=169.254.169.254,.internal.example.com
EOF

2. Insufficient Permissions and svc.sh Failure During systemd Service Startup

When replacing binaries with a new version, the service may fail to start due to execution permission mismatches in the systemd unit file.

Resolution: Stop and uninstall the existing service, then re-register with appropriate permissions.

cd /opt/actions-runner
sudo ./svc.sh stop
sudo ./svc.sh uninstall
sudo chown -R runner-user:runner-group /opt/actions-runner
sudo ./svc.sh install runner-user
sudo ./svc.sh start

3. Stale Image Retention in Actions Runner Controller (ARC)

When using ARC on Kubernetes, if image tags are hardcoded within custom resources (CRDs) such as RunnerDeployment or RunnerSet, older versions (< 2.329.0) will continue to be applied when Pods are recreated.

Resolution: Update the image tag in spec.template.spec.containers within the manifest to 2.329.0 or higher, and perform a rolling update of the Pods.

💡 Operational Notes

To verify health after migration completion, execute the following verification commands on target nodes to log process runtime status and version details.

$ sudo systemctl status actions.runner.*.service --no-pager
● actions.runner.org-repo.node01.service - GitHub Actions Runner (org-repo.node01)
     Loaded: loaded (/etc/systemd/system/actions.runner.org-repo.node01.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2026-09-17 09:15:22 UTC; 2h 40min ago
   Main PID: 14205 (Runner.Listener)
      Tasks: 18 (limit: 9451)
     Memory: 112.4M
        CPU: 1.820s
     CGroup: /system.slice/actions.runner.org-repo.node01.service
             ├─14205 /opt/actions-runner/bin/Runner.Listener run --startuptype service
             └─14218 /opt/actions-runner/bin/Runner.Worker

$ cat /opt/actions-runner/.runner
{
  "agentId": 1042,
  "agentName": "node01",
  "poolId": 1,
  "poolName": "Default",
  "serverUrl": "https://pipelines.actions.githubusercontent.com/",
  "gitHubUrl": "https://github.com/my-org",
  "workFolder": "_work"
}

$ /opt/actions-runner/config.sh --version
2.329.0

For the brownout period and subsequent full enforcement, continuous log monitoring and unpinning of locked versions—including dynamic runner pools across all environments—must be conducted.

Built with Hugo
Theme Stack designed by Jimmy
Privacy Policy Disclaimer Contact