# Building OxCaml packages for Debian, Fedora, Homebrew and Arch

*2026-05-17 — note*


I needed to install [OxCaml](https://anil.recoil.org/projects/oxcaml) quickly on a fresh machine without
any [opam](https://opam.ocaml.org) machinery. This was an excellent excuse
to refresh my memory on how distributing system packages for distributions
like Debian, Arch, Fedora and Homebrew work.

I've built **[oxcaml-pkgs](https://tangled.org/anil.recoil.org/oxcaml-pkgs)**
to churn out native packages for the distros I need, with details below
for future reference.

These all install an `oxcaml-compiler` package into `/opt`, since anywhere else
would clash with the native OCaml packaging. The idea is that a consumer can
add this to their PATH to specifically get OxCaml. However, I don't intend
most people to do this manually as I'm wrapping this in my [oi](https://github.com/avsm/oi)
at the moment.

## The quick installer script

If you just want OxCaml and don't care how, there's a one-shot installer:

```sh
curl -fsSL https://oi.thicket.dev/repo/install.sh | sh
```

The rest of this note is the manual breakdown of what that script automates,
mostly so I remember how each packaging system works the next time I revisit
it\!

## Debian / Ubuntu

```sh
curl -fsSL https://oi.thicket.dev/repo/apt/oxcaml.asc | sudo gpg --dearmor -o /usr/share/keyrings/oxcaml.gpg
# pick your release: noble, resolute, or trixie
echo 'deb [signed-by=/usr/share/keyrings/oxcaml.gpg] https://oi.thicket.dev/repo/apt resolute main' | sudo tee /etc/apt/sources.list.d/oxcaml.list
sudo apt update && sudo apt install oxcaml-compiler
```

Debian and Ubuntu both maintain [packaging metadata in a debian/](https://tangled.org/anil.recoil.org/oxcaml-pkgs/tree/main/packaging/deb/debian)
directory with various bits of metadata, e.g.:

```
Source: oxcaml-compiler
Section: devel
Priority: optional
Maintainer: @MAINTAINER@
Build-Depends: debhelper-compat (= 13),
 gcc, g++, make, m4, autoconf, perl, rsync, tar, gzip, bzip2, pkg-config, zstd
Standards-Version: 4.7.0
Homepage: https://oxcaml.org
Rules-Requires-Root: no

Package: oxcaml-compiler
Architecture: any
Depends: ${misc:Depends}, libc6
```

This is then compiled from a source package to an architecture-specific binary one that has a `.deb` extension.
That's done via [scripts](https://tangled.org/anil.recoil.org/oxcaml-pkgs/blob/main/packaging/deb/pbuild.sh) that invoke [pbuilder](https://pbuilder-team.pages.debian.net/pbuilder/) in a Docker container for the exact Ubuntu or Debian distro.

I would have used [Launchpad](https://launchpad.net) as I used to do for [opam PPAs](https://anil.recoil.org/notes/docker-and-opam) back in the day, but it's currently down due to a [DDoS](https://discourse.ubuntu.com/t/launchpad-still-down-even-though-status-reports-as-up-all-day/81586) so I'm building these myself for now.

## Fedora 44

```sh
sudo tee /etc/yum.repos.d/oxcaml.repo >/dev/null <<'EOF'
[oxcaml]
name=OxCaml
baseurl=https://oi.thicket.dev/repo/rpm/fedora-44
enabled=1
gpgcheck=0
repo_gpgcheck=1
gpgkey=https://oi.thicket.dev/repo/rpm/fedora-44/oxcaml.asc
EOF
sudo dnf install oxcaml-compiler
```

Fedora's got the [DNF](https://docs.fedoraproject.org/en-US/quick-docs/dnf/) package manager, which uses [spec files](https://tangled.org/anil.recoil.org/oxcaml-pkgs/blob/main/packaging/rpm/oxcaml-compiler.spec.in) to wrap the build. These source RPMs are then compiled to binary ones via a [mock build in a Docker container](https://tangled.org/anil.recoil.org/oxcaml-pkgs/blob/main/packaging/rpm/mockbuild.sh) for that distro.

Once that's done, the repository metadata is assembled using [createrepo](https://tangled.org/anil.recoil.org/oxcaml-pkgs/blob/main/packaging/repo/mkrepo.sh#L129), and a bunch of files that can be served over HTTP.

## Arch Linux

```sh
curl -fsSL https://oi.thicket.dev/repo/arch/oxcaml.asc | sudo pacman-key --add -
sudo pacman-key --lsign-key <keyid>
sudo tee -a /etc/pacman.conf >/dev/null <<'EOF'

[oxcaml]
SigLevel = Required DatabaseOptional
Server = https://oi.thicket.dev/repo/arch/$arch
EOF
sudo pacman -Sy oxcaml-compiler
```

Arch uses [PKGBUILD](https://tangled.org/anil.recoil.org/oxcaml-pkgs/blob/main/packaging/arch/PKGBUILD.in) files for its metadata format, which `makepkg` compiles into a simple [`.pkg.tar.zst` layer](https://tangled.org/anil.recoil.org/oxcaml-pkgs/blob/main/packaging/arch/makepkg/build-pkg.sh) in an `archlinux` container; `repo-add` then stitches them into a pacman database.

## Homebrew

My [custom Homebrew instructions](https://anil.recoil.org/notes/custom-homebrew-taps) from yesteryear still work fine, so I just pushed a [Homebrew OxCaml formula](https://github.com/avsm/homebrew-ocaml/pull/22/changes) there and let the [brew bot](https://docs.brew.sh/BrewTestBot) do its magic.

The release flow here is two stage:

- `tests.yml` runs `brew test-bot` on every PR, building the formula and uploading the resulting bottles as CI artifacts.
- Then when I manually add the `pr-pull` label to that PR, `publish.yml` fires on the `labeled` event, runs `brew pr-pull` to download those built bottles, commits them with the formula to `main`, pushes, and deletes the branch.

The only quirk here is to not link it into `/opt/homebrew` as it would collide with OCaml, so it's marked "keg only" (installed but not symlinked into the prefix).  I think we can integrate the brew bottling directly into [obuilder](https://github.com/ocurrent/obuilder) just as soon as we add [secrets support](https://github.com/ocurrent/obuilder/pull/207) to the macOS backend.

## Resurrecting a 2013 GPG key

I did also have to do some GPG shenanigans as my ancient Debian signing key
from 2013 is now rejected because its crypto signature used SHA-1.
Modern `gpg`, `apt` and `pacman` reject SHA-1 certifications outright now
as being too weak, so `reprepro` refused to trust me anymore.

Upgrading the key gracefully (rather than minting a brand new identity and
losing decades worth of signatures) turned out to be fiddly, and I have
only the haziest memory of modern keyserver etiquette. The last time I
looked at this seriously was chatting to [Yaron Minsky](https://github.com/yminsky) about fifteen years
ago about his [SKS OCaml keyserver](https://github.com/yminsky/sks-keyserver)\!

Anyway, I have a fresh `ed25519` signing subkey now, so I'll properly
rebuild the web of trust later on. Maybe [tangled.org](https://tangled.org)'s
new [vouching system](https://anil.recoil.org/notes/2026w18) would be a good place to anchor a PGP web
of trust again.

## Reproducing the OxCaml opam directives

The most fiddly part of all this was reproducing the OxCaml build
*exactly* as its [opam directives](https://github.com/oxcaml/opam-repository) would, but without opam in the loop
and just a single unified tarball where you can do a `make && make install`. Distros typically abhor other package managers...

I used a fair amount of [agentic coding](https://anil.recoil.org/notes/aoah-2025) here: I pinned the
`oxcaml-compiler.5.2.0minus31` opam package and had Claude resolve the
patch list and build/install steps into a single shell script, then
verified that the resulting unified patches were byte-identical to what
opam would have assembled.

This is also all fiddly enough that it makes me want to investigate [package
repositories on ATProto](https://oppi.li/weeklies/2026-19/) more now...
Synopsis: Native OxCaml system packages for Debian/Ubuntu, Fedora, Arch and Homebrew — plus reviving a 2013 GPG key that modern tooling rejects for SHA-1, and using agentic coding to collapse the opam build into one tarball.
Words: 873

## Related

- [.plan-26-18: From tropical forest protection to oi swallowing its oxcaml tail](https://anil.recoil.org/notes/2026w18) (note, 2026-05-03)
- [2025 Advent of Agentic Humps: Building a useful O(x)Caml library every day](https://anil.recoil.org/notes/aoah-2025) (note, 2025-12-26)
- [How to publish custom Homebrew taps for OCaml](https://anil.recoil.org/notes/custom-homebrew-taps) (note, 2025-01-31)
- [OxCaml Labs](https://anil.recoil.org/projects/oxcaml) (project, 2025-01-01)
- [Using Docker to bulk-build OPAM packages on Linux](https://anil.recoil.org/notes/docker-and-opam) (note, 2013-11-15)

---
Canonical: https://anil.recoil.org/notes/oxcaml-packages
Type: note
Tags: ocaml, oxcaml, packaging, llms, linux
