Skip to main content
setup-php supports self-hosted runners in addition to GitHub-hosted runners. This page covers supported operating systems, runner configuration, containerized setups, and local testing.

Supported operating systems

The following operating systems are supported on self-hosted runners:
Host OSYAML workflow label
Ubuntu 24.04self-hosted or Linux
Ubuntu 22.04self-hosted or Linux
Debian 13self-hosted or Linux
Debian 12self-hosted or Linux
Debian 11self-hosted or Linux
Windows 7 and newerself-hosted or Windows
Windows Server 2012 R2 and newerself-hosted or Windows
macOS Tahoe 26.x (x86_64/arm64)self-hosted or macOS
macOS Sequoia 15.x (x86_64/arm64)self-hosted or macOS
macOS Sonoma 14.x (x86_64/arm64)self-hosted or macOS
Operating systems based on the supported Ubuntu and Debian versions are also supported on a best-effort basis. PHP 5.6 to PHP 8.6 can be set up on self-hosted runners.

Setting the runner environment variable

Set the runner environment variable to self-hosted when using self-hosted runners. This tells setup-php to apply self-hosted-specific behaviour during setup.
- name: Setup PHP
  uses: shivammathur/setup-php@v2
  with:
    php-version: '8.5'
  env:
    runner: self-hosted

Containerized self-hosted runner setup

Running the GitHub Actions runner inside a container isolates it from the host OS and makes it easier to reproduce environments. Follow the appropriate guide for your host OS:

Linux

Guide for running a containerized self-hosted runner on a Linux host.

Windows

Guide for running a containerized self-hosted runner on a Windows host.

Running directly on the host OS

If you prefer to run the Actions runner directly on the host machine or in a virtual machine rather than in a container, review the requirements guide before registering your runner. The guide covers required packages, permissions, and system configuration for each supported OS.

Service containers

If your workflow uses service containers (for example, MySQL or Redis), you must run the self-hosted runner on a Linux host or in a Linux virtual machine. GitHub Actions does not support nested virtualization on Linux, so service containers will not work when the runner itself is running inside a Docker container.

Complete example with matrix

The following workflow sets up multiple PHP versions on a self-hosted runner using a matrix strategy:
jobs:
  run:
    runs-on: self-hosted
    strategy:
      matrix:
        php-versions:
          - '5.6'
          - '7.0'
          - '7.1'
          - '7.2'
          - '7.3'
          - '7.4'
          - '8.0'
          - '8.1'
          - '8.2'
          - '8.3'
          - '8.4'
          - '8.5'
    name: PHP ${{ matrix.php-versions }}
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php-versions }}
        env:
          runner: self-hosted

      - name: Install dependencies
        run: composer install --prefer-dist

      - name: Run tests
        run: vendor/bin/phpunit

Best practices

Do not register multiple self-hosted runners on the same server instance. Parallel workflow jobs will conflict with each other during PHP setup, leading to race conditions and unpredictable failures.
Do not run self-hosted runners alongside your development environment or on a production server. A workflow step with sufficient permissions could inadvertently modify files or services on the host.
Avoid using labels on your self-hosted runners that match GitHub-hosted runner labels (for example, ubuntu-latest, windows-latest). Ambiguous labels can cause workflows intended for GitHub-hosted runners to be dispatched to your self-hosted runner instead.

Local testing with nektos/act

nektos/act lets you run your GitHub Actions workflows locally. Use shivammathur/node Docker images as the container for act to get an environment compatible with setup-php. Choose the image tag that matches the runs-on value in your workflow:
# For runs-on: ubuntu-latest
act -P ubuntu-latest=shivammathur/node:latest

# For runs-on: ubuntu-24.04
act -P ubuntu-24.04=shivammathur/node:24.04

# For runs-on: ubuntu-22.04
act -P ubuntu-22.04=shivammathur/node:22.04
Example workflow to test locally:
jobs:
  run:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.5'

      - name: Install dependencies
        run: composer install --prefer-dist

      - name: Run tests
        run: vendor/bin/phpunit
Run it locally with:
act -P ubuntu-latest=shivammathur/node:latest
The shivammathur/node images are the same images used by setup-php internally for multi-arch builds, so they are well-tested and kept up to date with each PHP release.

Build docs developers (and LLMs) love