How To

Install Podman on Arch Linux and Manjaro (Rootless and Quadlet)

Podman on Arch Linux is one package from the extra repository, and it runs rootless containers as soon as it is installed. You do not start a daemon, join a group or touch a socket, which is the main practical difference from Docker. Two things do not work until you set them up, though: short image names like nginx, and containers that start on their own at boot.

Original content from computingforgeeks.com - post 21512

We installed Podman on Arch Linux, ran rootless containers through the pasta network stack, turned one into a systemd service with Quadlet and rebooted to prove it comes back. Manjaro carries the same package a few patch releases behind. Everything below was tested on Arch with Podman 6.1 in October 2026, and the errors in the troubleshooting section are the ones we actually hit.

Install Podman

The package pulls in everything a rootless setup needs, so there is nothing to pick by hand:

  • crun, the OCI runtime that starts the containers
  • netavark and aardvark-dns for container networks and name resolution
  • passt, which provides the pasta rootless network stack
  • containers-common with the default registry, storage and policy files

Install it:

sudo pacman -S podman

pacman resolved 17 packages, about 137 MiB installed, on a system that already had a desktop library stack:

Packages (17) aardvark-dns-2.1.0-3  abseil-cpp-20260817.0-2  catatonit-0.2.1-2  conmon-1:2.2.1-1  containers-common-1:0.69.2-1  criu-4.2.1-1  crun-1.30.1-1  hwloc-2.15.0-1  libblake3-1.8.7-1  libnet-2:1.3-2  netavark-2.1.0-3  onetbb-2023.1.0-1  passt-2026_10_02.cba3570-1  protobuf-36.1-1  protobuf-c-1.5.2-15  python-protobuf-36.1-1  podman-6.1.4-1
Total Installed Size:  136.61 MiB

pacman stops once to ask which oci-runtime provider you want. Older guides show two choices; in a fresh Arch container we got three, 1) crun 2) krun 3) runc, and pressing Enter takes the default crun, which is what Podman’s own defaults expect. Pick runc only if a tool you use requires it. On Manjaro the command is the same, and its stable branch had podman 6.1.1-1 when we checked, three patch releases behind Arch’s 6.1.4. Podman 6 changed several defaults compared with 5.x, so if you’re upgrading an existing setup, read our Podman 6 breaking changes notes first.

Check what you got before you run anything. podman info reports the pieces that matter for a rootless setup, and a wrong value here explains most rootless failures later:

podman info --format "{{.Host.NetworkBackend}} {{.Host.RootlessNetworkCmd}} {{.Store.GraphDriverName}} {{.Host.CgroupsVersion}} {{.Host.OCIRuntime.Name}} rootless={{.Host.Security.Rootless}}"

You want pasta for rootless networking, the overlay storage driver and cgroups v2. Podman 6 dropped cgroups v1 support entirely, and Arch boots with v2 by default:

netavark pasta overlay v2 crun rootless=true

Check your subordinate UIDs

Rootless Podman maps container users onto a range of UIDs your account owns, listed in /etc/subuid and /etc/subgid. On Arch, useradd creates that range for every new user, because /etc/login.defs sets SUB_UID_COUNT 65536, so most accounts already have one. Confirm yours:

grep -h "^$USER:" /etc/subuid /etc/subgid

Each file should show your name, a start ID and the count:

josphat:100000:65536
josphat:100000:65536

Accounts created some other way can be missing from these files, and Podman does not fail until the first image pull, which makes the cause hard to spot. We removed the entries for a test user and the pull failed with potentially insufficient UIDs or GIDs available in user namespace (requested 0:42 for /etc/shadow). Add a range that doesn’t overlap any other user’s. Take the last entry in /etc/subuid, add its count to its start, and begin the new range there; ours was 100000 plus 65536, so the test user dev2 got 165536 to 231071. Replace dev2 with the affected account:

sudo usermod --add-subuids 165536-231071 --add-subgids 165536-231071 dev2

Then log in as that user and run podman system migrate, which restarts that user’s Podman processes so they pick up the new range:

podman system migrate

After that, the same pull and podman run worked for our test user.

Pull images by their full name

Arch does not configure any search registries, so a short name has nowhere to go. Our first pull failed straight away:

podman pull nginx

Podman refuses to guess a registry:

Error: short-name "nginx" did not resolve to an alias and no containers-registries.conf(5) was found

That is a deliberate choice. There is no /etc/containers/registries.conf, the template containers-common ships in /usr/share/containers/ is all comments, and its 00-shortnames.conf has 132 aliases for common images, but nginx isn’t one of them. Without a search list, a short name can’t be silently pulled from a registry you didn’t expect. The safest habit is the full name, registry and all:

podman pull docker.io/library/nginx:alpine

If you would rather type short names, add Docker Hub as a search registry for your own account. Use a drop-in in registries.conf.d rather than a full ~/.config/containers/registries.conf, because a full user file replaces the system one instead of adding to it, so you’d silently lose any mirror or block an admin adds later:

mkdir -p ~/.config/containers/registries.conf.d
echo 'unqualified-search-registries = ["docker.io"]' > ~/.config/containers/registries.conf.d/10-docker-hub.conf

podman pull busybox worked straight after. Put the same file in /etc/containers/registries.conf.d/ if everyone on the machine should get it. Keep the list short: with one registry Podman pulls from it directly, while with several it asks you to pick one at a terminal and, without one, tries them in order, so an unattended script can end up on a registry you didn’t intend.

Run a rootless container

Start nginx in the background and publish its port 80 on port 8080 of the host:

podman run -d --name web -p 8080:80 docker.io/library/nginx:alpine

The container was up within a second. pasta forwards the port from a process in your own user session, so Podman adds no firewall rules of its own:

podman ps

The PORTS column shows the mapping:

CONTAINER ID  IMAGE                           COMMAND               CREATED        STATUS        PORTS                 NAMES
9bf5ad562cdb  docker.io/library/nginx:alpine  nginx -g daemon o...  2 seconds ago  Up 1 second   0.0.0.0:8080->80/tcp  web

curl -sI http://localhost:8080 returned HTTP/1.1 200 OK from nginx. To see what rootless means in practice, compare the users inside the container with the ones the host sees:

podman top web user huser pid hpid

Root in the container is your own UID 1000 on the host, and the nginx worker runs as 100100, an ID from your subordinate range:

USER        HUSER       PID         HPID
root        1000        1           6572
nginx       100100      25          6597
nginx       100100      26          6598

So even if something breaks out of the container, it lands as an unprivileged user on the host, not as root. podman unshare cat /proc/self/uid_map prints the mapping itself: container UID 0 to 1000, then 1 onward to 100000 onward.

Ports below 1024 are the one place rootless gets in your way. Publishing port 80 failed with a pasta error, because the kernel only lets privileged processes bind those ports:

Error: pasta failed with exit code 1:
Listen failed for HOST TCP port */80: Permission denied
Couldn't listen on requested ports

Publish a high port and put a reverse proxy in front, or lower the kernel’s limit if this machine only runs your containers. The sysctl applies to every user, so any local account can then bind port 80, which is why it belongs on a single-purpose server rather than a shared one:

echo 'net.ipv4.ip_unprivileged_port_start=80' | sudo tee /etc/sysctl.d/90-unprivileged-ports.conf
sudo sysctl --system

With the limit at 80, the same podman run -p 80:80 worked and answered on http://localhost/. To undo it, delete the file and run sudo sysctl -w net.ipv4.ip_unprivileged_port_start=1024.

Run a container as a service with Quadlet

podman generate systemd is deprecated, and Quadlet is its replacement: you describe the container in a small unit file and systemd’s generator turns it into a service. Rootless Quadlet files live in your home directory:

mkdir -p ~/.config/containers/systemd
vim ~/.config/containers/systemd/web.container

Add this unit. The [Container] section takes the same settings as podman run, under their own names:

[Unit]
Description=nginx in a rootless Podman container

[Container]
Image=docker.io/library/nginx:alpine
ContainerName=web-quadlet
PublishPort=8081:80
AutoUpdate=registry

[Service]
Restart=on-failure

[Install]
WantedBy=default.target

The file name decides the service name, so web.container becomes web.service. Before you load it, the generator can show you what it would produce. If the generator rejects the file, systemctl only reports that the unit does not exist, so the dry run is the quickest way to see what went wrong:

/usr/lib/systemd/user-generators/podman-user-generator --dryrun

The output ends with the podman run command systemd will execute:

ExecStart=/usr/bin/podman run --name web-quadlet --replace --rm --cgroups=split --sdnotify=conmon -d --label io.containers.autoupdate=registry --publish 8081:80 docker.io/library/nginx:alpine

Reload systemd and start the service:

systemctl --user daemon-reload
systemctl --user start web.service

curl -sI http://localhost:8081 returned HTTP/1.1 200 OK, so the service is serving. Do not run systemctl --user enable web.service. We tried, and systemd refused with Unit /run/user/1000/systemd/generator/web.service is transient or generated. The [Install] section in the .container file already wires the service into default.target, which is all enable would do. What you do need is lingering, so your user’s systemd starts at boot even when nobody logs in:

sudo loginctl enable-linger $USER

We rebooted the VM to check. Without anyone logging in, web.service was active and the container was running:

Rootless Podman with pasta networking running an nginx Quadlet service on Arch Linux

The capture shows the Quadlet container running under the same UID mapping as before and answering on port 8081. AutoUpdate=registry labels the container for podman auto-update, which pulls a newer image and restarts the service when the registry has one. podman auto-update --dry-run lists what it would update without touching anything:

podman auto-update --dry-run

Our container was current, so UPDATED reads false:

            UNIT         CONTAINER                   IMAGE                           POLICY      UPDATED
            web.service  521826adb95c (web-quadlet)  docker.io/library/nginx:alpine  registry    false

Enable podman-auto-update.timer with systemctl --user enable --now if you want that to run on a schedule. Our Quadlet guide for Fedora covers pods, volumes and networks as Quadlet files, and every one of those works the same on Arch.

Fix common Podman errors

These three came up while we tested, and each has a short fix:

ErrorCauseFix
no systemd user session availableYou switched users with sudo -iu or suLog in as that user, or use sudo machinectl shell dev2@
potentially insufficient UIDs or GIDsThe account has no /etc/subuid rangeusermod --add-subuids, then podman system migrate
Listen failed for HOST TCP port */80Rootless containers can’t bind ports below 1024Use a high port or lower ip_unprivileged_port_start

The first one needs the most explanation.

“cgroupv2 manager is set to systemd but there is no systemd user session”

This appears when you switch to another user with sudo -iu or su and run Podman there. Our test user got a block of these warnings before every command, followed by Falling back to --cgroup-manager=cgroupfs:

level=warning msg="The cgroupv2 manager is set to systemd but there is no systemd user session available"
level=warning msg="For using systemd, you may need to log in using a user session"

sudo and su do not create a login session, so there is no user systemd for Podman to talk to. The container still runs on the cgroupfs fallback, but Quadlet and --user services will not, because they need that systemd instance. Podman’s own warning suggests loginctl enable-linger, which starts that user’s systemd at boot, but you still need a real session to talk to it. Log in as that user over SSH or at the console, or open one with sudo machinectl shell dev2@; under machinectl, podman info reported the systemd cgroup manager instead of the cgroupfs fallback.

The other two have their full fixes in the subordinate UID and rootless container sections above.

If you need Docker’s CLI or compose files, podman-compose and podman-docker are both in Arch’s repositories, and our Podman Compose guide walks through them. When a project insists on the real Docker daemon, our Docker CE on Manjaro guide covers that side, and the Podman on Ubuntu 26.04 guide shows the same rootless setup on a Debian-family system. The podman-desktop GUI is in extra too, so sudo pacman -S podman-desktop installs it without an AUR helper. For tools that only exist in the AUR, our yay guide sets one up.

Keep reading

Install KVM and Virt-Manager on Arch Linux Virtualization Install KVM and Virt-Manager on Arch Linux Things to Do After Installing CachyOS Arch Linux Things to Do After Installing CachyOS How to Install CachyOS: Step-by-Step Guide Arch Linux How to Install CachyOS: Step-by-Step Guide CapRover Docker Install on Debian 13: Deploy Your First App Containers CapRover Docker Install on Debian 13: Deploy Your First App Best OpenShift Books for Admins and EX280 Candidates Books Best OpenShift Books for Admins and EX280 Candidates Radar: Open Source Kubernetes UI With Topology and MCP Containers Radar: Open Source Kubernetes UI With Topology and MCP

Leave a Comment

Press ESC to close