GitHub Actions runners

Coolify can run the GitHub Actions workflow jobs of a GitHub organization on your build servers. Each job runs in a new runner container. Coolify deletes the container after the job.

Beta

GitHub Actions runners are in beta. The settings and the behavior can change in later versions.

The runners run on your own servers, on self-hosted Coolify and on Coolify Cloud. Coolify never runs them on the server that runs Coolify itself.

How it works

  1. A workflow job asks for runs-on: [self-hosted, <your label>].
  2. GitHub sends a Workflow job webhook event to Coolify through your GitHub App.
  3. Coolify finds an enabled build server whose labels match the job and that has free capacity. It selects the least busy server.
  4. Coolify starts an ephemeral runner container on that server and registers it with GitHub.
  5. The runner takes one job. When the job completes, Coolify deletes the container, its network, and its volumes.

When all runners are busy, the job waits in the Coolify queue until a runner is free. When a runner cannot start, Coolify removes it and tries again, up to 3 times. Refer to Monitor runners.

Use only for trusted, private repositories

In the Docker (privileged, full host access) mode, each job gets a privileged Docker daemon. A malicious workflow can take control of the build server. Use Isolated Docker (Sysbox) or No Docker to keep jobs away from the server. Coolify creates a runner group that is limited to private repositories. Do not use these runners for repositories that accept code from untrusted contributors.

What you need

Before you start, make sure you have:

  • a server with the Builds only role. Refer to Build servers.
  • a GitHub App source in Coolify that belongs to a GitHub organization. Runners are registered at organization level, so GitHub Apps of personal accounts cannot run workflow jobs.
  • a Coolify instance that GitHub can send webhook events to.
  • outbound internet access from the build server to github.com, ghcr.io (runner image), and Docker Hub (Docker sidecar image).

Set up the GitHub App

The GitHub App needs these permissions and events:

TypeNameAccess
Organization permissionSelf-hosted runnersWrite
Repository permissionActionsRead
Webhook eventWorkflow job-

Create the source

  1. Open Sources in the Coolify sidebar.
  2. Select + Add to create a source.
  3. Enter the Name and the Organization.
  4. In Use this App for, select GitHub Actions runners.
  5. Select Continue.

The Organization field is required when you select GitHub Actions runners.

Register the App on GitHub

  1. On the next page, make sure that GitHub Actions runners is set to Run workflow jobs on build servers.
  2. Select Register with GitHub.
  3. Complete the registration and install the App in your organization.

Coolify adds the required permissions and the Workflow job webhook event to the App.

For the full registration flow, refer to Set up a GitHub App.


Configure runners on a build server

Enable the runners

  1. Open Servers in the Coolify sidebar and select the server.
  2. Open GitHub Runners.
  3. Select Enable runners.

Coolify saves the default settings and shows the runner settings. If the server does not have the Builds only role, the page shows This server is not enabled for builds. Change the role in the General settings of the server first.

Set the runner settings

SettingDescription
GitHub AppThe organization GitHub App that receives the Workflow job events. Coolify selects the first App that has all the required permissions.
LabelsComma-separated custom labels, for example coolify. Coolify also registers self-hosted and linux.
Application buildsAlso build applications, or Dedicated to runners. A dedicated server is not used for application builds while its runners are enabled.

Pull request jobs defaults to Refuse pull request jobs. Jobs started by pull requests, including pull_request_target and review events, are refused before a step runs. Choose Run pull request jobs only when your repository and organization approval policies permit it. The setting applies to runners started after you save; push, scheduled, and manual jobs are unaffected.

If Coolify shows The GitHub App is not ready, complete Set up the GitHub App. You can save the settings with an App that is not ready, but Coolify does not get jobs until the App has the required permissions.

Set the resources

SettingDefaultDescription
Parallel runners2The maximum number of runners on this server at the same time (1 to 32).
CPU limitNo limitThe number of CPUs for each runner, for example 2.
Memory limitNo limitThe memory for each runner, for example 4g.
Docker in jobsDocker (privileged, full host access)Refer to Docker in jobs.
Runner imageghcr.io/actions/actions-runner:latestRefer to Runner image.

The CPU and memory limits apply to the runner container and to its Docker sidecar.

Set the timeouts

All values are in minutes.

SettingDefaultDescription
Queue wait60Coolify drops a job that waits longer for a free runner.
Idle runner10Coolify removes a runner that gets no job in this time.
Job360Coolify stops a job that runs longer.

Save the settings

Select Save.

When the GitHub App has all the required permissions, Coolify creates a runner group named Coolify <app-uuid> in your organization. The group is limited to private repositories.

GitHub Free organizations

Organizations on the GitHub Free plan cannot create runner groups. In that case, Coolify uses the Default runner group and shows a warning. On GitHub, check which repositories can use the Default group.

You can configure runners on more than one build server. Coolify sends each job to the least busy server that matches the job labels.


Use the runners in a workflow

Add self-hosted and one of your custom labels to runs-on:

jobs:
  build:
    runs-on: [self-hosted, coolify]
    steps:
      - uses: actions/checkout@v4
      - run: docker build -t my-app .

Coolify takes a job only when:

  • the job asks for at least one of your custom labels, and
  • all labels of the job are registered by the runner (self-hosted, linux, and your custom labels).

Jobs that ask only for generic labels, such as self-hosted, are left for other runners. This prevents Coolify from taking jobs that are for other self-hosted runners of your organization.

A custom label can contain letters, numbers, dots, dashes, and underscores. You cannot use self-hosted, linux, x64, arm64, arm, windows, or macos as the only label.


Docker in jobs

ModeDescription
Docker (privileged, full host access)Each runner gets its own Docker daemon in a privileged sidecar container. A job can get root access to the build server. Use this mode only for trusted repositories.
Isolated Docker (Sysbox)Each runner gets its own Docker daemon in an unprivileged sidecar container that uses the Sysbox runtime. The root user in a job has no rights on the build server. The server must have Sysbox. Refer to Install Sysbox.
No Docker (isolated, no container actions)Jobs run in an unprivileged container without Docker.

What works in each mode:

Workflow featureDocker (privileged)Isolated Docker (Sysbox)No Docker
Shell steps, JavaScript actions, and composite actionsYesYesYes
docker commandsYesYesNo
Service containers (services:)YesYesNo
Container jobs (container:)YesYesNo
Docker container actions (uses: docker://... or actions with runs.using: docker)YesYesNo

Coolify never shares the Docker socket of the host with a runner. Each runner has its own network and volumes.

Install Sysbox

When you select Isolated Docker (Sysbox), Coolify checks if the server has Sysbox. If Sysbox is not installed, select Install Sysbox. Coolify shows the installation logs.

The automatic installation needs:

  • Debian or Ubuntu.
  • The amd64 or arm64 architecture.
  • Linux kernel 5.12 or newer.

During the installation, Coolify:

  1. Writes the current bip and default-address-pools values of Docker to /etc/docker/daemon.json. It keeps the other settings and saves a backup of the file as /etc/docker/daemon.json.before-sysbox. Without these values, the Sysbox package restarts Docker, or stops when containers exist.
  2. Downloads the pinned Sysbox package from GitHub and checks its SHA-256 checksum.
  3. Installs the package and fuse3. Docker reloads its configuration. Running containers are not restarted.

For other distributions, install Sysbox manually. Coolify detects it when the Sysbox services run and Docker lists the sysbox-runc runtime.

Known Sysbox issue

Sysbox has an open issue in which a host can stop responding. Coolify does not remove Sysbox from a server. To remove it, refer to the Sysbox uninstall instructions.


Runner image

By default, Coolify uses ghcr.io/actions/actions-runner:latest and pulls it each time it starts a runner, so the runner stays up to date. When the registry is not available, Coolify uses the image that is already on the server.

In Runner image, you can:

  • pin a version, for example ghcr.io/actions/actions-runner:2.337.0.
  • use a custom image based on the official runner image, to add tools.
Keep pinned images up to date

GitHub stops sending jobs to runners that are more than 30 days behind the newest runner version. If you pin a version or use a custom image, update it regularly.


Monitor runners

The Recent runners section on the GitHub Runners page shows the queued jobs, the active runners, and their results. The list updates every 10 seconds.

StatusDescription
QueuedThe job waits for a free runner.
ProvisioningCoolify starts the runner container.
Waiting for jobThe runner is registered and waits for GitHub to give it a job.
RunningThe runner runs the job.
CompletedThe job completed and Coolify removed the runner.
FailedCoolify could not start the runner after 3 attempts. The error message shows the cause.
CancelledThe job ended before a runner started, the runner got no job, or a user cancelled it.
Timed outThe job waited or ran longer than the configured timeout.

When a runner cannot start, Coolify removes it and puts the job back in the queue. It tries again after 30 seconds, and then after 60 seconds, possibly on another build server. While it waits, the row shows Attempt 1 of 3 failed or Attempt 2 of 3 failed with the cause.

After the last failed attempt, the job stays queued on GitHub until GitHub cancels it. Another runner with matching labels can still take it.

To stop an active runner, select Cancel on its row.


Disable runners

Select Disable runners to stop taking new jobs. Coolify removes the runners that wait for a job. Running jobs continue until they finish. Coolify keeps the settings and the execution history of the server.

To take jobs again, select Enable runners.

You cannot change the role of a build server while its runners are enabled. Disable the runners first.


Troubleshooting

ProblemSolution
This server is not enabled for buildsSet the server role to Builds only in the General settings of the server.
The GitHub Runners menu does not showCoolify does not run runners on the server that runs Coolify. Use another server.
No GitHub App shows in the settingsAdd a GitHub App that belongs to an organization, and install it.
The GitHub App is not readyAdd the missing permissions or events on GitHub, then select Refetch on the Permissions page of the App.
Jobs stay in Queued on GitHub and Coolify shows nothingMake sure that runs-on has one of your custom labels, and that all labels of the job are registered by the runner. Make sure that GitHub can send webhook events to Coolify.
Jobs stay in Queued in CoolifyAll runners are busy. Increase Parallel runners or configure runners on more build servers.
A job fails at Initialize containers or at a Docker stepThe job needs Docker. Select Docker (privileged, full host access) or Isolated Docker (Sysbox).
Install Sysbox failsMake sure that the server runs Debian or Ubuntu on amd64 or arm64, with Linux kernel 5.12 or newer. Otherwise, install Sysbox manually.
Sysbox is not installed shows after a manual installationMake sure that the sysbox-mgr and sysbox-fs services run, that /usr/bin/fusermount3 exists, and that docker info lists the sysbox-runc runtime. Select Install Sysbox to repair the installation on Debian or Ubuntu.
Runners show Failed with Could not start a runner after 3 attemptsRead the error message. For Isolated Docker, check the Sysbox services on the server.
GitHub does not send jobs to the runnersA pinned or custom Runner image can be too old. Use a newer runner version.
The job cannot find a toolUse a custom Runner image based on the official runner image that includes the tool.

On this page