FARM: Disposable Forgejo Actions runners with Incus
Table of Contents
FARM: Disposable Forgejo Actions runners with Incus #
I use Forgejo to host my Git repositories and run Forgejo Actions for CI/CD. For the runners, I wanted something slightly different from having a few long-running machines or containers waiting for jobs.
I wanted every job to get its own virtual machine.
The VM should be created when a job is queued, register itself as a Forgejo Actions runner, execute exactly one job, and disappear afterwards.
This is why I created FARM.
FARM runs Forgejo Actions jobs in disposable Incus virtual machines:
queued job → FARM → Incus VM → one-job runner → cleanup
Each VM registers a temporary Forgejo runner and accepts at most one job. After the job has finished, FARM removes both the VM and the runner registration.
Why virtual machines? #
Forgejo already makes it possible to run Actions with self-hosted runners, and there are several ways to make those runners dynamic.
For my setup, I wanted the runner itself to be disposable while still having a stronger isolation boundary than running jobs directly on the host or inside long-lived containers.
Incus already manages the virtual machines in my infrastructure, so using it to create short-lived runner VMs was a natural fit.
FARM only manages virtual machines. It deliberately does not create or manage Incus containers.
How it works #
FARM watches the Forgejo Actions queue and maintains one or more runner pools.
A pool defines things such as the Forgejo scope, runner label, Incus image, profile and capacity limits. Pools can exist globally or for individual users, organizations and repositories.
When capacity is needed, FARM creates an Incus VM and registers an ephemeral Forgejo runner inside it. The runner processes one job and is then removed together with the VM.
FARM can also keep a configurable number of idle VMs available, avoiding VM startup time when jobs arrive.

The included read-only web interface gives an overview of the configured pools, running instances, capacity and recent lifecycle activity.
FARM also exposes health and Prometheus metrics endpoints, and continuously reconciles its state with Forgejo and Incus to clean up stale runners and virtual machines.
Getting started #
FARM is still a new project, but I am already using it for my own Forgejo Actions setup.
The repository contains a setup guide, configuration reference and example configuration:
https://github.com/maveonair/farm
You need Forgejo, an Incus installation with a dedicated project and a VM image prepared for running the Forgejo Actions runner.
I will probably write more about my actual FARM and Incus setup in a follow-up post.