Forgejo Actions administrator guide
Forgejo Actions
provides continuous integration driven from the files found in the .forgejo/workflows
directory of a repository. Note that Forgejo
does not run the jobs, it relies on the Forgejo runner
to do so. It needs to be installed separately.
Settings
Default Actions URL
In a workflow, when uses:
does not specify an absolute URL, the
value of DEFAULT_ACTIONS_URL
is prepended to it.
The actions published at https://code.forgejo.org are:
- known to work with Forgejo Actions
- published under a Free Software license
They can be found in the following organizations:
When setting DEFAULT_ACTIONS_URL
to a Forgejo instance with an open
registration, care must be taken to avoid name conflicts. For
instance if an action has uses: foo/bar@main
it will clone and try
to run the action found at DEFAULT_ACTIONS_URL/foo/bar
if it exists,
even if it provides something different than what is expected.
Disabling
As of Forgejo v1.21
it is enabled by default. It can be disabled by adding the following to app.ini
:
Storage
The logs and artifacts are stored in Forgejo
. The cache is stored by
the runner itself and never sent to Forgejo
.
job
logs
The logs of each job
run is stored by the Forgejo
server and never
expires. The location where these files are stored is configured in
the storage.actions_log
section of app.ini
as explained in in the
storage documentation.
artifacts
logs
The artifacts uploaded by a job are stored by the Forgejo
server and
expire after a delay that defaults to 90 days and can be configured as
follows:
The location where these artifacts are stored is configured in
the storage.artifacts
section of app.ini
as explained in in the
storage documentation.
The admin/monitor/cron
administration web interface can be used to
manually trigger the expiration of artifacts instead of waiting for
the scheduled task to happen.
Forgejo runner
The Forgejo runner
is a daemon that fetches workflows to run from a
Forgejo instance, executes them, sends back with the logs and
ultimately reports its success or failure.
Installation
Each Forgejo runner
release is published for all supported architectures as:
Installation of the binary
Download the latest binary release and verify its signature:
Installation of the OCI image
The OCI
images
are built from the Dockerfile which is found in the source
directory. It contains the forgejo-runner
binary.
It does not run as root:
One way to run the Docker image is via Docker Compose. To do so,
first prepare a data
directory with non-root permissions
(in this case, we pick 1001:1001
):
After running this script with bash setup.sh
, define the following
docker-compose.yml
:
Here, we’re not running the forgejo-runner daemon
yet because we
need to register it first. Please note that in a recent install of
docker docker-compose
is not a separate command but should be run as
docker compose
.
Follow the registration instructions below
by starting the runner
service with docker-compose up -d
and
entering it via:
In this shell, run the forgejo-runner register
command as described
below. After that is done, take the service down again with
docker-compose down
and modify the command
to:
Here, the sleep allows the docker-in-docker
service to start up
before the forgejo-runner daemon
is started.
More docker compose examples are provided to demonstrate how to install that OCI image to successfully run a workflow.
Execution of the workflows
The Forgejo runner
relies on application containers (Docker, Podman,
etc) or system containers (LXC) to execute a workflow in an isolated
environment. They need to be installed and configured independently.
-
Docker: See the Docker installation documentation for more information.
-
Podman: While Podman is generally compatible with Docker, it does not create a socket for managing containers by default (because it doesn’t usually need one).
If the Forgejo runner complains about “daemon Docker Engine socket not found”, or “cannot ping the docker daemon”, you can use Podman to provide a Docker compatible socket from an unprivileged user and pass that socket on to the runner, e.g. by executing:
-
LXC: For jobs to run in LXC containers, the
Forgejo runner
needs passwordless sudo access for alllxc-*
commands on a Debian GNU/Linuxbookworm
system where LXC is installed. The LXC helpers can be used as follows to create a suitable container:NOTE: Multiarch Go builds and binfmt need
bookworm
to produce and test binaries on a single machine for people who do not have access to dedicated hardware. If this is not needed, installing theForgejo runner
onbullseye
will also work.The
Forgejo runner
can then be installed and run within themyrunner
container.Warning: LXC containers do not provide a level of security that makes them safe for potentially malicious users to run jobs. They provide an excellent isolation for jobs that may accidentally damage the system they run on.
-
self-hosted: There is no requirement for jobs that run directly on the host.
Warning: there is no isolation at all and a single job can permanently destroy the host.
Registration
The Forgejo runner
needs to connect to a Forgejo
instance and must be registered before doing so. It will give it permission to read the repositories and send back information to Forgejo
such as the logs or its status.
-
Online registration
A special kind of token is needed and can be obtained from the
Create new runner
button:- in
/admin/actions/runners
to accept workflows from all repositories. - in
/org/{org}/settings/actions/runners
to accept workflows from all repositories within the organization. - in
/user/settings/actions/runners
to accept workflows from all repositories of the logged in user - in
/{owner}/{repository}/settings/actions/runners
to accept workflows from a single repository.
For instance, using a token obtained for a test repository from
next.forgejo.org
:It will create a
.runner
file that looks like:The same token can be used multiple times to register any number of runners, independent of each other.
When using the
forgejo-runner register
command, it will ask for a label too. To get a runner that is close to GitHub’s runners, useor
as the label. The
act
container image is much bigger than thenode
image, but also more similar to the GitHub runners. See the labels andruns-on
section for more information. - in
-
Offline registration
When Infrastructure as Code (Ansible, kubernetes, etc.) is used to deploy and configure both Forgejo and the Forgejo runner, it may be more convenient for it to generate a secret and share it with both.
The
forgejo forgejo-cli actions register --secret <secret>
subcommand can be used to register the runner with the Forgejo instance and theforgejo-runner create-runner-file --secret <secret>
subcommand can be used to configure the Forgejo runner with the credentials that will allow it to start picking up tasks from the Forgejo instances as soon as it comes online.For instance, on the machine running Forgejo:
and on the machine on which the Forgejo runner is installed:
The secret must be a 40-character long string of hexadecimal numbers. The first 16 characters will be used as an identifier for the runner, while the rest is the actual secret. It is possible to update the secret of an existing runner by running the command again on the Forgejo machine, with the last 24 characters updated.
For instance, the command below would change the secret set by the previous command:
The registration command on the Forgejo side is mostly idempotent, with the exception of the runner labels. If the command is run without
--labels
, they will be reset, and the runner won’t set them back until it is restarted. The--keep-labels
option can be used to preserve the existing labels.
Configuration
The default configuration for the runner can be
displayed with forgejo-runner generate-config
, stored in a
config.yml
file, modified and used instead of the default with the
--config
flag.
Cache configuration
Some actions such as https://code.forgejo.org/actions/cache or
https://code.forgejo.org/actions/setup-go can communicate with the
Forgejo runner
to save and restore commonly used files such as
compilation dependencies. They are stored as compressed tar archives,
fetched when a job starts and saved when it completes.
If the machine has a fast disk, uploading the cache when the job starts may significantly reduce the bandwidth required to download and rebuild dependencies.
If the machine on which the Forgejo runner
is running has a slow
disk and plenty of CPU and bandwidth, it may be better to not activate
the cache as it can slow down the execution time.
Running the daemon
Once the Forgejo runner
is successfully registered, it can be run from the directory in which the .runner
file is found with:
To verify it is actually available for the targeted repository, go to /{owner}/{repository}/settings/actions/runners
. It will show the runners:
- dedicated to the repository with the repo type
- available to all repositories within an organization or a user
- available to all repositories, with the Global type
Adding the .forgejo/workflows/demo.yaml
file to the test repository:
Will send a job request to the Forgejo runner
that will display logs such as:
It will also show a similar output in the Actions
tab of the repository.
If no Forgejo runner
is available, Forgejo
will wait for one to connect and submit the job as soon as it is available.
Enable IPv6 in Docker & Podman Networks
When a Forgejo runner
creates its own Docker or Podman networks, IPv6 is not enabled by default, and must be enabled explicitly in the Forgejo runner
configuration.
Docker only: The Docker daemon requires additional configuration to enable IPv6. To make use of IPv6 with Docker, you need to provide an /etc/docker/daemon.json
configuration file with at least the following keys:
Afterwards restart the Docker daemon with systemctl restart docker.service
.
NOTE: These are example values. While this setup should work out of the box, it may not meet your requirements. Please refer to the Docker documentation regarding enabling IPv6 and allocating IPv6 addresses to subnets dynamically.
Docker & Podman:
To test IPv6 connectivity in Forgejo runner
-created networks, create a small workflow such as the following:
If you run this action with forgejo-runner exec
, you should expect this job fail:
To actually enable IPv6 with forgejo-runner exec
, the flag --enable-ipv6
must be provided. If you run this again with forgejo-runner exec --enable-ipv6
, the job should succeed:
Finally, if this test was successful, enable IPv6 in the config.yml
file of the Forgejo runner
daemon and restart the daemon:
Now, Forgejo runner
will create networks with IPv6 enabled, and workflow containers will be assigned addresses from the pools defined in the Docker daemon configuration.
Labels and runs-on
The workflows / tasks defined in the files found in .forgejo/workflows
must specify the environment they need to run with runs-on
. Each Forgejo runner
declares, when they connect to the Forgejo
instance the list of labels they support so Forgejo
sends them tasks accordingly. For instance if a job within a workflow has:
it will be submitted to a runner that declared supporting this label.
When the Forgejo runner
starts, it reads the list of labels from the
configuration file specified with --config
. For instance:
will have the Forgejo runner
declare that it supports the node20
and bullseye
labels.
If the list of labels is empty, it defaults to docker:docker://node:16-bullseye
and will declare the label docker
.
Declaring a label means that the Forgejo runner
will accept tasks that specify this label in the runs-on
field.
So, to mimic the GitHub runners, the runs-on
field can be set to ubuntu-22.04:docker://node:20-bullseye
for instance.
With this, the Forgejo runner will respond to runs-on: ubuntu-22.04
and will use the node:20-bullseye
image from hub.docker.com.
This image is quite capable of running many of the workflows that are designed for the GitHub runners.
For a slightly bigger image, use ghcr.io/catthehacker/ubuntu:act-22.04
instead of node:20-bullseye
which should be compatible with most actions while remaining relatively small.
There exist larger images used that can go up to 20GB compressed with more software installed if needed.
Docker or Podman
If runs-on
is matched to a label mapped to docker://
, the rest of it is interpreted as the default container image to use if no other is specified. The runner will execute all the steps, as root, within a container created from that image. The default container image can be overridden by a workflow to use alpine:3.18
as follows.
See the user documentation for jobs.<job_id>.container
for more information.
Labels examples:
node20:docker://node:20-bookworm
==node20:docker://docker.io/node:20-bookworm
definesnode20
to be thenode:20-bookworm
image from hub.docker.comdocker:docker://code.forgejo.org/oci/alpine:3.18
definesdocker
to be thealpine:3.18
image from https://code.forgejo.org/oci/-/packages/container/alpine/3.18
LXC
If runs-on
is matched to a label mapped to lxc://
, the rest of it is interpreted as the default template and release to use if no other is specified. The runner will execute all the steps, as root, within a LXC container created from that template and release. The default template is debian
and the default release is bullseye
.
nodejs version 20 is installed.
They can be overridden by a workflow to use debian
and bookworm
as follows.
See the user documentation for jobs.<job_id>.container
for more information.
Labels examples:
bookworm:lxc://debian:bookworm
defines bookworm to be an LXC container running Debian GNU/Linux bookworm.
shell
If runs-on
is matched to a label mapped to `host://-self-hosted“, the runner will execute all the steps in a shell forked from the runner, directly on the host.
Label example:
self-hosted:host://-self-hosted
definesself-hosted
to be a shell
Packaging
NixOS
The forgejo-actions-runner
recipe is released in NixOS.
Please note that the services.forgejo-actions-runner.instances.<name>.labels
key may be set to []
(an empty list) to use the packaged Forgejo instance list. One of virtualisation.docker.enable
or virtualisation.podman.enable
will need to be set. The default Forgejo image list is populated with docker images.
IPv6 support is not enabled by default for docker. The following snippet enables this.
If you would like to use docker runners in combination with cache actions, be sure to add docker bridge interfaces “br-*” to the firewalls’ trusted interfaces:
Other runners
It is possible to use other runners instead of Forgejo runner
. As long as they can connect to a Forgejo
instance using the same protocol, they will be given tasks to run.