Forgejo runner setup on Fedora
Topics: Forgejo, Fedora Workstation, Podman
This setup runs Forgejo CI jobs in Podman containers through Podman’s Docker-compatible socket.
Summary
Forgejo Runner can run CI jobs in Podman containers by using Podman’s Docker-compatible socket. The runner labels still use the docker:// label type, even when the backend is Podman.
Runner labels
Use docker labels for Podman-backed jobs:
runner:
labels:
- docker:docker://ghcr.io/catthehacker/ubuntu:act-22.04
- ubuntu-latest:docker://ghcr.io/catthehacker/ubuntu:act-22.04
Workflows can then use either:
runs-on: docker
or, for GitHub-style compatibility:
runs-on: ubuntu-latest
ubuntu-latest is only the Forgejo runner label. The actual container image is whatever the runner config maps it to.
Enable the rootless Podman socket
Podman does not run a daemon by default. Forgejo Runner needs the Docker-compatible Podman socket.
Configure subuid and subgid mappings
Rootless Podman also needs subordinate UID and GID ranges for the runner user. This is easy to miss when the runner account was created as a system user.
Check whether mappings already exist:
grep '^forgejo-runner:' /etc/subuid /etc/subgid
If there is no entry, assign a range:
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 forgejo-runner
Use a range that does not overlap with another user’s existing /etc/subuid or /etc/subgid range. The example above gives the runner 65,536 subordinate IDs, which is the usual rootless Podman size.
If Podman had already been used by that account before the mapping was added, migrate its rootless storage metadata:
uid=$(id -u forgejo-runner)
sudo -u forgejo-runner \
XDG_RUNTIME_DIR="/run/user/$uid" \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
podman system migrate
Verify the mapping:
uid=$(id -u forgejo-runner)
sudo -u forgejo-runner \
XDG_RUNTIME_DIR="/run/user/$uid" \
podman unshare cat /proc/self/uid_map
For a dedicated runner user, first enable lingering and start the user’s systemd scope:
sudo loginctl enable-linger forgejo-runner
uid=$(id -u forgejo-runner)
sudo systemctl start "user@$uid.service"
Then enable the Podman socket in that user’s systemd scope:
sudo -u forgejo-runner \
XDG_RUNTIME_DIR="/run/user/$uid" \
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
systemctl --user enable --now podman.socket
Verify the socket exists:
ls -l "/run/user/$uid/podman/podman.sock"
Configure Forgejo Runner
Point the runner at the rootless Podman socket:
container:
docker_host: unix:///run/user/<runner-uid>/podman/podman.sock
Replace <runner-uid> with the UID of the runner user.
Common failure
Running systemctl --user via sudo -iu forgejo-runner can fail with:
Failed to connect to user scope bus via local transport: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined
That means the user systemd bus and runtime directory were not available in the sudo session. Start the user’s systemd service and set XDG_RUNTIME_DIR and DBUS_SESSION_BUS_ADDRESS explicitly, as shown above.
Rootful fallback
Rootful Podman also works, but gives CI jobs a much larger crowbar:
sudo systemctl enable --now podman.socket
ls -l /run/podman/podman.sock
Runner config:
container:
docker_host: unix:///run/podman/podman.sock
Prefer rootless unless there is a specific reason to let CI jobs talk to a rootful container backend.