Runner Resource Optimization
CI/CD runner right-sizing through historical resource utilization analysis and a sustainability dashboard.
Action runners are the execution environment for Forgejo Actions workflows. By design, runners execute remote code submitted through CI/CD pipelines, making their architecture highly dependent on the underlying infrastructure and security requirements.
The primary objective in any runner setup is the separation and isolation of individual runs. Since runners are specifically built to execute arbitrary code from repositories, proper isolation is critical to prevent data and secret leakage between different pipeline executions. Each runner must be thoroughly cleaned or recreated after every job to ensure no residual data persists that could compromise subsequent runs.
Beyond isolation concerns, action runners represent high-value targets for supply chain attacks. Runners frequently compile, build, and package software binaries that may be distributed to thousands or millions of end users. Compromising a runner could allow attackers to inject malicious code directly into the software supply chain, making runner security a critical consideration in any deployment.
This document explores different runner architectures, examining their security characteristics, operational trade-offs, and suitability for various infrastructure environments and showing off an example deployment using a Containerized Kubernetes environment.
A actions runner are executing Forgejo actions, which can be used to build, test, package and deploy software. To ensure that EDP customers do not need to provision their own action runners with high efford, we provide globally registered actions runners to pick up jobs.
Code:
Documentation: Forgejo Runner installation guide
Different runner deployment architectures offer varying levels of isolation, security, and operational complexity. The choice depends on your infrastructure capabilities, security requirements, and operational overhead tolerance.
Bare metal runners execute directly on physical hardware without virtualization layers.
Advantages:
Disadvantages:
Use case: Best suited for specialized workloads requiring specific hardware, performance-critical builds, or environments where virtualization is not available.
VM-based runners operate within virtualized environments managed by a hypervisor.
Advantages:
Disadvantages:
Use case: Ideal for environments requiring strong isolation guarantees, multi-tenant scenarios, or when running untrusted code from external contributors.
Container-based runners execute within isolated containers using OCI-compliant runtimes.
Advantages:
Disadvantages:
Use case: Best for high-volume CI/CD workloads, trusted code repositories, and environments prioritizing speed and efficiency over maximum isolation.
admin settings > actions > runner > Create new runnerorganization settings > actions > runner > Create new runnerrepository settings > actions > runner > Create new runner${RUNNER_SECRET} with the runner registration token${RUNNER_NAME} with the name the runner should have${FORGEJO_INSTANCE_URL} with the instance urlkubectl create ns giteakubectl apply -f <file>Take a look at the runners page, where you generated the token. There should be 3 runners in idle state now.
---
title: Forgejo Runner executed in daemon mode
---
sequenceDiagram
Runner->>Forgejo: Register runner
loop Job Workflow
Runner->>Forgejo: Fetch job
Runner->>Runner: Work on job
Runner->>Forgejo: Send result
end[Add infrastructure and deployment diagrams showing how the component is deployed]
There is a sophisticated configuration file, where finetuning can be done. The most important thing is done by using labels to define the execution environment.
The label ubuntu-latest:docker://ghcr.io/catthehacker/ubuntu:act-22.04 (as used in example runner). That a job that uses ubuntu-latest label will be executed as docker container inside the ghcr.io/catthehacker/ubuntu:act-22.04 image.
Alternatives to docker are lxc and host.
Problem: In containerized environment, containers usually do not have many privileges. To start or build containers additional privleges, usually root is required inside of the kernel, the container runtime needs to manage linux namespaces and cgroups.
Solution: A partial solution for this is buildkitd utilizing rootlesskit. This allows containers to be built (but not run) in a non root environment. Several examples can be found in the official buildkit repo.
Rootless vs User namespaces:
As of Kubernetes 1.33, uid mapping can be enabled for pods using pod.spec.hostUsers: false utilizing user namespaces to map user and group ids between the container ids (0-65535) to high host ids (0-65535 + n * 65536) where n is an arbitrary number of containers. This allows that the container runs with actual root permission in its user namespace without being root on the host system.
Rootless is considered the more secure version, as the executable is mapped to a privileged entitiy at all.
Maturity: Beta
CI/CD runner right-sizing through historical resource utilization analysis and a sustainability dashboard.
Using GARM to manage short-lived Forgejo runners