Self-Hosting a Forgejo Runner for Codeberg Actions

ZanderHammer2 pts0 comments

Self-Hosting a Forgejo Runner for Codeberg Actions | Hammer Blog

Why I Run My Own Codeberg Runner<br>My Codeberg review is still in the pipeline but I wanted to get this out now.<br>For everyone who doesn&rsquo;t know Codeberg: it&rsquo;s a GitHub alternative run by the non-profit organization Codeberg e. V. out of Berlin. It&rsquo;s based on the Gitea fork Forgejo. Just like GitHub, Forgejo has an Actions feature. Codeberg offers runners to use, but since they&rsquo;re a non-profit and their resources are limited, the only right thing to do is to set up your own Forgejo runner and connect it to Codeberg.<br>In this quick guide I&rsquo;ll show you how to set up the Forgejo runner with Docker and connect it to Codeberg. I set it up on my VPS, which acts as my development server. But since the runner connects to Codeberg and not the other way around, it&rsquo;s absolutely possible to deploy the runner on a local machine and only fire it up when you need it.<br>Setting Up the Docker Compose File<br>The official Forgejo documentation lets you run the runners on bare metal or in Docker. But either way you need Docker or Podman, since the runners run in containers. Since I&rsquo;m team Docker, I chose to run it in Docker. For security reasons the runners shouldn&rsquo;t get access to the host Docker daemon and instead be given &ldquo;Docker in Docker&rdquo;.<br>The Docker Compose file is pretty straightforward. Two containers. The DinD and the Forgejo runner itself:<br>version: '3.8'

services:<br>docker-in-docker:<br>image: docker:dind<br>container_name: 'docker_dind'<br>privileged: 'true'<br>command: ['dockerd', '-H', 'tcp://0.0.0.0:2375', '--tls=false']<br>restart: 'unless-stopped'

runner:<br>image: 'data.forgejo.org/forgejo/runner:12'<br>links:<br>- docker-in-docker<br>depends_on:<br>docker-in-docker:<br>condition: service_started<br>container_name: 'runner'<br>environment:<br>DOCKER_HOST: tcp://docker-in-docker:2375<br># User without root privileges, but with access to `./data`.<br>user: 1001:1001<br>volumes:<br>- ./data:/data<br>restart: 'unless-stopped'<br>command: 'forgejo-runner daemon --config runner-config.yml'

We are not quiet ready to start it. You first need to create the data folder and its permissions, and of course the config file. Choose a directory where you want to place the docker-compose.yml. I like to put my Compose files in the /opt directory, but your home folder is also fine. Then create the data and cache folders and give them non-root permissions:<br>cd /opt/forgejo-runner<br>mkdir -p data/.cache<br>chown -R 1001:1001 data<br>chmod 775 data/.cache<br>chmod g+s data/.cache

Now it&rsquo;s time to create the default Forgejo runner config. Using Docker, this can be done with this command:<br>sudo sh -c 'docker run --rm data.forgejo.org/forgejo/runner:12 forgejo-runner generate-config > data/runner-config.yml'

Now we&rsquo;re almost ready to fire up the runner.<br>Getting Your Runner Token from Codeberg<br>Now we need to get our token for the runner from Codeberg. You can set up a runner either for your account, for your organization, or just a single repository. Go to the respective settings -> Actions -> Runners. The Codeberg documentation is outdated here. It tells you to copy the registration token. But that route is deprecated. Instead, hit &ldquo;Create new runner&rdquo;, enter the name for your runner and an optional description.<br>Codeberg create new runner dialog<br>You&rsquo;re then presented with the UUID and Token. These values need to be added to the runner config so the runner can connect to Codeberg. They&rsquo;re only shown once, so write them down or you&rsquo;ll have to reset them later.<br>Codeberg runner config block<br>Here, Codeberg hands you the correct config so you don&rsquo;t have to bother writing it yourself. Which, given my own YAML track record, I&rsquo;m grateful for.<br>Editing the Config and Starting the Runner<br>Head back to the folder where you created the runner-config.yml and open it with the text editor of your choice. The default config is fine for most users. It&rsquo;s very well documented. Just scroll through it and you&rsquo;ll understand it. The only optional change I made is the capacity setting. Default is one job per runner. I set it to 4. And then there are two changes you have to make: add the server config and set the runner labels.<br>In line 63 you&rsquo;ll find the config for the labels:<br># The labels of a runner are used to determine which jobs the runner can run and how to run them.<br># Like: ["macos-arm64:host", "ubuntu-latest:docker://node:20-bookworm", "ubuntu-22.04:docker://node:20-bookworm"]<br># If it's empty when registering, it will ask for inputting labels.<br># If it's empty when executing the `daemon`, it will use labels in the `.runner` file.<br>labels: ['ubuntu-latest:docker://node:20-bookworm', 'ubuntu-22.04:docker://node:20-bookworm', 'ubuntu-24.04:docker://node:22-bookworm']

These labels tell Codeberg what actions the runner can handle. Think of it as a matchmaking system between your workflows and this runner. Each label follows a strict three-part...

runner docker codeberg rsquo forgejo config

Related Articles