Codeberg logo
Logo: Codeberg e.V.CC BY-SA 4.0

As part of moving my services to EU-based infrastructure, I’ve been migrating away from GitHub to Codeberg, a non-profit code hosting platform based in Germany. One of the things I needed was a CI pipeline to build a container image and push it to the Codeberg container registry for my wildfires project (which also posts to @catfires@rls.social). It took a few tries to get right, so here’s what works for me.

The workflow

name: Build and push container image

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: codeberg-small
    steps:
      - name: Checkout
        uses: https://code.forgejo.org/actions/checkout@v4

      - name: Install buildah
        run: apt-get update -qq && apt-get install -y buildah ca-certificates

      - name: Build image
        run: |
          buildah build \
            --storage-driver=vfs \
            --isolation=chroot \
            --tag codeberg.org/YOUR_USERNAME/YOUR_IMAGE:latest \
            .

      - name: Push image
        run: |
          buildah push \
            --storage-driver=vfs \
            --creds YOUR_USERNAME:${{ secrets.REGISTRY_TOKEN }} \
            codeberg.org/YOUR_USERNAME/YOUR_IMAGE:latest

Registry token

The automatic FORGEJO_TOKEN cannot push to the container registry. You need a personal access token with write:packages scope. Create one under Settings → Applications → Access Tokens, then add it as a repository secret named REGISTRY_TOKEN under Settings → Actions → Secrets.

Why buildah, and why those flags

Codeberg’s hosted runners are rootless Podman containers running inside LXC containers. Neither docker nor podman are available. buildah is the right tool here, but it needs two flags to work in this environment:

  • --storage-driver=vfs — the default overlay driver needs FUSE, which isn’t available inside the nested container
  • --isolation=chroot — avoids namespace operations that require elevated privileges

Both flags are needed on buildah build and buildah push.

What didn’t work

  • docker/build-push-action — tries to connect to /var/run/docker.sock which doesn’t exist
  • podman build directly — not installed on the runners
  • buildah without --storage-driver=vfs — fails because overlayfs requires FUSE
Join the conversation
Have thoughts on any of this post? Reply on Mastodon or find me at @cdamian@rls.social.