# Forgejo Runner Quadlets My configurations for running a Forgejo Runner with root-less Podman Quadlets. This configuration enables Actions to build container images using `buildah`. ## Set-up Install podman: ```sh sudo apt-get update && sudo apt-get install -y podman fuse-overlayfs sudo modprobe fuse ``` Create the data directories (`/data`) for persisting Forgejo runner configurations and cache: ```sh sudo mkdir -p /data/.cache /data/.config sudo touch /data/.runner sudo chown -R $UID:$UID /data sudo chmod -R 700 /data ``` Clone this repository: ```sh git clone https://git.poire.dev/aramperes/forgejo-runner-quadlet.git ``` For the first-time set-up, you will need to stop the Forgejo Runner from starting up so you can configure the token with your Forgejo server. ```diff # vim forgejo-runner-quadlet/quadlets/forgejo-runner.container - Exec=/bin/sh -c "sleep 5; forgejo-runner daemon -c .config/config.yml" - # Exec=/bin/sh -c "while : ; do sleep 1 ; done ;" + # Exec=/bin/sh -c "sleep 5; forgejo-runner daemon -c .config/config.yml" + Exec=/bin/sh -c "while : ; do sleep 1 ; done ;" ``` Create the directory for the quadlets. SystemD will be looking for the quadlets here, and we can use symbolic links to keep them in sync with this repo. ```sh mkdir -p $HOME/.config/containers/systemd for f in forgejo-runner-quadlet/quadlets/*; do ln -s $(realpath $f) $HOME/.config/containers/systemd/$(basename $f); done ``` Confirm: ```sh ls -l $HOME/.config/containers/systemd/ # forgejo-runner.container -> /home/user/forgejo-runner-quadlet/quadlets/forgejo-runner.container # podman-runtime.container -> /home/user/forgejo-runner-quadlet/quadlets/podman-runtime.container # runner.network -> /home/user/forgejo-runner-quadlet/quadlets/runner.network ``` Run SystemD generator dry-run to validate the quadlets: ```sh /usr/lib/systemd/system-generators/podman-system-generator --user --dryrun && echo 'Validated!' ``` Reload SystemD daemon and start the Runner. This will automatically create the Podman Runtime container and the bridge network. ```sh systemctl --user daemon-reload systemctl --user start forgejo-runner.service ``` Confirm the containers are running. This might take a few seconds. ```sh podman ps # CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # b2e57b02edea quay.io/podman/stable:latest podman system ser... 6 minutes ago Up 6 minutes systemd-podman-runtime # 7521cab26b80 data.forgejo.org/forgejo/runner:9 /bin/sh -c while ... 14 seconds ago Up 15 seconds systemd-forgejo-runner ``` To enable automatic start-up on boot, your user needs to have "lingering" enabled in SystemD: ```sh sudo loginctl enable-linger $USER ``` ## Register the Runner On your Forgejo server's `Site administration` page, go to `Action` then `Runners`. Click `Create a new runner` and copy the token. Back on your Forgejo Runner host, run: ```sh podman exec -it systemd-forgejo-runner /bin/sh # Run inside the container and follow the instructions: # (I recommend setting the label 'docker') forgejo-runner register # Confirm the .runner file has been written to: cat .runner # Write out default configurations: forgejo-runner generate-config > .config/config.yml exit ``` For building containers, you will need to tweak the runner's configurations to create privileged containers and avoid creating a nested network stack. Don't worry, this is still sandboxed inside the `podman-runtime` container. ```diff # sudo vim /data/.config/config.yml container: - network: "" + network: host - privileged: false + privileged: true ``` Revert the runner's quadlet to launch the daemon: ```diff # vim forgejo-runner-quadlet/quadlets/forgejo-runner.container - # Exec=/bin/sh -c "sleep 5; forgejo-runner daemon -c .config/config.yml" - Exec=/bin/sh -c "while : ; do sleep 1 ; done ;" + Exec=/bin/sh -c "sleep 5; forgejo-runner daemon -c .config/config.yml" + # Exec=/bin/sh -c "while : ; do sleep 1 ; done ;" ``` Reload the quadlet and restart it: ```sh systemctl --user daemon-reload systemctl --user restart forgejo-runner.service ``` Now, in the Forgejo server Runners page, you should see your new runner as "Idle". ## Example Action: build and push an image > Note, `secrets.PACKAGE_TOKEN` is a Forgejo Personal Access Token (PAT) with write-permissions to the Packages function. This has to be created manually because the automatic token `FORGEJO_TOKEN` does not have this permission. Track [this feature request](https://codeberg.org/forgejo/forgejo/issues/6198). ```yaml # .forgejo/workflows/image.yaml on: push: branches: - master jobs: build: runs-on: docker steps: - name: Checkout code uses: actions/checkout@v4 - name: Extract the tag id: extract_tag run: echo "::set-output name=tag::$(echo ${{ forge.sha }} | cut -c1-10)" - name: Install Buildah and Podman run: apt-get update && apt-get install -y buildah podman - name: Buildah Build id: build-image uses: redhat-actions/buildah-build@v2 with: image: aramperes/imagename tags: ${{ steps.extract_tag.outputs.tag }} context: . containerfiles: ./Dockerfile - name: Push to Registry uses: https://github.com/redhat-actions/push-to-registry@v2 with: image: ${{ steps.build-image.outputs.image }} tags: ${{ steps.build-image.outputs.tags }} registry: git.poire.dev username: ${{ env.FORGEJO_ACTOR }} password: ${{ secrets.PACKAGE_TOKEN }} ``` ## Making Changes If you would like to modify the quadlet configurations, you will need to run these commands to validate, apply, and restart: ```sh /usr/lib/systemd/system-generators/podman-system-generator --user --dryrun && echo 'Validated!' systemctl --user daemon-reload systemctl --user restart podman-runtime.service systemctl --user restart forgejo-runner.service ```