LabHub

Blog

Podman 6.0 — slirp4netns, CNI, and cgroups v1 Removed; macOS's Default Provider Is Now libkrun

한국어English日本語中文

Introduction — A Major Release After 27 Months, and a Quiet Change of Home

Podman 6.0.0 was released on June 24, 2026. Since 5.0.0 shipped on March 19, 2024, that makes this a major release 27 months later. Close behind, 6.0.1 came out on July 8, along with — the same day — 5.8.5 from the 5.8 branch. The fact that the older-generation branch is still receiving patches right after a major release is itself important material for the "when to upgrade" judgment later in this post.

Before the version number, what stands out is the repository address. Every issue link in the release notes points to github.com/podman-container-tools/podman. Together with Buildah, Skopeo, and others, Podman was approved into the CNCF Sandbox on January 21, 2025 under the name "Podman Container Tools" (CNCF project page, Red Hat announcement), and 6.0 is where the GitHub organization move actually took effect. The Go import path also changed from github.com/containers/podman/v5 to go.podman.io/podman/v6. For any project importing Podman as a library, this alone is a migration task.

This blog already covered the story of switching from Docker to Podman. Less than ten days after that post said "Podman is on the 5.x generation," 6.0 shipped — so this post is its sequel. It looks only at what the release notes themselves say: what got removed in 6.0, and what changes on the desktop (macOS especially). The latest developments on the container image layer side were covered separately in containerd's native EROFS layers; this post focuses on the runtime and desktop layer.

The Removal List First — Check Your Environment Before Upgrading

6.0 is a release where removal, not new features, takes center stage. Carrying the Breaking Changes from the release notes over directly:

Attached to this is a companion stack requirement. 6.0.0 must be used together with Buildah v1.44.0, Skopeo v1.23, and Netavark/Aardvark v2.0.0, and the config-file parsing logic was rewritten from the ground up, with a separate design document published for it. Distro package users get this combination matched by their distro, but anyone building from source or running a partial upgrade needs to verify the version combination themselves.

You can check whether your environment hits the removal list before upgrading, like this:

# if the network backend is cni, it won't work on 6.0 (must be netavark)
podman info --format '{{.Host.NetworkBackend}}'

# check whether rootless networking is pinned to slirp4netns — check containers.conf
grep -r "slirp4netns" ~/.config/containers/ /etc/containers/ 2>/dev/null

# DB backend — if boltdb, a sqlite migration runs on 6.0's first launch
podman info --format '{{.Host.DatabaseBackend}}'

# cgroups version — if v1, the host needs to change first
podman info --format '{{.Host.CgroupsVersion}}'

BoltDB → SQLite does have an automatic migration, but trusting the word "automatic" enough to run a major upgrade without a backup is a separate matter. Cleaning up containers before upgrading is the safer route.

macOS — The Default Provider Is Now libkrun

Let me set the background for the macOS story first: in 5.0 (2024-03), the QEMU provider was removed and the Apple-native-hypervisor-based applehv (internally vfkit + Virtualization.framework) became the default, and in 5.2 (2024-08) the libkrun backend was added. The advantage of libkrun the release notes stated at the time was that it could mount a GPU into the VM to accelerate work, and the default stayed at applehv.

6.0 flipped that default. The release notes, verbatim: "The default podman machine provider on Macs has been changed to libkrun." This looks like a choice not unrelated to the growing demand to use a GPU inside a VM, for things like local LLM inference (this isn't a guess — the 5.2 notes themselves state GPU mounting as libkrun's reason for existing).

Practically important points:

And here's the part that needs an honest look. Whether libkrun is mature enough to be the default is a question the evidence doesn't settle cleanly. The bug that 6.0.1 and 5.8.5 fixed on the same day was: "the host's port-scanning process could unintentionally send a shutdown command to the libkrun VM, causing the VM to periodically shut down" — meaning this was the very first patch to arrive, just two weeks after the default was promoted. Also, a discussion from December 2025 reported bind-mount permission problems when using libkrun in a classroom setting (by the reporter's own count, about a quarter of students had to loosen host directory permissions to 777 to get the mount to work), and said the issue didn't reproduce on applehv. It's a single user's report, so it can't be generalized, but if your work centers on -v bind mounts, that's reason enough to verify against your own workflow before following the new default.

Worth noting on the Windows side too: in exchange for dropping Windows 10 support, starting and stopping a hyperv provider VM no longer requires administrator privileges (creation still does, and this only applies to new VMs), and a podman system hyperv-prep command was added for an administrator to prep the host in advance.

The Pasta-Only Era — and the Pesto Experiment

The removal of slirp4netns isn't sudden. In 5.0, the rootless default networking had already switched from slirp4netns to pasta ("for improved performance" — the 5.0 release notes), and 6.0 simply deleted code that hadn't been the default for over two years. Even so, environments where slirp4netns is baked into containers.conf or scripts will still be out there, so the one-line grep above is worth running.

One behavioral trait worth knowing in the pasta-only era: as the Podman networking tutorial states explicitly, containers in pasta mode are isolated from each other by default. There's no virtual network the way a bridge provides one, so communication between containers has to go through host port mapping, or the containers need to share a network namespace by being placed in the same pod. If containers in rootless mode need to talk to each other directly, the standard approach is to create a rootless netavark bridge network.

But rootless bridges carry an old pain point — rootlessport, which handles port forwarding, sits in as a proxy, which means the client source IP a container sees is not the real address. Anyone who's seen every connection log stamped with the gateway address knows this one. 6.0 adds an experimental alternative here: set this in containers.conf,

[network]
rootless_port_forwarder = "pasta"

and port forwarding for the rootless bridge network is handled not by rootlessport but by a tool called Pesto, using pasta's kernel-level forwarding. According to the source code's own description, a shared pasta instance in the rootless namespace takes over host-side forwarding, handling localhost traffic via kernel splice and external traffic via TAP, while preserving the source IP — so the container sees the real client address instead of a proxy or gateway address.

It's a welcome capability, but expectations should be tempered. The default is still rootlessport, the release notes themselves say "we'll consider switching once stability is more certain," and it requires a passt version that includes the pesto binary (passt-0^20260507.g1afd4ed or later). And 6.0.1 has already fixed a Pesto rule-cleanup bug (rules weren't cleaned up on container restart or network reload, causing forwarding to fail). The "experimental" label isn't decorative. This is a stage for opt-in verification in environments where source IP genuinely matters (fail2ban-style tools, access control, audit logs) — not a stage for a production default.

One more appendix-sized experiment: on kernel 6.18 and above, a feature landed that replaces the pause process used to hold open a rootless user namespace with an nsfs file handle. It's an experimental feature hiding behind the drop-pause-process environment variable, but it's a signal that one of rootless Podman's longstanding structural pieces could go away.

Quadlet — From .app Files to Subdirectories

There's a structural change on the Quadlet side too — the system for managing containers as systemd units. Previously, Quadlet units and their accompanying files installed via podman quadlet install were tracked as .app files; starting in 6.0, they're placed in a subdirectory instead. The release notes explain this should reduce bugs and make manual management easier — which, said the other way around, means scripts or docs that relied on the .app approach need updating.

Other Quadlet changes:

The shift where podman generate systemd becomes legacy and Quadlet becomes the answer is exactly what was covered in the migration guide; 6.0 pushes that same Quadlet toward becoming "something a distro can package and distribute." It reads as a signal that deploying containers as systemd services is becoming a first-class pattern.

Docker Compatibility Improvements = Changed Script Behavior

A good chunk of 6.0's Breaking Changes are about "making it match Docker." Compatibility improvements are welcome, but flip that around and it means scripts that were tuned to the old Podman behavior will now quietly behave differently. The ones easy to get tripped up by:

It's easy to read past a sentence like "Docker compatibility got better," but in CI or cleanup cron jobs, a change in the meaning of volume prune and filters is an actual change in how data gets deleted. Watching the first run closely after upgrading is worth doing.

CVE-2026-57231 — Reason Enough to Upgrade If You're on 5.8.3 or Below

There's one security fix that shipped alongside 6.0.0. GHSA-4hq8-gpf5-8p68 (CVE-2026-57231, GitHub severity: high): a malicious image could leak host environment variables into the container via crafted Env entries, and using wildcard globs made it possible to exfiltrate large numbers of them without even knowing the variable names in advance. The affected range is v1.8.1 through v5.8.3 — effectively every version from the past several years. The fix landed in v5.8.4 (2026-06-26) and v6.0.0.

The category of vulnerability where "just pulling and running an image leaks host environment variables" hits desktop users especially hard. A development machine is exactly the kind of shell environment where API keys and tokens sit exported. Even if you have no plan to move to 6.0, if you're on 5.8.3 or below, you should still upgrade to at least 5.8.4.

So, When Should You Upgrade?

Fine to upgrade now, if:

Wait, or stay on 5.8.x, if:

One more quiet change worth adding: podman machine os apply was rewritten around bootc switch in 6.0. That means OS updates for machine VMs are now handled as a switch to a bootable container image — the immutable-OS pattern has made its way down to desktop VMs (for the server-side immutable OS story, see the Talos 1.13 post).

Closing

Podman 6.0 isn't a release that lures you in with new features; it's a release that pays off debt. slirp4netns, CNI, iptables, cgroups v1, BoltDB — every one of these already had a designated successor years ago, and 6.0 is the declaration that the grace period is over. On top of that sits a governance change (the CNCF move), a desktop change (the libkrun switch on macOS), and Pesto, the next experiment in rootless networking.

The upgrade call is simple. Check whether you hit the removal list with the three podman info lines above; if you do, resolve that first. If you're on macOS, choose your provider deliberately. If you have a lot of automation, audit the Docker-compatibility change list before upgrading. And either way, don't stay on 5.8.3 or below — CVE-2026-57231 alone is reason enough.

References

Comments

No comments yet.

Sign in to leave a comment