Updates and Notes:
- 2025-01-09: With the latest versions of the Docker Runner, this setup does not work any more. I wrote about that here
I am using Forgejo as a local Github alternative where I can host my stuff. Until now, I used that in combination with Drone for doing CI/CD tasks. I was never really happy with Drone, but just kept it because I was not motivated to replace it.
Some time ago, Gitea introduced an own CI/CD alternative called Gitea Runners. This functionality is also available for Forgejo, so I decided to switch to this one.
My primary setup
I wanted a quite bare metal installation: Have a system that has as few modifications as possible. For me, thas means: Have a Debian Host with Docker installed on it, and that’s all.
Most guides that follow this setup then use ‘Docker in Docker’ to run tasks. I wanted that differently: I wanted the runner to use the Docker installation directly on the machine. Realizing that this may be a security threat to somebody, I see it the following way: My Git Server is running in my homelab and inaccessible from outside (given that only I and a handful of other people have VPN access). The same holds true for the server that will run the Forgejo Runner. So the security threat is (currently) not too important to me.
So, the infrastructure is simple: Install a Debian machine, install Docker on it. Everything else will run inside Docker.
Setup the runner
After a bit of fiddling around, I have got the following setup, in a docker-compose.yaml
file.
Please note some adaptions for later versions here.
services:
forgejo-runner:
image: code.forgejo.org/forgejo/runner:3.5.1
container_name: runner
environment:
DOCKER_HOST: unix:///var/run/docker.sock
user: 0:0
volumes:
- ./data:/data
restart: unless-stopped
command: forgejo-runner -c /data/config.yml daemon
Differences from the official docs:
- There is no Docker-in-Docker container. Obviously.
- The user for the runner is root (
user: 0:0
). This is required, as otherwise thedocker.sock
cannot be accessed. - Obviously,
docker.sock
is mapped into the container. Also, theDOCKER_HOST
variable is updated accordingly. - I fixed the startup command: In the official docs, there is a
sleep 5
setting before starting the Forgejo runner. This is for the DinD container to start; I don’t need that in my scenario and hence removed it.
Configuration
First, we need to create the mapped directory:
mkdir ~/data
Next, let the Forgejo Runner generate it’s default configuration with the following command:
docker compose run --rm forgejo-runner 'forgejo-runner' 'generate-config' > data/config.yaml
Note the quotes - these are not there arbitrary. The container knows the
forego-runner
executable and this way, we can also pass the sub-commandgenerate-config
. If we don’t add the quotes here, Docker searchs for the executable'forgejo-runner generate-config'
, which fails.This command creates the default configuration. For storing it in a file, the part
> data/config.yaml
is again executed on the host system - and the configuration file is stored in~/data/config.yaml
.Now open the configuration file. I did the following changes:
- I played around a bit with
fetch_interval
andreport_interval
. This is probably not required and was just out of interest. - Define some labels. I defined the following labels:
ubuntu-22.04:docker://node:20-bullseye
. This is defined as a good approach in the docs.debian-12:docker://registry.hub.docker.com/library/debian:12
. This is a test of me. Be aware - with that, it is quite hard to use any predefined actions!
- Please note the updates for newer versions I described here.
- I played around a bit with
The labels are the actually important part. I will still have to find out what good labels are, and how to actually use them. I will probably keep you posted.
Note that the labels are also not completely static. You can edit them in the config file and restart the runner, then also new labels will be accessible.
Register the runner
This one is surprisingly easy.
- Go to your forgejo instance (I am using
forgejo.tech-tales.blog
here) and login.- Go to Settings - Actions - Runners. Here, find the “Create new runner” button. When clicking that, you will be presented a registration token. Note that down (or copy it to clipboard), you will need it in a second.
- Now go back to your Forgejo Runner server. Execute the following command:
docker compose run --rm -it forgejo-runner 'forgejo-runner' 'register'
- You will be asked for the domain of your Forgejo instance (
https://forgejo.tech-tales.blog
for me), the token (which you just copied) and a name for the runner (I choseforgejo-docker-runner-0
, but this is mostly up to you). Enter all that and you are essentially done!
- You will be asked for the domain of your Forgejo instance (
- Back on the command line of your Forgejo Runner Host, a new file was created:
~/data/.runner
. Check that this one exists - it contains the token that the runner will use to authenticate against your Forgejo instance. Note that this is a different token than your registration token!
Startup the runner!
We are done! Run docker compose up -d
and check the logs with docker compose logs -f
. If everything went smoothly, you should see three lines about the runner starting up successfully.
Finally, also head over to Forgejo again. In the Settings - Actions - Runners section, you should see your runner now, and you should see that the status is Idle
.
You can now start using workflows in your repo. Don’t forget to setup Actions for the repo in the repo Settings under “Repository units - Overview”, and then choose runs-on: ubuntu-22.04
for a workflow!