Podman Pasta Networking
A rootless container on the default network has `eth0` set to 192.168.0.21 - the host's own LAN address - and an empty IPAddress field. It never touches the 10.88.0.0/16 bridge, because rootless has no authority to create one.
Networking Guide 29 of 47 Advanced
- OSUbuntu 26.04 LTS (resolute)
- Podman5.7.0
- Runtimecrun 1.21
- Networknetavark 1.16.1
- TimeAbout 15 min
- Reviewed22 August 2026
Written against the versions above. Podman follows the distribution here rather than a vendor repository, so the version you get is the one Ubuntu shipped. The commands are stable across 5.x.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| PODMAN01 | 192.168.0.21 | Ubuntu 26.04 LTS | Primary Container Host | 2 Core | 4 GB | 50 GB |
Before you start
- guide 3 - the reason for all of this is that you have no privilege over the host's network.
- guide 52 for the observation this guide explains.
-
Three containers, three different addressing schemes
Same host, same engine, same image, and three completely different answers to "what is my IP":
| network | eth0 | |---|---| | default (
podman) |192.168.0.21/24- the host's own address | | user-defined (appnet) |10.89.0.2/24- a real bridge address | |--network slirp4netns|10.0.2.100/24on atap0interface |The first one is the surprising one, and it is the default. A rootless container with no
--networkflag does not get a bridge address - it sees the host's interface configuration, which is whyNetworkSettings.IPAddressis empty. There is no Podman-managed address to report.The 10.88.0.0/16 subnet from guide 50 is defined and, rootless, simply unused.
bash Example session podman run --rm --network host docker.io/library/alpine ip -o addr show eth02: eth0 inet 192.168.0.21/24 brd 192.168.0.255 scope global eth0\ valid_lft forever preferred_lft forever2: eth0 inet6 fe80::215:5dff:fe01:115a/64 scope link \ valid_lft forever preferred_lft foreverpodman run --rm --network slirp4netns docker.io/library/alpine ip -o addr show tap02: tap0 inet 10.0.2.100/24 brd 10.0.2.255 scope global tap0\ valid_lft forever preferred_lft forever2: tap0 inet6 fd00::b0e5:baff:fe9a:6933/64 scope global dynamic flags 100 \ valid_lft 86400sec preferred_lft 14400sec2: tap0 inet6 fe80::b0e5:baff:fe9a:6933/64 scope link \ valid_lft forever preferred_lft foreverExpected resultThe host's address from
--network host, and 10.0.2.100 from slirp4netns.Success conditionYou have seen two of the three schemes side by side.
-
The process doing it
pgrep -a pastashows what is actually implementing the default rootless network:/usr/bin/pasta --config-net --pid /run/user/1000/containers/networks/rootless-netns/rootless-netns-conn.pid --dns-forward 169.254.1.1 -t none -u none -T none -U none --no-map-gw --quiet --netns /run/user/1000/containers/networks/rootless-netns/rootless-netns --map-guest-addr 169.254.1.2pasta - "pack a subtle tap abstraction" - is a userspace network device. It arrived as part of the
passtpackage in guide 1.The reason it exists is the whole rootless story. Creating a bridge, attaching a veth pair to it and writing NAT rules all require privilege over the host's network stack, and an unprivileged user has none. So instead pasta runs as you, copies packets between the container's namespace and a normal socket it opens as your user, and configures the container to look like the host.
Two flags are worth marking.
--netns .../rootless-netnsis a shared namespace - one per user, not one per container, which is why the teardown error in guide 23 talks about killing *the* network process. And--map-guest-addr 169.254.1.2is the address that will turn up in guide 55.bash Example session pgrep -a pasta8421 /usr/bin/pasta --config-net --pid /run/user/1000/containers/networks/rootless-netns/rootless-netns-conn.pid --dns-forward 169.254.1.1 -t none -u none -T none -U none --no-map-gw --quiet --netns /run/user/1000/containers/networks/rootless-netns/rootless-netns --map-guest-addr 169.254.1.2podman inspect alpha --format 'ip={{.NetworkSettings.Networks.appnet.IPAddress}}'ip=10.89.0.2Expected resultOne pasta process holding a shared netns, and a real bridge IP for the container that has one.
Success conditionYou can name the process that gives a rootless container its network.
-
pasta, slirp4netns, and when to override
slirp4netns is the older implementation of the same idea and still available with
--network slirp4netns. It gives the container atap0at 10.0.2.100/24 - a fixed, private address unrelated to your host.Podman 5 defaults to pasta because it is faster and, importantly, preserves the source address of outbound connections. slirp4netns rewrites everything to look like it came from 10.0.2.x, which breaks anything the far end does with the client address.
What to reach for, and why:
- Default (pasta) - almost always right. Outbound works, performance is good.
- A user-defined network - whenever containers must reach *each other* by name or by stable address. This is the answer to most "how do I connect two containers" questions.
--network host- no isolation at all; the container uses your namespace directly. Note it looked identical to the pasta case in step 1, which is a fair summary of how close the default is to no isolation, network-wise.--network none- no interfaces beyond loopback. Good for a build or a batch job that must not reach anything.--network slirp4netns- only for compatibility with something that expects 10.0.2.x.
The mental model that makes rootless networking predictable: you get no bridge unless you ask for one. Ask, by creating a network, and everything behaves the way the documentation assumes.
bash Example session podman run --rm --network none docker.io/library/alpine ip -o addr1: lo inet 127.0.0.1/8 scope host lo\ valid_lft forever preferred_lft forever1: lo inet6 ::1/128 scope host \ valid_lft forever preferred_lft foreverpodman network create --driver bridge --subnet 10.90.0.0/24 --gateway 10.90.0.1 fixedfixedpodman network inspect fixed --format 'subnet={{range .Subnets}}{{.Subnet}} gw={{.Gateway}}{{end}}'subnet=10.90.0.0/24 gw=10.90.0.1podman run --rm --network fixed docker.io/library/alpine ip -o addr show eth02: eth0 inet 10.90.0.2/24 brd 10.90.0.255 scope global eth0\ valid_lft forever preferred_lft forever2: eth0 inet6 fe80::bc24:94ff:fea8:55cb/64 scope link tentative \ valid_lft forever preferred_lft forevertime="2026-08-22T12:03:25Z" level=error msg="Removing container 3d5a52b3359f8991421ae73898d382d4db809d426d2cbce61beb1f4e2fb12b0e: cleaning up container 3d5a52b3359f8991421ae73898d382d4db809d426d2cbce61beb1f4e2fb12b0e: removing container 3d5a52b3359f8991421ae73898d382d4db809d426d2cbce61beb1f4e2fb12b0e network: 1 error occurred:\n\t* rootless netns: kill network process: permission denied\n\n"Expected resultLoopback only from
--network none, and a container on a network with a subnet you chose.Success conditionYou can pick a network mode and say what address the container will get.
Troubleshooting
NetworkSettings.IPAddressis empty and scripts depending on it break.Why: There is no Podman-assigned address on the default rootless network.
Fix:Put the container on a user-defined network and read
.NetworkSettings.Networks.<name>.IPAddress, as step 2 does.Two rootless containers cannot reach each other on the host's IP.
Why: They each see the host's address configuration but are not actually on that LAN, so the address does not route between them.
Fix:A user-defined network, or a pod. Do not use the host's IP as a way for containers to find each other.
Performance is poor for a network-heavy rootless workload.
Why: All traffic is being copied through a userspace process.
Fix:Measure before acting. If it is genuinely the bottleneck, rootful with a real bridge avoids userspace copying entirely - which is a real reason to run rootful, unlike most.
pasta failed with exit code 1when starting a container.Why: Usually a port it cannot bind. See guide 51.
Fix:Read the message - pasta names the port and the reason.