Podman is the container engine Fedora ships and supports. It runs containers without a daemon, and as a normal user by default. Fedora 45 carries Podman 6.1 and Fedora 44 carries Podman 5.8. The install is one command on both. The parts that catch people out come after the install: published ports that firewalld blocks for one user and not for another, containers that die when you log out, and search settings in registries.conf that Fedora 45 now overrides. Tested on Fedora 45 and Fedora 44 in October 2026; every output below is a real capture from those two VMs.
What you get on Fedora 45 and Fedora 44
Both releases use the same stack: netavark for networking, pasta for rootless networking, SQLite for the container database and cgroup v2. The difference is the Podman major version and where the default config lives.
| Component | Fedora 44 | Fedora 45 |
|---|---|---|
| Podman | 5.8.7 | 6.1.3 |
| netavark | 1.17.2 | 2.1.0 |
| crun | 1.28 | 1.30.1 |
| containers-common | 0.67.2 | 0.69.2 |
| Rootless network | pasta | pasta (slirp4netns removed in Podman 6) |
| Default config files | /etc/containers/ | /usr/share/containers/*.conf.d/00-vendor.conf |
Podman 6 dropped slirp4netns, the iptables firewall driver and the old BoltDB database. If you are upgrading a Fedora 44 machine that already has containers, read how to fix Podman containers after a Fedora upgrade first. The full list of upstream removals is in Podman 6 breaking changes.
Install Podman
Fedora Workstation pulls Podman in for Toolbx, and the Fedora Cloud images we used had it installed through the image package group. Check before you install anything:
rpm -q podman
On a minimal install, or after removing it, install it from the Fedora repos:
sudo dnf install -y podman
On Fedora 45 that pulled 45 packages and used 256 MiB. Most of the size is qemu-user-static, a weak dependency that lets Podman run images built for other CPU architectures. Fedora 44 pulled 45 packages for 247 MiB. If you only run x86_64 images, skip the weak dependencies:
sudo dnf install -y --setopt=install_weak_deps=False podman
That drops the transaction to 19 packages and 78 MiB. Rootless containers, pasta networking and overlay storage all worked on the slim install. What you lose is foreign-architecture images. Without the emulator, an arm64 image pulls fine and then fails at exec. The pull progress lines are left out below:
podman run --rm --platform linux/arm64 docker.io/library/alpine:latest uname -m
The run ends with:
{
"msg": "exec container process `/bin/uname`: Exec format error",
"level": "error",
"time": "2026-10-04T15:03:58.396550Z"
}
Install the emulator for the architecture you need and the same command works:
sudo dnf install -y qemu-user-static-aarch64
podman run --rm --platform linux/arm64 docker.io/library/alpine:latest uname -m
Leaving out the dnf transaction, the container reports its architecture:
aarch64
One detail from testing: removing the emulator package doesn’t unregister it from the running kernel. Right after dnf remove, the same arm64 run still printed aarch64. After a reboot, the same run failed as shown above.
Verify the install
Check the version and the components behind it:
podman version
rpm -q podman passt netavark aardvark-dns crun conmon containers-common-extra
Output on Fedora 45:
Client: Podman Engine
Version: 6.1.3
API Version: 6.1.3
Go Version: go1.27.1-X:nodwarf5
Git Commit: 85b994955e0b4e30fbce9c8351cab85676140ede
Built: Tue Sep 29 00:00:00 2026
Build Origin: Fedora Project
OS/Arch: linux/amd64
podman-6.1.3-1.fc45.x86_64
passt-0^20261002.gcba3570-1.fc45.x86_64
netavark-2.1.0-1.fc45.x86_64
aardvark-dns-2.1.0-1.fc45.x86_64
crun-1.30.1-1.fc45.x86_64
conmon-2.2.1-2.fc45.x86_64
containers-common-extra-0.69.2-1.fc45.noarch
Then confirm the storage driver, network backend, rootless network command, database and cgroup version in one line:
podman info --format "{{.Store.GraphDriverName}} {{.Host.NetworkBackend}} {{.Host.RootlessNetworkCmd}} {{.Host.DatabaseBackend}} {{.Host.CgroupsVersion}}"
Fedora 45 and Fedora 44 returned the same answer:
overlay netavark pasta sqlite v2
Both checks on the Fedora 45 VM:

Run your first rootless container
No group membership and no sudo is needed. Rootless Podman maps container users through the ranges in /etc/subuid and /etc/subgid, which useradd fills in for local users. Accounts from FreeIPA, LDAP or SSSD get no entries there and need them added. Confirm your entry exists:
grep "^$USER:" /etc/subuid /etc/subgid
Run a container with a fully qualified image name:
podman run --rm docker.io/library/alpine:latest cat /etc/alpine-release
Use the full name in scripts. Fedora enforces short-name resolution, so a bare name that has no alias stops when there is no terminal to prompt on:
podman pull adminer
It fails straight away:
Error: short-name resolution enforced but cannot prompt without a TTY
Common names like nginx and busybox work because they are listed in the shipped alias file. The next section shows how to add your own aliases and search registries.
Configure registries on Fedora 45
This is the change most likely to break an existing setup. On Fedora 44, /etc/containers/registries.conf holds the defaults and you edit it in place. On Fedora 45, containers-common ships no registries.conf or policy.json in /etc/containers. The defaults sit in drop-ins under /usr/share/containers:
ls /etc/containers/ /usr/share/containers/
The two directories on Fedora 45:
/etc/containers/:
certs.d
networks
oci
registries.conf.d
registries.d
systemd
/usr/share/containers/:
containers.conf
containers.conf.d
mounts.conf
podman-sequoia
policy.json
registries.conf
registries.conf.d
registries.d
seccomp.json
selinux
storage.conf
storage.conf.d
storage.rootful.conf.d
storage.rootless.conf.d
systemd
The search list and the short-name mode now come from /usr/share/containers/registries.conf.d/00-vendor.conf. Drop-ins are applied after the main file. So if you create, or carry over, a full /etc/containers/registries.conf, the vendor drop-in overrides its search list and short-name mode. Registry tables in it, such as mirrors, still apply. We tested that with a main file that sets a single search registry and permissive mode:
printf "unqualified-search-registries = [\"docker.io\"]\nshort-name-mode = \"permissive\"\n" | sudo tee /etc/containers/registries.conf >/dev/null
podman pull adminer
The pull still stops at the short-name check:
Error: short-name resolution enforced but cannot prompt without a TTY
Both settings were overridden. The fix is to put the same lines in a drop-in whose file name sorts after 00-vendor.conf. Drop-ins from all the directories are sorted together by file name, so a file called 00-local.conf would lose again:
sudo mv /etc/containers/registries.conf /etc/containers/registries.conf.d/50-search.conf
podman pull adminer
The first two lines of the pull:
Resolving "adminer" using unqualified-search registries (/etc/containers/registries.conf.d/50-search.conf)
Trying to pull docker.io/library/adminer:latest...
A single user can add aliases without root. Files in ~/.config/containers/registries.conf.d/ apply to that user only:
mkdir -p ~/.config/containers/registries.conf.d
printf "[aliases]\n \"adminer\" = \"docker.io/library/adminer\"\n" > ~/.config/containers/registries.conf.d/50-aliases.conf
podman pull adminer
The first two lines again show where the name came from:
Resolved "adminer" as an alias (/home/josphat/.config/containers/registries.conf.d/50-aliases.conf)
Trying to pull docker.io/library/adminer:latest...
The full search order, including the per-UID rootless directories, is in man 5 containers-registries.conf. On Fedora 44, editing /etc/containers/registries.conf still works as before.

Publish ports from rootless containers
Rootless containers cannot bind ports below 1024. The error comes from pasta, and it is identical on Fedora 44 and Fedora 45:
podman run -d --name web -p 80:80 docker.io/library/nginx:latest
Pasta refuses the bind:
Error: pasta failed with exit code 1:
Listen failed for HOST TCP port */80: Permission denied
Couldn't listen on requested ports
This catches people out: the failed run still creates the container. Retry with a different port and the name is taken:
podman run -d --name web -p 8080:80 docker.io/library/nginx:latest
Podman refuses the name:
Error: creating container storage: the container name "web" is already in use by a50122b9d2154503734873b280afe1868318b6add884feaadd09e82078365260. You have to remove that container to be able to reuse that name: that name is already in use, or use --replace to instruct Podman to do so.
Add --replace, or remove the leftover with podman rm web:
podman run -d --replace --name web -p 8080:80 docker.io/library/nginx:latest
curl -sI http://127.0.0.1:8080 | head -1
The new container ID, then the response:
ed8d2095c35ddb29704bf099b38a89302565351b49e273c61160fc0c2413cd05
HTTP/1.1 200 OK
If a rootless container must own port 80, lower the unprivileged port floor for the whole host:
echo "net.ipv4.ip_unprivileged_port_start = 80" | sudo tee /etc/sysctl.d/90-unprivileged-ports.conf
sudo sysctl --system
After that, -p 80:80 worked as a normal user. Every user on the host can then bind ports 80 to 1023, so prefer a reverse proxy on a single box shared by several people.
Open the firewall for published ports
Fedora Server and Workstation run firewalld. Rootless and rootful containers behave differently behind it, and the difference surprises people in both directions. Our Fedora 45 VM ran firewalld with the public zone, ran a rootless nginx on ports 80 and 8080, and a rootful nginx on port 8081:
sudo podman run -d --name rootweb -p 8081:80 docker.io/library/nginx:latest
From a second machine on the same network:
for p in 80 8080 8081; do printf "port %s: " $p; curl -s -o /dev/null -m 4 -w "%{http_code}\n" http://f45-01:$p/ || echo; done
Results:
port 80: 000
port 8080: 000
port 8081: 200
The rootless ports were blocked, which is what you want. The rootful port was reachable even though 8081 is not open in the zone. Netavark writes its own nftables DNAT rules, and firewalld accepts DNAT traffic:
sudo nft list ruleset | grep -E "table|dnat" | head
The relevant lines from the ruleset:
table inet netavark {
tcp dport 8081 jump nv_2f259bab_10_88_0_0_nm16_dnat
chain nv_2f259bab_10_88_0_0_nm16_dnat {
tcp dport 8081 ct mark set meta mark | 0x00001000 dnat ip to 10.88.0.2:80
table inet firewalld { # progname firewalld
ct status dnat accept
ct status dnat accept
ct status dnat accept
Fedora 44 with Podman 5.8 gave the same result: rootless 8080 blocked, rootful 8081 open. So treat every rootful -p as a public port. Bind it to one address when it should stay local, for example -p 127.0.0.1:8081:80.
Rootless ports need a normal firewalld rule:
sudo firewall-cmd --permanent --add-port={80,8080}/tcp
sudo firewall-cmd --reload
The same curl loop from the second machine, run for ports 80 and 8080, now gets an answer:
port 80: 200
port 8080: 200
The zone matters too. The FedoraWorkstation zone already allows TCP and UDP 1025 to 65535, so on a desktop install rootless ports above 1024 are reachable without any rule. The FedoraServer zone allows only cockpit, dhcpv6-client and ssh.

Use SELinux labels on bind mounts
SELinux is enforcing on Fedora. A host directory mounted without a label is unreadable inside the container. Nginx returned 403 for a page in the home directory:
mkdir -p ~/site && echo "hello from f45-01" > ~/site/index.html
podman run -d --replace --name site -p 8082:80 -v ~/site:/usr/share/nginx/html:ro docker.io/library/nginx:latest
curl -s http://127.0.0.1:8082/ | grep -o "<title>.*</title>"
Nginx cannot read the file:
<title>403 Forbidden</title>
Add Z to the mount options. Podman relabels the directory with a private container_file_t context:
podman run -d --replace --name site -p 8082:80 -v ~/site:/usr/share/nginx/html:ro,Z docker.io/library/nginx:latest
curl -s http://127.0.0.1:8082/
ls -Z ~/site/index.html
The page loads, and the file carries the new label:
hello from f45-01
system_u:object_r:container_file_t:s0:c170,c261 /home/josphat/site/index.html
Use a lowercase z when several containers share the directory. Never use either option on a system path like /home or /etc. For more SELinux detail, see Podman SELinux contexts.
Keep rootless containers running after logout
On a server this one bites. Rootless containers belong to your systemd user session. Without lingering, systemd stops that session about ten seconds after your last login closes, and the containers go with it. Our web container was started over SSH. When we logged back in 30 seconds later, it had already exited:
podman ps -a --format "{{.Names}} {{.Status}}"
Both containers had exited:
web80 Exited (0) 49 seconds ago
web Exited (0) 20 seconds ago
Enable lingering for the user. Run it with sudo; from a non-interactive SSH session a plain request from the user fails:
loginctl enable-linger
Over SSH, the request is refused:
Could not enable linger: Access denied
Run it with sudo instead:
sudo loginctl enable-linger $USER
loginctl show-user $USER -p Linger
Lingering is now on:
Linger=yes
With lingering on, both containers were still up after the session closed. Lingering keeps them alive. It does not start them again after a reboot. For that, use Quadlet.
Run a container as a systemd service with Quadlet
Quadlet turns a small .container file into a systemd unit. Create one in the Quadlet directory for your user:
mkdir -p ~/.config/containers/systemd
vi ~/.config/containers/systemd/web.container
The unit serves the same ~/site directory and opts into automatic image updates:
[Unit]
Description=nginx web
[Container]
Image=docker.io/library/nginx:latest
PublishPort=8080:80
Volume=%h/site:/usr/share/nginx/html:ro,Z
AutoUpdate=registry
[Install]
WantedBy=default.target
Preview the generated podman run line, then load and start the service:
/usr/libexec/podman/quadlet -dryrun -user 2>&1 | grep -E "^(ExecStart|---)" | head -3
systemctl --user daemon-reload
systemctl --user start web.service
The generated command line:
---web.service---
ExecStart=/usr/bin/podman run --name systemd-%N --replace --rm --cgroups=split --sdnotify=conmon -d -v %h/site:/usr/share/nginx/html:ro,Z --label io.containers.autoupdate=registry --publish 8080:80 docker.io/library/nginx:latest
Don’t run systemctl --user enable on it. The unit is generated:
systemctl --user enable web.service
Systemd refuses it:
Failed to enable unit: Unit /run/user/1001/systemd/generator/web.service is transient or generated
The [Install] section already does the job. After a reboot, with lingering on, the service started at boot on its own:
uptime -p; systemctl --user is-active web.service
podman ps --format "{{.Names}} {{.Status}} {{.Ports}}"
curl -s http://127.0.0.1:8080/
After the reboot:
up 0 minute
active
systemd-web Up 22 seconds 0.0.0.0:8080->80/tcp
hello from f45-01
The same unit file worked unchanged on Fedora 44. Pods, networks, volumes and .kube units are covered in Podman Quadlet with systemd on Fedora.

Turn on automatic image updates
The AutoUpdate=registry line labels the container, but nothing checks for updates until the timer runs. It is disabled by default on both releases. Check what would update:
podman auto-update --dry-run
One container is labelled for updates:
UNIT CONTAINER IMAGE POLICY UPDATED
web.service 272a6073c7e6 (systemd-web) docker.io/library/nginx:latest registry false
Then enable the daily timer for the user:
systemctl --user enable --now podman-auto-update.timer
systemctl --user list-timers podman-auto-update.timer --no-pager
The timer list is cut to its first two lines:
Created symlink '/home/josphat/.config/systemd/user/timers.target.wants/podman-auto-update.timer' → '/usr/lib/systemd/user/podman-auto-update.timer'.
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-10-05 00:00:19 UTC 8h - - podman-auto-update.timer podman-auto-update.service
When a newer image appears, Podman pulls it and restarts the service. If the restarted unit fails, Podman rolls back to the previous image. That check relies on systemd readiness, so an app that crashes after its container reports ready is not caught.
Use Docker tools with Podman
Many tools expect a docker command or a Docker socket. Podman covers both. The podman-docker package adds a docker wrapper:
sudo dnf install -y podman-docker
docker ps --format "{{.Names}}"
Skipping the dnf transaction, the docker call prints:
Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg.
web80
web
Create the file it mentions to silence the notice: sudo touch /etc/containers/nodocker. For tools that talk to the Docker API, start the user API socket:
systemctl --user enable --now podman.socket
curl -s --unix-socket $XDG_RUNTIME_DIR/podman/podman.sock http://d/_ping
The socket answers the ping:
Created symlink '/home/josphat/.config/systemd/user/sockets.target.wants/podman.socket' → '/usr/lib/systemd/user/podman.socket'.
OK
The socket answered the Docker-compatible API at version 1.44 on Podman 6.1.3. Point Docker clients at it with DOCKER_HOST when you run them directly. podman compose sets up that connection for its provider by itself, and it calls the Fedora docker-compose package when that is installed. We exported the variable anyway in our run. Our test project in ~/demo/compose.yaml was a single nginx service:
services:
web:
image: docker.io/library/nginx:latest
ports:
- "8083:80"
Install the provider and bring it up:
sudo dnf install -y docker-compose
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock
cd ~/demo && podman compose up -d
The compose run prints:
Container demo-web-1 Creating
Container demo-web-1 Created
Container demo-web-1 Starting
Container demo-web-1 Started
That output is the last four lines. The compose file and the choice between docker-compose and podman-compose are covered in Podman Compose on Fedora. If you need the real Docker Engine instead, follow install Docker on Fedora. Do not run both engines for the same workloads.
Troubleshooting
Error: short-name resolution enforced but cannot prompt without a TTY
The image name has no registry and no alias. Use the full name, such as docker.io/library/adminer, or add an alias or search registry in a drop-in as shown above. On Fedora 45, the search list and short-name mode in a full /etc/containers/registries.conf are overridden by the vendor drop-in.
Listen failed for HOST TCP port */80: Permission denied
A rootless container asked for a port below 1024. Publish a high port, or lower net.ipv4.ip_unprivileged_port_start. Remove the container left in Created state before you retry.
Containers stop a few seconds after you log out
Lingering is off for the user. Run sudo loginctl enable-linger $USER, and use Quadlet for anything that must survive a reboot.
slirp4netns support has been removed
The container or containers.conf still asks for slirp4netns, which Podman 6 dropped. Run podman system migrate and remove the setting. The full walkthrough, including Quadlet files and the iptables firewall driver error, is in fix Podman after a Fedora upgrade.
Next steps
Podman also powers Toolbx on Fedora. If you want mutable development shells next to the host, read Distrobox and Toolbx on Fedora. For the rest of a new install, the things to do after installing Fedora 45 list covers repos, codecs and updates, and the dnf5 cheatsheet covers package management. Release changes beyond containers are summarised in what is new in Fedora 45. On other distributions, see Podman on Ubuntu 26.04 and Podman and Buildah on Rocky Linux and AlmaLinux.