| LICENSE | Initial commit | |
| README.md | Actualiser README.md | |
codeberg-actions
Setting up CI with Codeberg.org
Codeberg runs Woodpecker CI and, more recently, Actions. They have limited resources, unlike GitHub aka Microsoft, so they will only run Woodpecker for you if you ask nicely.
But you can set up your own CI machine, self-hosted.
This is how I set this up with a spare ArchLinux machine I had idling.
sudo pacman -S forgejo-runner
The Arch package assumed Docker. I don't like that. I want podman so I can run rootless 1
Also my system has /var too small to store a bunch of containers, so I wanted to put it on /home.
I made some (fragile) patches to get this to work for me:
-
sudo userdel -r forgejo-runner; sudo useradd -m -d /home/forgejo-runner forgejo-runnerThis moves the homedir, sets the shell to /bin/bash instead of /bin/nologin, but more importantly it writes /etc/subuid and /etc/subgid; by default forgejo-runner installs as a system account, which means it does not have subuid rights, which means rootless podman doesn't work. You could do this without deleting the account, by editing /etc/subuid yourself, but it's simpler to get the math right this way.
-
sudo systemctl edit --full --force forgejo-podmanThis is needed because forgejo-runner expects to be able to talk to a docker socket.
[Unit] Description=Podman Socket for forgejo-runner [Service] # https://forgejo.org/docs/v11.0/admin/actions/runner-installation/#setting-up-the-container-environment User=forgejo-runner Group=forgejo-runner ExecStart=/usr/bin/podman system service -t 0 Restart=on-failure [Install] WantedBy=multi-user.targetsudo systemctl enable --now forgejo-podman -
sudo su -l forgejo-runner; make surepodman run --rm -it ubuntu:latestworks. -
Now, getting the service registered was confusing. The forgejo docs don't quite seem to line up with the codeberg docs.
I ended up doing this. This was the fiddliest part:
- Go to https://codeberg.org/user/settings/actions/runners and get a REGISTRATION token from "Create new Runner"
- as
forgejo-runner, runforgejo-runner registerpass the registration token in to the prompts mv .runner .runner.disabled; cat .runner.disabled-> get the UUID and the long term token
Then run uuidgen to get a UUID, and edit /etc/forgejo-runner/config.yaml with
connections:
codeberg:
url: https://codeberg.org/
uuid: YOUR_UUID
token: YOUR_LONG_TERM_TOKEN
labels:
- archlinux:docker://docker.io/library/archlinux:latest
- ubuntu-latest:docker://library/ubuntu:24.04
- python-3.12:docker://docker.io/library/python:3.12
- python-3.13:docker://docker.io/library/python:3.13
- python-3.14:docker://docker.io/library/python:3.14
The 'labels' you add are the platforms users can 'runs-on' in their workflow scripts.
- I also changed
/etc/forgejo-runner/config.yamlto say
runner:
# increase how many parallel jobs we can handle
capacity: 4
# shorten how long each job can run
timeout: 30m
-
sudo systemctl edit --full forgejo-runnerto tell it about podman and about its new homedir:WorkingDirectory=/home/forgejo-runner Environment="DOCKER_HOST=unix:///var/run/user/1004/podman/podman.sock"1004 is from
id forgejo-runnerso that needs to adapt to your system. -
Finally turn it on:
sudo systemctl enable --now forgejo-runner
Monitor with
sudo journalctl -lfu forgejo-runner
and look at https://codeberg.org/user/settings/actions/runners to see if it's detected by Codeberg.
If it's not launching right, it helps to troubleshoot by running it manually (as the forgejo-runner user)
DOCKER_HOST=unix:///var/run/user/1004/podman/podman.sock /usr/bin/forgejo-runner daemon --config /etc/forgejo-runner/config.yaml
Security
Set up subnet isolation so the forgejo-runner can't see your LAN:
# ~/.config/containers/containers.conf
[containers]
netns = "podman"
#!/bin/sh
set -e
nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }
# Allow DNS to anywhere
for protocol in tcp udp; do
nft add rule inet filter output meta skuid forgejo-runner ${protocol} dport 53 accept
done
# Block everything else
for range in 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 127.0.0.0/8 169.254.0.0/16; do
nft add rule inet filter output meta skuid forgejo-runner ip daddr $range drop
done
for range in fc00::/7 fe80::/10 ::1/128; do
nft add rule inet filter output meta skuid forgejo-runner ip6 daddr $range drop
done
Run
sudo sh ./block.sh
# After testing a bit, save changes:
sudo nft list ruleset | sudo tee /etc/nftables.conf
Review: https://forgejo.org/docs/latest/admin/actions/security
- Test if runners have access to the docker socket for possible container escape
Usage
Actions is disabled by default on every repo. For each repo, need to go to https://codeberg.org/$OWNER/$REPO/settings/units and enable Actions. When you do that, an 'Actions' table will show up.
Forgejo-actions is mostly Github-actions compatible, but there's some limitations and differences. Create workflow files in .forgejo/workflows/ in your projects instead of .github/workflows; it will try to run .github/workflows scripts too, but many of them will probably break! You need to port pre-existing workflows.
- 'runs-on' is defined by the 'labels' of the runner's config. You can see available labels in https://codeberg.org/user/settings/actions/runners.
- To see what you can 'uses:', look in https://data.forgejo.org/actions/ (you can't see their contents directly but you can git clone each)
- in particular, there's
actions/forgejo-releaseandactions/upload-artifactandactions/download-artifactwhich are a bit different than the github versions. - You can also 'uses' actions directly github by prefixing 'https://github.com/' e.g.
uses: https://github.com/pypa/gh-action-pypi-publish@release/v1; but a lot of Actions on github are going to assume they can use the github API and not everything is compatible.
- in particular, there's
-
other options are lxc, or 'host' most, meaning no containerization which might be safe if wrapped in a systemd service that launches everything in an ephemeral temporary HOME; I haven't investigated this yet. HOST mode would be useful to speed up testing because most of the tool installs in a workflow could be skipped. ↩︎