Inside the Wolfi package repository: melange build files, apko images and rolling patches
Main package repository for production Wolfi images
At a glance
- What is it?
- Chainguard's rolling GNU/Linux package set, built with melange and consumed by apko for container images, with a policy that every package must track an actively maintained upstream. The repository is a read-only public clone of internal repositories, so nothing you push here can be merged.
- Who is it for?
- Adopt Wolfi if you build container images and want a package set that rolls with security patches rather than one frozen on a distribution release cycle. Do not adopt it as a general purpose operating system, because the README says plainly that it is not intended to be one, and do not mix its packages with Alpine's even though both use apk, because the packages are not compatible and doing so creates security problems.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Shell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A package set, deliberately not a distribution
Wolfi is the main package repository for the Wolfi project, and the description sets out what it is in one sentence. It is a lightweight GNU software distribution designed around minimalism, which makes it well suited for containerized environments built with apko.
The distribution is built using melange and is sponsored by Chainguard, which uses it to provide lightweight GNU/Linux runtime images.
The important word in that is package repository. The README is explicit that Wolfi is not intended to be a general purpose desktop operating system, and that the priority is to provide packages that enable containerized and embedded system workflows. So the deliverable is a set of packages with a repository and a signing key, not an installer, not a live image, and not a set of installable media.
Two operational details follow from that. The Wolfi APK package repository is at packages.wolfi.dev/os, and the signing public key is published alongside it at packages.wolfi.dev/os/wolfi-signing.rsa.pub, which is what a consumer needs to verify what it pulls.
The policy is stated with the same plainness. Packages must use an open source license, ideally FSF or OSI approved licences. Wolfi aims to keep its package set as up to date with security patches as possible, and uses the latest releases of packages by default. And a package and version in Wolfi must have an actively maintained upstream project.
That last rule is the sharpest one. It is an admission criterion rather than a preference, which means the set of things you can install is bounded by what somebody upstream is still working on. For a container base image that is a feature, because a package with a dead upstream is a package with a frozen vulnerability, and for a general purpose system it would be crippling.
The repository is a mirror, and the pipeline is melange YAML
The repository layout is the interesting part, and it is two things at once: a catalogue of packages and the build definitions that produce them.
The top level is a very long list of YAML files, one per package, with source directories alongside some of them. `abseil-cpp.yaml` sits next to `abseil-cpp-20250127.yaml` and `abseil-cpp-20260107.yaml` and `abseil-cpp-20260526.yaml`, and then `abseil-cpp.yaml` itself. The R packages follow the same pattern with `R.yaml`, `R-DBI.yaml`, `R-classInt.yaml` and the rest. There are also `7zip.yaml`, `Catch2.yaml`, `Rcpp.yaml`, `docker-compose.yaml` and so on.
The pattern is the key. A package can have dated variants alongside the rolling one, so a build that needs a pinned version of a library has a way to get it, and the default entry tracks the latest. That is what makes the set usable in a world where upstream releases move quickly and reproducibility still matters.
The build definitions are melange configurations, and the `docker-compose.yaml` file in the repository shows the shape of one in full. The package block carries a name, a version, an epoch with a CVE reference in a comment, a description, and a copyright block with the license. The environment block lists the build and runtime packages needed, and the pipeline block describes the steps.
package:
name: docker-compose
version: "5.6.0"
epoch: 2 # CVE-2026-78659
description: Define and run multi-container applications with Docker
copyright:
- license: Apache-2.0The epoch field is the interesting one for anyone who has dealt with package management. An epoch bump is how a package signals a breaking change that cannot be expressed in the version number, and the comment shows it being used for a CVE, which is a good illustration of why the mechanism exists in a distribution that ships the latest upstream releases by default.
The test block in that same file shows the testing vocabulary, using `test/tw/ldd-check` for shared library dependencies, `test/tw/help-check` for the help output, and `test/tw/ver-check` for the version string, plus plain shell steps that verify a symlink exists and that the CLI subcommand reports the expected version.
The Makefile is a build tool with opinions about architecture
The Makefile at the repository root is where the practical instructions live, and the comments are unusually informative about the constraints.
The first thing it explains is the architecture handling. The `ARCH` variable is one of aarch64 or x86_64, you run the make on and for that architecture, and running aarch64 on x86 is extremely slow, so you probably want an ARM workstation. The default is the current architecture.
Then the melange options. `MELANGE_EXTRA_OPTS` passes extra command line options through to melange, and `MELANGE_RUNNER` chooses the runner used to build and test the packages, one of qemu, docker or bubblewrap. The comment says qemu is usually the best choice, bubblewrap uses less resources, and docker might be required for some tests to work, and that they should make that consistent. The `MELANGE_TMPDIR` variable sets the directory for the melange cache and build files, defaulting to `$TMPDIR` or `/tmp`.
The `USE_PODMAN` variable is the most detailed, and it exists because a lot of CI runs podman with the docker alias. Setting it to true when the docker command is an alias to podman running in rootless mode adds appropriate modifications to the docker commands and other utilities that require different behavior when running as a non-root Linux process, with a note that some of the modifications may be specific to podman or may require additional external configuration, for example installing the podman-docker package on Fedora.
The make targets are named after what they do. `make debug/{foo}` builds a package in debug mode, and if a pipeline command fails you get dropped into a shell running inside the container for further investigation. `make local-wolfi` boots a local container with access to and locally built APKs. `make package/{foo}` builds a package and `make test/{foo}` tests it.
The debug target is the interesting design choice. A package build that fails inside a container normally leaves you with an error message and a log. Dropping the failing command into a shell in the same environment means you can inspect the filesystem, re-run the failing step and try variations, all inside the exact environment the build uses. For a repository this size, that is the difference between fixing a broken build in minutes and not fixing it at all.
Policy documents, and the Alpine incompatibility
The repository has a set of policy documents at the root, and their names describe the governance model.
There is `HOW_TO_PATCH_CVES.md` about how to patch a CVE, plus `REPRODUCIBILITY.md`, `RESTORING_PACKAGES.md` and `WITHDRAWING_PACKAGES.md`. Those last two are the ones that describe a real operating discipline. Restoring a package means bringing back a version that was withdrawn, and withdrawing a package means removing it, and both are operations a distribution needs and that a casual reader would never think about.
There is `CONTRIBUTING.md`, which the README points to for details, and the README is clear about the consequence. This repository is a read-only public clone, synced from internal Chainguard repositories, and pull requests opened here cannot be merged directly.
That is the single most important operational fact in the README for anyone who wants to contribute. The contribution path is not this repository. A pull request opened here goes nowhere, and the repository exists so that people can read the package definitions, browse the catalogue and understand the system without an account.
The other policy is the mixing rule, and it is stated in its own section. Mixing packages with other distributions is not supported and can create security problems, and although both Wolfi and Alpine use the apk package manager, packages are not compatible with each other.
That is worth dwelling on, because the shared package manager makes it look like a supported option. Same format, same tool, different contents, and the mismatch is a security problem rather than a cosmetic one. It is the kind of thing that gets discovered in production rather than in a test, and the README putting it in bold at the end of a short document is the right place for it.
Trying it, and what the base image shows you
The Getting Started section gives one command, and the output it produces is the clearest possible statement of what Wolfi is.
docker run -it cgr.dev/chainguard/wolfi-baseThen the shell prompt, and two commands that answer the questions you would otherwise have to guess at.
52aace776b20:/# uname -a
Linux 52aace776b20 5.15.49-linuxkit-pr #1 SMP PREEMPT Thu May 25 07:27:39 UTC 2023 aarch64 Linux
52aace776b20:/# cat /etc/os-release
ID=wolfi
NAME="Wolfi"
PRETTY_NAME="Wolfi"
VERSION_ID="20230201"
HOME_URL="https://wolfi.dev"The `uname -a` line shows a bare kernel with no init system, running on aarch64 under the linuxkit kernel. The `/etc/os-release` shows the identity fields, and the `VERSION_ID` of 20230201 is the giveaway that this is a rolling distribution. There is no release number because there is no release. The identifier is a date, and it changes with the package set rather than with a versioned image.
That is the whole design in two commands. What you get is a filesystem and a package manager, assembled at build time by apko into an image, with no init system and no long term support commitment, because the point is that the packages get security patches as soon as upstream publishes them rather than when a distribution release ships.
The name is the smallest octopus, and the logo in the README is drawn twice, once for dark mode and once for light mode, following the GitHub themed image syntax so the logo matches the viewer's colour scheme. There is a `CLAUDE.md` and a `.claude/` directory for AI assistant conventions, a `.devcontainer/` for the development environment, a `.prettierrc` and a `.yam.yaml` file, the latter presumably for formatting the YAML package definitions that dominate this repository.
Editorial conclusion
Adopt Wolfi if you build container images and want a package set that rolls with security patches rather than one frozen on a distribution release cycle. Do not adopt it as a general purpose operating system, because the README says plainly that it is not intended to be one, and do not mix its packages with Alpine's even though both use apk, because the packages are not compatible and doing so creates security problems. Verify first that each dependency you need has an actively maintained upstream, since that is an admission criterion rather than a preference, and that your base image tooling is apko, since the packages are built for that consumption model.
Frequently asked questions
What is Wolfi?
Wolfi is a lightweight GNU software distribution designed around minimalism, which makes it well suited for containerized environments built with apko. It is built using melange and is sponsored by Chainguard, which uses it to provide lightweight GNU/Linux runtime images.
Can I open a pull request against the Wolfi repository?
No. The README states that this repository is a read-only public clone synced from internal Chainguard repositories, and that pull requests opened here cannot be merged directly. The CONTRIBUTING.md file has the details of the actual contribution path.
Can I mix Wolfi packages with Alpine packages?
No. The README says mixing packages with other distributions is not supported and can create security problems, and that although both Wolfi and Alpine use the apk package manager, packages are not compatible with each other.
What is the policy for a package to be in Wolfi?
Packages must use an open source license, ideally FSF or OSI approved, and a package and version in Wolfi must have an actively maintained upstream project. Wolfi also aims to keep its package set as up to date with security patches as possible and uses the latest releases by default.
How do I build or test a Wolfi package locally?
The Makefile provides make package/{foo} to build a package and make test/{foo} to test it, with make debug/{foo} dropping you into a shell inside the container if a pipeline step fails. The runner used to build and test is chosen with MELANGE_RUNNER as qemu, docker or bubblewrap, and ARCH selects aarch64 or x86_64.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/wolfi-dev-os)Was this useful?