What rootless Podman is and how it differs from Docker
Podman runs containers as an ordinary user, without root privileges. It also does not keep a permanent root daemon: containers start as child processes of the user. Docker has a rootless mode, but it is a separate dockerd daemon running as the user inside a user namespace.
Podman also relies on subuid and subgid, and only root can add lines to those files. The project code lives in the repository podman-container-tools/podman; the old address containers/podman answers with a redirect.
When it makes sense and when it does not
Rootless makes sense when a service must not get root on the host even if its container is compromised: a web application, a bot, a background worker. It does not make sense if you need privileged ports without workaround settings, original client IPs in logs without extra work, or complex compose files that cannot be tested in advance.
If Docker already runs on the server, moving is not mandatory. The basic Docker setup on a server is covered in the article on setting up Docker on a VDS, and the general picture of images and containers in the piece on the Docker image and container.
Versions and what changed in them
As of 9 November 2026 the current stable Podman is 6.1.4 from 12 October 2026; the 5.8.9 branch is supported alongside it. Below are four milestones for a rootless setup, from the project release notes.
| Version | Date | What changed |
|---|---|---|
| 4.4.0 | 1 February 2023 | Quadlet appeared: a systemd unit generator |
| 5.0.0 | 19 March 2024 | pasta replaced slirp4netns as the default for rootless networking |
| 6.0.0 | 24 June 2026 | slirp4netns, CNI and cgroups v1 were removed |
| 6.1.4 | 12 October 2026 | The current stable version |
Which version your distribution ships
The version in the package repository is almost always older than the current one, and that decides whether you have Quadlet. It appeared in 4.4, so Ubuntu 22.04 and Debian 12 do not have it, while Ubuntu 24.04 and Debian 13 do. The package versions as of 9 November 2026 come from the Debian and Ubuntu catalogs.
| Distribution | Podman version | Quadlet |
|---|---|---|
| Ubuntu 22.04 | 3.4.4 | No |
| Ubuntu 24.04 | 4.9.3 | Yes |
| Debian 12 | 4.3.1 | No |
| Debian 13 | 5.4.2 | Yes |
Package versions go stale quickly, so check yours with podman --version.
Installation and first run
Installation takes one command from the distribution repository, and the container starts as an ordinary user. For that, the subuid and subgid files must contain a line with your name; usually the system administrator creates it when adding the user.
sudo apt install podman
grep "$USER" /etc/subuid /etc/subgid
podman run --rm -d --name web -p 8080:80 docker.io/library/nginx:stable
podman ps
curl -sI http://127.0.0.1:8080/If grep printed nothing, ask the administrator to add the ranges: without them a rootless container will not start.
Limits of rootless mode
The main price of rootless is networking. Ports below 1024 are unavailable by default, and when ports are published through rootlessport the service loses the original client IP. These are not bugs but a consequence of the process having no rights to configure the host network.
- Privileged ports: the project documentation says Podman cannot bind a container to ports below 1024.
- Original IP: rootless bridge networks use rootlessport by default, which loses the client address. The
rootless_port_forwarder="pasta"mode preserves it, but in 6.0.0 it is marked experimental.
The workaround for ports is to lower the threshold for unprivileged processes with sysctl net.ipv4.ip_unprivileged_port_start=443 (the value from the project documentation); to make it survive a reboot, write it to a file in /etc/sysctl.d/. Remember: the setting applies to all users of the host, not only to Podman.
An alternative that leaves the kernel alone is to keep the container on a high port and put a reverse proxy on 80 and 443. For how Docker interacts with the firewall, read the article on the Docker and UFW firewall bypass; for Podman, test the behavior on your own test setup.
Quadlet: a container as a systemd service
Quadlet turns .container, .pod, .network and .volume files into systemd units, so the container restarts, writes logs to the journal and starts at boot. For rootless, files go into the ~/.config/containers/systemd/ directory.
- Create the file
~/.config/containers/systemd/web.containerwith the content below. - Run
systemctl --user daemon-reloadso systemd picks up the file. - Start the service and check its state.
- Let the user keep running without logging in:
loginctl enable-linger.
[Unit]
Description=Web container
[Container]
Image=docker.io/library/nginx:stable
PublishPort=8080:80
[Install]
WantedBy=default.targetCompatibility with Docker commands and compose files
The podman commands mirror the docker commands, but compatibility is incomplete. podman compose is a thin wrapper over an external provider, that is docker-compose or podman-compose; if both are installed, docker-compose is used.
The socket with a Docker-compatible API is enabled with one command, and Docker clients are pointed to its address through the DOCKER_HOST variable. The Podman documentation describes this as a compatibility layer with the Docker API version 1.40; since version 6.1.0 it is being brought up to version 1.44.
systemctl --user enable --now podman.socket
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock
docker psFrequently asked questions
Can I simply replace docker with podman in my scripts?
Often yes, but you need to test each script. The basic commands match, while networking, privileged ports and some compose fields behave differently.
Why do my old guides with slirp4netns not work?
In Podman 5.0.0 pasta became the default, and in 6.0.0 support for slirp4netns was removed. On version 6 and later use pasta.
What should ZevsHost customers do?
Podman is installed on a VPS or a dedicated server with root access; on shared hosting the panel takes care of the server side. Installation, subuid and subgid, ports and systemd services are configured by you.