Overview

CI/CD Integration

The build farm challenge#

The challenge: how do you build native FreeBSD images without maintaining a private, physical build farm?

The solution: Daemonless uses GitHub Actions with vmactions/freebsd-vm to run native FreeBSD 15 environments inside Ubuntu runners via QEMU/KVM. This provides a real FreeBSD kernel, native tooling (pkg, podman, buildah), and a consistent environment for building complex native components like Python wheels.

dbuild ci-run pipeline#

ci-run is the single entry point for automated pipelines:

graph TD
    A[Source Code] --> B[dbuild build]
    B --> C[dbuild test]
    C -->|Pass| D{PR?}
    C -->|Fail| E[Abort]
    D -->|No| F[dbuild push]
    D -->|Yes| G[Done]
    F --> H[dbuild sbom]
    F --> I[dbuild manifest]
    H --> G
    I --> G
  1. Prepare (optional, with --prepare) — installs tools and configures networking.
  2. Build — builds all variants; exits immediately on failure.
  3. Test — runs Container Integration Tests (CIT) for all variants.
  4. PR check — if a pull request is detected, the pipeline stops (skips push/sbom).
  5. Push — tags and pushes images to the registry, mirrors to Docker Hub.
  6. Post-push — generates SBOMs and multi-arch manifests.
- name: Run CI Pipeline
  uses: vmactions/freebsd-vm@v1
  with:
    release: "15.0"
    usesh: true
    run: |
      pip install dbuild
      dbuild ci-run --prepare

Skip directives#

Control CI behavior by adding these tags to commit messages:

Directive Effect
[skip test] Skip the entire testing phase
[skip push] Build and test, but do not push to any registry
[skip push:dockerhub] Push to GHCR, but skip the Docker Hub mirror
[skip sbom] Skip CycloneDX SBOM generation

Linux pre-build artifacts#

Some images require assets built with toolchains unavailable on FreeBSD (e.g. SWC for JavaScript frontends). These are built on a Linux runner first and passed into the FreeBSD build as a GitHub Actions artifact — see the Linux Pre-Build guide on daemonless.io for the full pattern.

CI environment setup#

dbuild ci-prepare installs everything needed to build on a fresh FreeBSD VM (requires root):

  1. Configures the FreeBSD latest package repository.
  2. Installs podman, buildah, skopeo, jq, trivy, and python3.
  3. Installs ocijail 0.5.0+ (required for jail annotations like allow.mlock).
  4. Cleans stale container state.
  5. Loads the pf kernel module and enables IP forwarding.
doas dbuild ci-prepare --compose

Preflight checks#

Run dbuild ci-test-env to verify a CI runner is ready. It validates required tools (podman, buildah, etc.), Podman runtime connectivity (expects ocijail), networking configuration (PF and IP forwarding), and jail annotation support (mlock and sysvipc). Returns exit code 0 if all required checks pass.

Building your own image?

Wire this same pipeline into your repo with dbuild init --github.

Updated

Was this page helpful?