Getting Started With Rootless Container Using Podman

Are you deploying software using containers? Are you using Podman? Do you want to up your security game by running containers with as little privilege as possible? Boy, do I have an article for you!

What is Podman?

Podman is a Red Hat product aimed as a replacement for Docker. For 99% of tasks, it is indeed a true Docker replacement. A few of its features are support for root-less containers, uses the fork/exec model to start containers, is daemon-less, and more.

The advantages of a rootless container are obvious. If it can be prevented from running as root, you run it without root privileges.

via GIPHY

With this article, I hope to help remove some hurdles that may crop up when you use Podman to deploy rootless containers.

Podman in rootless execution

If you are a seasoned IT professional, you might have committed either one of the following crimes:

  • Running the docker command using sudo, escalating its privileges
  • Adding your user non-root user to the docker group. big oof

As you might have realized by now, this is a terrible security practice. You are giving the Docker daemon root access to your machine. That exposes two methods of exploitation:

  • The Docker daemon (dockerd) runs as root. If dockerd has a security vulnerability, your entire system is compromised because dockerd is a process owned by the root user.
  • An image that you use might have vulnerabilities. What if the vulnerable imgae is used by a container that is running as a process of the root user? An attacker can use the vulnerable image to gain access to your entire system.

The solution is simple, don't run everything as root, even if you trust it. Remember, nothing is 100% secure. I present to you Podman's ability to manage containers without root access.

If you start a container using Podman as a non-root user, said container does not gain any additional privileges, nor will Podman ask you for a sudo password.

Below are the benefits Podman provides when you use it for root-less containers (without any super-user privileges):

  • You can isolate a group of common containers per local user. (e.g., run Nextcloud and MariaDB under user nextcloud_user and containers Gitea and PostgreSQL under the user gitea_user)
  • Even if a container/Podman gets compromised, it can not get complete control over the host system, since the user executing the container is not root. But yes, the user under which the exploited container is running might as well be considered as user gone rogue.
Customer Referral Landing Page - $100
Cut Your Cloud Bills in Half Deploy more with Linux virtual machines, global infrastructure, and simple pricing. No surprise bills, no lock-in, and the
Get started on Linode with a $100, 60-day credit for new users.

Limits of root-less Podman

When you use root-full Podman/Docker, you are giving Podman/Docker super-user level privileges. That is certainly very bad, but it also means that all of the advertised functionalities work as intended.

Instead, when you run Podman containers without root privileges, it has some limits. Some of the major ones are as follows:

  • Container images can not be shared across users. If user0 pulls the 'nginx:stable-alpine' image, user1 will have to separately pull the 'nginx:stable-alpine' image for themselves. There is no way [at least not yet] that allows you to share images between users. But, you can copy images from one user to another user, refer to this guide by Red Hat.
  • Ports less than 1024 cannot be binded out of the box. A workaround exists.
  • A root-less container may not be able to ping any hosts. A workaround exists.
  • If you specify a UID in root-less Podman container, any UID that is not mapped to a pre-existing container may fail. Best to execute Podman from an existing user shell. Or better yet, create a systemd service to auto-start it.
podman/rootless.md at main · containers/podman
Podman: A tool for managing OCI containers and pods. - podman/rootless.md at main · containers/podman

Getting started with root-less Podman

Before you get started with the rootless execution of containers, there are a few prerequisites that need to be met.

Make sure you have slirp4netns installed

The slirp4netns package is used to provide user-mode networking for unprivileged network namespaces. This is a necessary if you want your root-less container to interact with any kind of network.

You can install the slirp4netns package on Debian/Ubuntu based Linux distributions using the apt package manager like so:

sudo apt install slirp4netns

On Fedora/RHEL based Linux distributions, use the dnf package manager to install slirp4netns like so:

sudo dnf install slirp4netns

You Arch Linux users know how to do it with pacman, but regardless, below is the command you might be looking for:

sudo pacman -Sy slirp4netns

Make sure that your subuid and subgid are properly configured

Since root-less Podman containers are run by an existing user on the system, said non-root users need permission to run a root-less container as a UID that is not their own UID. This also applies to the GID.

Each user is given a range of UIDs that it is allowed to use. This is specified in the /etc/subuid file; and the /etc/subgid file is for the GIDs a user is allowed to use.

The format of this file is as following:

username:initial UID/GID allocated to user:range/size of allowd UIDs/GIDs

So, let us say my user, pratham wants 100 UIDs for himself and krishna wants 1000 UIDs for himself. Below is how the /etc/subuid file would look like:

pratham:100000:100
krishna:100100:1000

What this effectively means is that the user pratham can use UIDs between '100000' and '100100'. Meanwhile, user krishna can use UIDs between '100100' and '101100'.

Usually, this is already set up for each user you create. And usually, this range is set to '65536' usable GIDs/UIDs. But in some cases, this needs to be done manually.

But hold on, if this is not already done for your user, you do not need to do this by hand for each user. You can use the usermod command for this. Below is the command syntax to do so:

sudo usermod --add-subuids START-RANGE --add-subgids START-RANGE USERNAME 

Replace the strings START, RANGE and USERNAME according to your needs.

⚠️
Make sure that the permissions for files /etc/subuid and /etc/subgid are set to 644 and is owned by root:root.

Want to bind Ports less than 1024?

If you are using a reverse proxy for SSL, you will know that ports 80 and 443 need to be accessible by a certificate provider like Let's Encrypt.

If you try to bind ports lower than 1024 to a root-less container managed by Podman, you will notice that it is not possible. Well, it is possible, but that is not configured out of the box.

A non-root user is not allowed to bind anything on ports less than port 1024.

So, how do I bind ports lower than 1024 in root-less Podman? To do that, first determine the lowest port that you need. In my case, to deploy SSL, I need ports 80 and 443. So the lowest port that I need is port 80.

Once that is determined, add the following line to the /etc/sysctl.conf file:

net.ipv4.ip_unprivileged_port_start=YOUR_PORT_NUMBER

Essentially, you are changing the value of net.ipv4.ip_unprivileged_port_start to the lowest port you need. If I substitute YOUR_PORT_NUMBER with 80, I can bind port 80 with Podman in a root-less container.

WHERE ARE MY IMAGES?

No need to scream at me buddy. I was going to tell you, eventually...

As I pointed out earlier, a limitation of Podman is that it can not share images between users. They either need to be pulled for each user or be copied from one user to another user. Both of these take up 2x/3x/4x space (depending on how many duplicates exist).

The image for any user is stored in their home directory. Specifically, they are stored inside the ~/.local/share/containers/storage/ directory.

Give it a try!

Once all the prerequisites are satisfied, you can run the podman run command from a non-user's shell and start a container.

Since I use Caddy Server for my SSL, I will use that in this tutorial. To run Caddy Server as a root-less container using Podman, while binding it ports lower than 1024, I will simply run the following command:

$ whoami
pratham

$ podman run -d --name=prathams-caddy -p 80:80 -p 443:443 caddy:alpine
e6ed67eb90e6d0f3475d78b287af941bc873f6d62db60d5c13b1106af80dc5ff

$ podman ps
CONTAINER ID  IMAGE                           COMMAND               CREATED        STATUS            PORTS                                     NAMES
e6ed67eb90e6  docker.io/library/caddy:alpine  caddy run --confi...  2 seconds ago  Up 2 seconds ago  0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp  prathams-caddy

$ ps aux | grep caddy
pratham     3022  0.0  0.0  85672  2140 ?        Ssl  06:53   0:00 /usr/bin/conmon --api-version 1 -c e6ed67eb90e6d0f3475d78b287af941bc873f6d62db60d5c13b1106af80dc5ff [...]
pratham     3025  0.1  0.3 753060 32320 ?        Ssl  06:53   0:00 caddy run --config /etc/caddy/Caddyfile --adapter caddyfile

As you can see, the user pratham is not root and also that I did not use the sudo command to escalate privileges of the user pratham. I was able to run the Caddy Server container with root-less privileges using Podman.

The output of ps command shows that the PID 3022 is of a process owned by the pratham user. This process is the Caddy Server container (I have trimmed the output). The PID 3025 is a child process of PID 3022 which is also under the pratham user.

Did I not address your issue?

I apologize if I did not cover your issue with root-less Podman containers. Since Podman is new (in software years), it will have some unexpected issues.

Fret not. I have included the official troubleshooting guide below. Refer to that when in doubt. It is also the one that will be updated frequently.

podman/troubleshooting.md at main · containers/podman
Podman: A tool for managing OCI containers and pods. - podman/troubleshooting.md at main · containers/podman

Conclusion

In this article, I demonstrate how you can start managing rootless containers using Podman. I talk about the necessary software that enables this functionality. I go over common issues you may face with root-less Podman containers and how to mitigate them.

I hope it helps you and if you need more details, check the official documentation where you might get a more technical troubleshooting guide.