Gehoste runner-image
Workflows met runs-on: fremforge draaien op een tijdelijke VM, één per commit, die wordt ingericht vanuit de gehoste runner-image. Die is ontworpen voor gelijkwaardigheid met ubuntu-latest: dezelfde actions/setup-*-ervaring als op GitHub Actions, dezelfde ingebakken toolchains, dezelfde scanners, plus native Docker voor containerbuilds.
Architectuur met twee lagen
De runner-image is de opstartschijf van de VM: beide lagen staan op dezelfde schijf en zijn aanwezig vanaf het moment dat de VM opstart, zonder download per job.
| Laag | Wat erin zit | Grootte |
|---|---|---|
| Systeemlaag | debian 13-basis + systeemtools in één versie (Node 24 LTS, build essentials, scanners, IaC- en cloud-CLI’s, browsers, databaseclients, native Docker-daemon) | ~300 MB |
| hostedtoolcache-laag | Taalruntimes in meerdere versies (Node, Go, Python, .NET, Java, Ruby) + Android SDK + Miniconda3 + R | ~7 GB |
setup-*-actions halen hun versie uit de hostedtoolcache, zonder download per job. RUNNER_TOOL_CACHE en AGENT_TOOLSDIRECTORY wijzen al naar /opt/hostedtoolcache.
De versienummers in de tabellen hieronder geven aan welke hoofd- en subversielijnen zijn ingebakken. De exacte versies worden continu bijgewerkt door de wekelijkse herbouw en bij elke herbouw automatisch gepubliceerd; zie de changelog voor de actueel gepubliceerde toolstack.
Talen: systeem
Eén recente versie op het PATH. Gebruik die rechtstreeks als je workflow tevreden is met de systeemstandaard.
| Taal | Versie | Opmerkingen |
|---|---|---|
| Node.js | 24.x (LTS) | + npm, plus pnpm + yarn via corepack. Nieuwere/oudere reeksen via actions/setup-node; zie hieronder |
| Rust | rustup stable | rustc + cargo |
| PowerShell | 7.x | pwsh |
| PHP | 8.3 | + Composer |
Talen: meerdere versies via setup-*-actions
Gebruik deze actions/setup-*-actions precies zoals op de door GitHub gehoste runners. De versie die je vraagt, komt uit de hostedtoolcache (geen ophalen via het netwerk).
| Action | Ingebakken versies | Wat het inricht |
|---|---|---|
actions/setup-node@v4 | 26.x, 24.x, 22.x | Node.js + npm; activeer pnpm/yarn met corepack enable |
actions/setup-go@v5 | 1.27.x, 1.26.x | Go-toolchain + modulecache |
actions/setup-python@v5 | 3.14, 3.13, 3.12 | Python + pip |
actions/setup-dotnet@v4 | 10.0, 8.0 | .NET SDK (naast elkaar, DOTNET_ROOT gezet) |
actions/setup-java@v4 | Temurin 25, 21, 17 | OpenJDK van Adoptium |
ruby/setup-ruby@v1 | 4.0.x, 3.4.x, 3.3.x | Ruby (ruby-builder) |
Heb je een versie nodig die we niet inbakken (bijv. Node 20.x voor een ouder project), dan kunnen actions/setup-node, actions/setup-go, actions/setup-java en actions/setup-dotnet een niet-ingebakken versie tijdens de job downloaden (trager, maar het werkt: ze halen generieke Linux-builds op). actions/setup-python en ruby/setup-ruby kunnen dat niet: upstream publiceert voor geen van beide een debian-asset, dus een niet-ingebakken reeks faalt meteen in plaats van terug te vallen. Kies een ingebakken reeks, of gebruik uv python install <version> (uv is ingebakken) of een container:-job voor een eenmalig geval.
Build essentials
Native Node-modules, Python-wheels met C-extensies, Go met cgo en Rust-crates met C-dependencies bouwen direct.
build-essential (gcc + make) · clang + lld · cmake · ninja · pkg-config · autoconf · automake · libtool · zstd · linux-headers (via de basis)
Pakketbeheerders en projecttools
| Pakketbeheerder | Versie | Opmerkingen |
|---|---|---|
npm | meegeleverd met Node 24 | |
pnpm | standaard 12.14.0 | Via corepack, staat al aan. Een packageManager-pin van het project gaat voor; zie Versies van pnpm en Yarn |
yarn | standaard 4.18.1 | Via corepack, staat al aan. Pin yarn@1.22.22 voor Yarn Classic; zie Versies van pnpm en Yarn |
pipx | debian | Installeert Python-CLI-tools in geïsoleerde venvs |
composer | nieuwste | PHP |
cargo | beheerd door rustup | Rust |
mvn (Maven) | 3.9.x | JVM |
gradle | 9.5.x | JVM |
Versies van pnpm en Yarn
pnpm en yarn draaien via corepack, dat op de runner aanstaat. Welke versie een job krijgt, hangt ervan af of het project er een vastzet:
- Geen pin: een job krijgt pnpm 12.14.0 en Yarn 4.18.1. Beide staan op de runner, dus er is geen download nodig. Tot 2026-10-21 kreeg een job zonder pin wat
latestvan npm op dat moment was, en dat was voor Yarn de Yarn Classic 1.22. - Met pin: zet
packageManagerin jepackage.json, bijvoorbeeld"packageManager": "pnpm@11.28.6"of"packageManager": "yarn@1.22.22", encorepackdraait precies die versie. pnpm 12.14.0 en 11.28.6 staan al op de runner; elke andere versie wordt gedownload wanneer de job start.
Met packageManager vastzetten kies je zelf. Het houdt ook je lokale machine en CI op dezelfde versie. Wanneer we de standaardversies naar een nieuwere release verplaatsen, kondigen we dat aan in de changelog.
IaC
| Tool | Opmerkingen |
|---|---|
tofu (OpenTofu) | MPL-2.0-vervanger voor Terraform. Het echte Terraform valt onder de BUSL-licentie en is niet ingebakken; gebruik hashicorp/setup-terraform als je specifiek Terraform nodig hebt. |
bicep | Azure |
pulumi | Voor meerdere clouds |
ansible (ansible-core) | Via pipx |
sam (AWS SAM CLI) | Serverless |
Cloud-CLI’s
| Cloud | CLI | Opmerkingen |
|---|---|---|
| AWS | aws v2, sam | |
| Google Cloud | gcloud, gsutil, bq | |
| Azure | az | |
| T Cloud Public (OTC) | tofu + provider opentelekomcloud | Of pip install otc-cli per job |
Containers en Kubernetes
| Tool | Opmerkingen |
|---|---|
docker (CLI + native daemon) | Docker draait native op de VM (geen sidecar, geen omweg via DOCKER_HOST); zie Containerbuilds hieronder |
kaniko | Rootless OCI-imagebouwer zonder daemon |
skopeo | Images kopiëren / inspecteren tussen registries |
kubectl | |
helm | |
kustomize | |
kind | Lokale k8s-clusters; werkt in de meeste gevallen met de native Docker-daemon; voeg het label dind-privileged toe als je tegen handelingen aanloopt die extra capabilities vereisen (KVM-nesting, rauwe /dev voor geneste gasten) |
tea | CLI voor Forgejo / Gitea |
Beveiliging en toeleveringsketen
Vooraf ingebakken, zodat scans op secrets, CVE’s, SBOM en SAST geen tijd voor inrichting kosten.
| Scanner | Vindt |
|---|---|
gitleaks | Secrets in commits |
trivy | CVE’s in OS en talen + misconfiguratie in IaC |
osv-scanner | Kwetsbaarheden uit de OSV-database |
cosign | Ondertekenen en verifiëren van container-images |
syft | SBOM’s genereren (CycloneDX / SPDX) |
opengrep | SAST (Semgrep-compatibele fork). Vooraf ingebakken met de taalmappen van GitLab sast-rules onder /opt/sast-rules/: csharp, go, java, javascript, python en scala. De regels vallen onder MIT, behalve go, dat onder Apache-2.0 valt (afgeleid van gosec). Alleen die mappen worden meegeleverd. Geef de mappen die je nodig hebt mee aan --config; de root van /opt/sast-rules is geen regelset |
scorecard | OSSF-scorecard voor de toeleveringsketen |
checkov | IaC-beveiliging (Terraform, CFN, k8s) |
cfn-lint | Lint voor CloudFormation |
Linters
shellcheck · shfmt · yamllint · actionlint (lint de Forgejo Actions-workflows die je op frem.sh schrijft) · hadolint (Dockerfile)
Browsers en e2e
Voor headless browsertests:
- Chromium +
chromedriver(debian-pakket, met bijpassende versie) - Firefox ESR +
geckodriver - Selenium Server (jar op
/opt/selenium-server.jar)
Microsoft Edge is niet ingebakken: Chromium gebruikt dezelfde Blink-engine, dus voor tests in CI is Chromium gelijkwaardig.
Databaseclients
postgresql-client · default-mysql-client · sqlite3. De volledige databaseservers komen via services:-blokken (een Docker-pull van Docker Hub, via de dependency-proxy van je organisatie als die eigen Docker Hub-inloggegevens heeft; zie Images van Docker Hub).
Mobiel en datawetenschap (ingebakken sinds 2026-06-06)
| Tool | Wat er vooraf is geïnstalleerd | Per job toevoegen |
|---|---|---|
| Android SDK | cmdline-tools (latest) + platforms;android-34 + build-tools;34.0.0 + platform-tools op ANDROID_HOME=/usr/local/lib/android/sdk | Extra API-niveaus / NDK / emulators via android-actions/setup-android@v3 (hergebruikt wat al is geïnstalleerd, geen nieuwe download) |
| R (CRAN) | r-base + r-base-dev (debian-CRAN-repository, momenteel 4.3.x) op /opt/hostedtoolcache/R/4.3/x64 | CRAN-pakketten via Rscript -e 'install.packages(...)' of r-lib/actions/setup-r-dependencies@v2 |
| Miniconda3 | conda + python 3.11 op CONDA=/opt/hostedtoolcache/Miniconda3/latest/x64 | Omgevingen + wetenschappelijke stack via conda-incubator/setup-miniconda@v3 met environment-file: |
# Android example
- uses: android-actions/setup-android@v3
- run: ./gradlew assembleDebug
# R example
- uses: r-lib/actions/setup-r@v2
- uses: r-lib/actions/setup-r-dependencies@v2
- run: Rscript -e 'testthat::test_local()'
# Miniconda example
- uses: conda-incubator/setup-miniconda@v3
with:
environment-file: env.yml
- shell: bash -el {0}
run: pytestWat er nog NIET is ingebakken
Echt nichegerichte of zware tools die de meeste workflows niet nodig hebben. Installeer ze per job:
| Tool | Installatieroute | Opmerkingen |
|---|---|---|
| iOS / Xcode | Alleen macOS: niet ondersteund (fremforge-runners zijn Linux) | Apart punt op de roadmap voor runnerniveaus |
| Julia | julia-actions/setup-julia@v2 | ~150 MB installatie per job |
| Swift | swift-actions/setup-swift@v2 | Swift-toolchain voor Linux |
| Haskell / GHC | haskell-actions/setup@v2 | |
| Mono | apt-get install mono-complete | Alleen het oude .NET Framework; .NET 8/10 zijn ingebakken |
| Browser Microsoft Edge | Niet nodig: Chromium is dezelfde engine | |
| Lua / Crystal / Nim / Elixir | setup-*-action of apt per job |
Containerbuilds
Native Docker (standaard)
De VM wordt geleverd met de Docker-daemon geïnstalleerd en draaiend op de host. Je docker-CLI praat ermee via de standaard lokale socket: geen Docker-in-Docker, geen sidecar, geen omweg via DOCKER_HOST. De meeste workflows voor door GitHub gehoste runners werken ongewijzigd: docker build, docker compose, docker pull, multi-stage builds, BuildKit-functies.
- run: docker build -t myapp:${{ github.sha }} .
- run: docker compose up -d
- run: docker pull postgres:16kaniko
Voor pure imagebuilds werkt kaniko zonder daemon (snellere koude start als je niet de hele Docker-daemon nodig hebt) en gaat het beter om met de laagcache bij externe registries.
- run: |
/usr/local/bin/kaniko \
--context=$GITHUB_WORKSPACE \
--dockerfile=Dockerfile \
--destination=registry.example.com/$GITHUB_REPOSITORY:$GITHUB_SHADocker met extra rechten (KVM-nesting)
Heeft je workload extra capabilities nodig naast wat de standaard Docker-gebruiker krijgt (bijv. kind met KVM-nesting, functies van testcontainers die capabilities voor het aanmaken van namespaces vereisen, toegang tot /dev voor geneste gasten), voeg dan het label toe aan runs-on:
jobs:
integration:
runs-on: [fremforge, dind-privileged]
steps:
- run: docker run --privileged kindest/node:v1.31.0 ...fremforge stuurt deze jobs naar een VM-type met geneste virtualisatie, met dezelfde isolatie van één VM per commit als de standaardrunners.
Hoe we in ~7 GB dekken waar GitHub ~50 GB voor gebruikt
De ubuntu-latest-images van GitHub zijn groot omdat ze het volgende inbakken:
- Meerdere versies per taal: wij bakken de 3 meest recente ondersteunde reeksen in voor Node, Python, Java en Ruby, en 2 voor Go en .NET (~3 GB in totaal voor alle 6 taalfamilies). De tabellen hierboven worden met de hand bijgehouden en noemen de reeks, niet de patchversie. Voor de exacte patchversies die nu zijn ingebakken, bij elke wijziging gegenereerd uit de eigen buildargumenten van de runner-image, zie de gegenereerde toolstacklijst. Spreken de twee elkaar ooit tegen, dan heeft de gegenereerde lijst gelijk. Een niet-ingebakken reeks kan voor Python en Ruby NIET per job worden gedownload (zie de opmerking hieronder), dus kies uit de ingebakken set.
- Android SDK + NDK (~10 GB bij GitHub): wij bakken de kern-SDK in (cmdline-tools + platform 34 + build-tools 34.0.0 + platform-tools, ~3 GB). Extra API-niveaus, NDK en systeemimages voor emulators installeer je per job via
setup-android(hergebruikt wat al is geïnstalleerd). - Vooraf opgehaalde Docker-images voor servicecontainers (postgres, mysql, mongo, redis, mssql ~5 GB): niet ingebakken. Een
docker pullhaalt ze op van Docker Hub, of via de dependency-proxy van je organisatie (zie pakketcaches). - De browser Microsoft Edge: niet ingebakken (Chromium is voor tests in CI dezelfde engine).
- Mono / Julia / Swift / Haskell / Lua / Crystal / Nim / Elixir: niet ingebakken (niche, per job te installeren).
- Oude GCC-versies, verouderde toolchains: wij leveren één actuele set.
Wat we voor gewone workflows niet inleveren ten opzichte van GitHub:
- Elke gangbare taal (Node, Python, Go, Java, .NET, Ruby, Rust, PHP, PowerShell)
- Mobiel (Android SDK) en datawetenschap (Miniconda + R), ingebakken sinds 2026-06-06
- Elke grote cloud-CLI (AWS, Azure, GCP)
- Elke gangbare scanner (Trivy, Gitleaks, OSV, Cosign, Syft, OpenGrep, Scorecard, Checkov)
- Beide grote browsers + Selenium
- Docker (native, met extra rechten via een label)
- Alle standaard GitHub Actions (
actions/checkout,actions/setup-*,actions/upload-artifact, enz.)
Heeft je team iets nodig wat we niet inbakken, neem contact op met support; tools die Renovate volgt, gaan mee in de volgende wekelijkse herbouw.
Grootte van de image, koude start, herbouwritme
- Wekelijkse herbouw: elke maandag om 06:00 UTC. Renovate stelt continu versie-updates voor; de herbouw op maandag neemt alles mee wat die week is gemerged.
- Trivy-poort tijdens de build: HIGH- en CRITICAL-CVE’s laten de build hard falen. We leveren nooit een image met bekende, niet-gepatchte HIGH/CRITICAL-bevindingen.
- Downloads vastgezet met sha256: elke binary die tijdens de build wordt opgehaald, wordt gecontroleerd tegen een vastgezette sha256. Renovate werkt de versie en de hash in dezelfde PR bij. De build faalt luid bij een afwijkende hash; dat is het vangnet voor de toeleveringsketen.
- Koude start van de VM: ~25 s (ECS-inrichting + opstarten vanuit de ingebakken image). VM’s uit een warme pool (vooraf ingericht en klaarstaand) brengen de wachttijd terug tot ~5 s als de pool capaciteit heeft.
- Publicatie van het manifest: elke herbouw publiceert de opgeloste toolversies, de image-digest, de Trivy-samenvatting en de CycloneDX-SBOM in de changelog.
Voorbeeldworkflow
Een minimale workflow die “alles gebruikt”:
name: ci
on:
push:
branches: [main]
workflow_dispatch: {}
jobs:
build-test-scan:
runs-on: fremforge
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '24' # resolves from hostedtoolcache, ~1 s
- run: npm ci && npm test
- uses: actions/setup-python@v5
with:
python-version: '3.13'
- run: pip install -r requirements.txt && pytest
- name: SAST + secrets
run: |
gitleaks detect --no-banner --redact
# one --config per language folder; /opt/sast-rules itself is not a rule set
opengrep scan --config=/opt/sast-rules/python --config=/opt/sast-rules/javascript .
- name: SBOM
run: syft scan dir:. -o cyclonedx-json > sbom.json
- name: Container build
run: docker build -t myapp:${{ github.sha }} .Licenties en vermeldingen van derden
De image bevat software van derden onder hun eigen licenties, waaronder opengrep (LGPL-2.1, met een bronaanbod), Node.js en de SAST-regels. De vermeldingen, de naamsvermelding voor advisorygegevens en waar je de broncode krijgt, staan op Vermeldingen van derden in de runner-image. Binnen een job staan de licentiebestanden onder /usr/share/licenses/ en /usr/share/doc/<package>/copyright.
Problemen met de runner-image melden
Ontbreekt een tool die je verwachtte, of loop je tegen een probleem in de VM-runtime aan (resourcelimieten, netwerk, capabilities), neem dan contact op met support@frem.sh. Bij regressies in de gehoste runners reageren we op dezelfde werkdag.