Skip to content

Latest commit

 

History

History
164 lines (120 loc) · 4.36 KB

README.md

File metadata and controls

164 lines (120 loc) · 4.36 KB

Rootful networking with rootless podman containers

As presented at devconf.cz 2023.

This python tool allows attaching network interfaces to initialized, but not running, rootless podman containers. It uses netavark, which is the same tool podman uses to do this. There are some known limitations:

  • podman inspect won't know about the network. From podman's point of view, the container doesn'thave networking.
  • podman run --sdnotify=conmon won't work; systemd receives but rejects the notification with a message similar to [email protected]: Got notification message from PID 7687, but reception only permitted for main PID 3201

If you are using podman >= 4.5, using

podman run \
    --uidmap="0:$(id -u user):1" \
    --uidmap="1:$(grep -Po '(?<=^user:).*$' /etc/subuid | head -1)" \
    --gidmap="0:$(id -g user):1" \
    --gidmap="1:$(grep -Po '(?<=^user:).*$' /etc/subgid | head -1")

also gives you containers without a mapped root UID without external tooling. You may want to use that, as it's a lot simpler.

Dependencies

  • python3
  • python3-podman
  • container-selinux
  • dbus-x11 for dbus-launch, which is called somewhere in the setup by podman or systemd

Running

To see this in action manually, open one shell as root and one as the unprivileged user you want to use to run your container. In the example below, this user is test with a UID of 1000.

Initial setup (run once)

As root:

# Create a secret that will be used to make the IP addresses (which are
# calculated from the container name) unpredictable
touch /etc/rootful_network_secret \
    && chmod 600 /etc/rootful_network_secret \
    && dd if=/dev/urandom of=/etc/rootful_network_secret bs=1 count=32

# lingering is required for the unprivileged user
loginctl enable-linger test

# clone and install required scripts
git clone https://github.com/neverpanic/podman-rootful-network
install -m0755 \
    podman-rootful-network/rootful_network.py \
    /usr/local/sbin/rootful_network

# enable the podman socket for root
systemctl enable --now podman.socket

# create the podman network you want to use; rootless_network.py expects to
# have exclusive control over this network, so do not use it for any other
# containers
podman network create [--ipv6] "$networkname"

As user:

# enable the podman socket for the user
systemctl --user enable --now podman.socket

For each container

As user:

# create the runtime directory that will contain state information
runtimedir="/run/user/$(id -u)/container/$containername"
mkdir -p "$runtimedir"
# create the container, but do not start it
# the --cidfile will be used by rootful_network.py
podman create \
    --cidfile="$runtimedir/ctr-id" \
    --network=none \
    --name "$containername" \
    "$image:$tag"

# initialize the container namespaces, but do not start it
podman container init rootless

As root:

runtimedir="/run/user/1000/container/$containername"

rootful_network \
    "$runtimedir" \
    setup \
    "$name_used_to_generate_ip" \
    /etc/rootful_network_secret \
    "$unprivileged_user" \
    --network "$networkname" \
    [--publish [[ip:][hostPort]:]containerPort[/protocol]] \
    [--network-alias "$alias"]

As user:

podman start "$containername"

Stopping containers

As user:

podman stop "$containername"

As root:

runtimedir="/run/user/1000/container/$containername"

rootful_network \
    "$runtimedir" \
    teardown

As user:

podman rm "$containername"

If you start containers with --rm rootful_network.py won't be able to determine the container ID during teardown and cleanup will fail.

The example systemd service file rootless-example.service shows these commands in a systemd service that can start and stop a container after the initial setup steps.

Credits

Without the help of the following people and their posts and presentations, this would not have been possible:

License

This code is licensed under the BSD-2-Clause license. The SPDX identifier is BSD-2-Clause.