Setting PUID and PGID to root

The unifi tag is just one I picked as example as I have more of an overall question.

A bit of background here, TLDR question at the bottom:
I’m currently trying to run Linuxserver containers rootless in podman. I know this is not officially supported, and I have no question that directly asks for support of this. Through trial and error and reading this forum I found out that the containers first seem to run init scripts as root to set the permissions and other things correctly, and afterwards it runs as the user provided by the PUID and GUID (correct me if I am wrong here).

My approach now is that podman allows me to run the container as a root user inside the container, but outside the container the root ID maps to whatever ID I started the container as (for example, 1000). As Linuxserver first needs to run as root, and then switch to whatever user was provided via the env. vars, I would need 2 users, which both have access to the files that I mount. But with podman I can afaik only map the user I ran the container as consistently.

TL:DR:
My solution would have now have been that I set the PUID/GUID via the env vars to 0 so the container just runs as root user internally all the time. Could this cause any problems for the container, or should it mostly act as usual ?

your assumptions above are correct at a high level of how our stuff works.

we can’t possibly tell you an answer to this as we do not test, use, or support podman in any way, shape, or form. I would say just give it a try and see what happens.

Isn’t this something that would also be possible in a normal docker setup though ? It’s not strictly podman specific (just would be unsecure in docker)

I will probably try it out and report back how it went (if I don’t forget to post here)

we have users who do this successfully, yes. We also get many users who do this and encounter weird issues, we tell them to use a non-root uid/gid, and things will be fixed. Since we dont support using root, it’s not something we’ve ever dug into.

I use podman, there is no need to do any of this. Podman from a container runner perspective is only different in that it is deamonless and runs in userspace. What happens inside the container should be 1:1 with docker unless you are trying to bind mount in root owned filesystems or devices.
Simply run the container as we recommend, our s6 init will run as root and when services are actually executed in the container they will run as the PUID and PGID you pass to the container as env variables. There are very few corner cases where we run anything as root in the container outside of init or need to have root privs to manipulate something like a device or docker socket etc…

1 Like

I can’t say I have made the same experience.
This is the compose I used for docker:

version: "3.7"
services:
  unifi-controller:
    image: docker.io/linuxserver/unifi-controller:version-6.5.55
    container_name: unifi-controller
    environment:
      - PUID=1000
      - PGID=1000
      - MEM_LIMIT=1024M #optional
    volumes:
      - /opt/Unifi:/config
    network_mode: host

Running this compose via podman-compose with the command

podman-compose -f ./docker-compose.yml up -d

results in these kinds of errors

chown: changing ownership of '/config/data/backup/6.0.23.unf': Operation not permitted

(There is more of these, just didn’t wanna fill the entire page with them)
If I exec into the container the mounted files appear as the following permissions:

root@container:/usr/lib/unifi# ls /config -la
total 20
drwxr-xr-x  5 root root 4096 Dec 23 14:07 .
dr-xr-xr-x 21 root root 4096 Dec 23 14:04 ..
drwxr-xr-x  5 root root 4096 Dec 23 14:03 data
drwxr-xr-x  3 root root 4096 Oct  3  2020 logs
drwxr-xr-x  3 root root 4096 Dec 23 14:04 run

On the host these files have the owner of the user I run the container with, which makes sense that they then would be mapped to root:root inside the container.

I’m not sure why this problem occurs, as the container should run as root initially, but changing the PUID/GUID to 0 seems to fix the issue.

Are you by chance running podman with sudo or root in your setup ? Because that would work for podman to access these files and run pretty much just like docker, but I don’t think that counts as rootless.

it’s likely because your path /opt/Unifi was preexisting and already owned by root. We typically suggest letting docker create the bind mount folders which will ensure it has proper permissions from the start.

/opt/Unifi was preexisting, but owned by the user I ran the container with, which isn’t root. In the container it just gets shown as root:root because podman handles it like that.

ahh we’ll have to wait on thelamer to chime in then

I had some permission error too when trying qbittorrent container, however after following tutorial here Media Server Setup with Podman. How to setup Radarr / Sonarr / NZBGet /… | by Pooch | Medium

it works if I add :z to my volume config. ( of course turning selinux off also works)

It looks like UID 911 and GID 911 are used when the environment variables PUID and PGID are not set.

Instead of setting the environment variables PUID and PGID, I believe the options –uidmap and –gidmap could be used instead.

I wrote a troubleshooting tip in the Podman repository of how to map the regular user on the host to a specific user in a container.

Here is an example

#!/bin/bash
set -o errexit
set -o nounset

mkdir -p ~/.config/heimdall

uid=911
gid=911
subuidSize=$(( $(podman info --format "{{ range .Host.IDMappings.UIDMap }}+{{.Size }}{{end }}" ) - 1 ))
subgidSize=$(( $(podman info --format "{{ range .Host.IDMappings.GIDMap }}+{{.Size }}{{end }}" ) - 1 ))

podman run --rm \
  -v ~/.config/heimdall:/config:Z \
  --uidmap $uid:0:1 \
  --uidmap 0:1:$uid \
  --uidmap $(($uid+1)):$(($uid+1)):$(($subuidSize-$uid)) \
  --gidmap $gid:0:1 \
  --gidmap 0:1:$gid \
  --gidmap $(($gid+1)):$(($gid+1)):$(($subgidSize-$gid)) \
  -p 8080:80 \
  -p 8443:443 \
     docker.io/linuxserver/heimdall

I ran the bash script

[test@asus ~]$ bash start.sh 
Trying to pull docker.io/linuxserver/heimdall:latest...
Getting image source signatures
Copying blob 71eb24213f7c done  
Copying blob baa3246ccc69 done  
Copying blob f94355ce9bfd done  
Copying blob ba8d42f2c1bb done  
Copying blob e9e48c4f24ff done  
Copying blob 6beb2e454873 done  
Copying blob e19334d55648 done  
Copying blob 94464ed1d383 done  
Copying blob 214298b99915 done  
Copying blob 93d4dcd25e9f done  
Copying config de6871c1e6 done  
Writing manifest to image destination
Storing signatures
[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] 01-envfile: executing... 
[cont-init.d] 01-envfile: exited 0.
[cont-init.d] 02-tamper-check: executing... 
[cont-init.d] 02-tamper-check: exited 0.
[cont-init.d] 10-adduser: executing... 
usermod: no changes

-------------------------------------
          _         ()
         | |  ___   _    __
         | | / __| | |  /  \
         | | \__ \ | | | () |
         |_| |___/ |_|  \__/


Brought to you by linuxserver.io
-------------------------------------

To support LSIO projects visit:
https://www.linuxserver.io/donate/
-------------------------------------
GID/UID
-------------------------------------

User uid:    911
User gid:    911
-------------------------------------

[cont-init.d] 10-adduser: exited 0.
[cont-init.d] 20-config: executing... 
[cont-init.d] 20-config: exited 0.
[cont-init.d] 30-keygen: executing... 
generating self-signed keys in /config/keys, you can replace these with your own keys if required
Generating a RSA private key
...................................................+++++
......................................+++++
writing new private key to '/config/keys/cert.key'
-----
[cont-init.d] 30-keygen: exited 0.
[cont-init.d] 50-config: executing... 
New container detected, installing Heimdall
Creating app key. This may take a while on slower systems
Application key set successfully.
Setting permissions
[cont-init.d] 50-config: exited 0.
[cont-init.d] 90-custom-folders: executing... 
[cont-init.d] 90-custom-folders: exited 0.
[cont-init.d] 99-custom-files: executing... 
[custom-init] no custom files found exiting...
[cont-init.d] 99-custom-files: exited 0.
[cont-init.d] done.
[services.d] starting services
[services.d] done.
^C[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.


[s6-finish] sending all processes the KILL signal and exiting.

Before typing Ctrl-C , I checked that the web page was available at port 8080.

These files and directories were created:

[test@asus ~]$ ls -l .config/heimdall/
total 0
drwxr-xr-x. 2 1479648 1479648   6 May  8 08:50 custom-cont-init.d
drwxr-xr-x. 2 1479648 1479648   6 May  8 08:50 custom-services.d
drwxr-xr-x. 2 test test  38 May  8 08:50 keys
drwxr-xr-x. 5 test test  46 May  8 08:50 log
drwxrwxr-x. 3 test test  42 May  8 08:50 nginx
drwxr-xr-x. 2 test test  44 May  8 08:50 php
drwxrwxr-x. 6 test test 150 May  8 08:50 www
[test@asus ~]$ 

The container started running as the container UID/GID 0:0 that was mapped to the subuid 1479648 and subgid 1479648 on the host. The container user abc:abc (911:911) was mapped to the regular user on the host (test:test).

In general it is more secure to run a container as a non-root user inside a container, because such a container user has fewer privileges. In other words, it is better to have non-zero values for PUID and GUID.

Even more secure would be not to start the container to run as root inside the container. It would be better to start the container as –user 911:911.

I tried out adding –user 911:911 but it failed because there are chown, usermod and groupmod commands (that require to be run as the container root user):

[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...s6-chown: fatal: unable to chown /var/run/s6/etc/cont-init.d/50-config: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/cont-init.d/30-keygen: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/cont-init.d/20-config: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/cont-init.d/02-tamper-check: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/cont-init.d/01-envfile: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/cont-init.d/10-adduser: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/cont-init.d/50-config: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/cont-init.d/30-keygen: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/cont-init.d/90-custom-folders: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/cont-init.d/99-custom-files: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/cont-init.d/20-config: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/cont-init.d/01-envfile: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/cont-init.d/10-adduser: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/cont-init.d/02-tamper-check: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/cont-init.d/90-custom-folders: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/cont-init.d/99-custom-files: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/services.d/queue/run: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/services.d/cron/run: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/services.d/php-fpm/run: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/services.d/nginx/run: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/services.d/queue/run: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/services.d/php-fpm/run: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/services.d/nginx/run: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/services.d/cron/run: Operation not permitted
exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] 01-envfile: executing... 
foreground: warning: unable to spawn /var/run/s6/etc/cont-init.d/01-envfile: Permission denied
[cont-init.d] 01-envfile: exited 127.
[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.
[s6-finish] sending all processes the KILL signal and exiting.

We do not support this or currently have any plans to. Our containers expect the PUID/PGID envvar (not listed as optional in any readme of ours) to be filled, it will default to 911 if not filled and will likely cause permissions errors. Following the readme is the supported method.

We also do not support rootless for the reasons you’ve already seen. this is not going to change any time soon.

I could add –env PUID=911 and –env PGID=911 to the Bash script so that I don’t rely on the default 911.

In regards to file permission problems, I think rootless Podman will normally
work just fine by adding –uidmap and –gidmap to map PUID and PGID to the UID and GID of the regular user on the host. A bind-mount (with –volume) of a directory owned by the regular user on the host will then be presented as being owned by abc:abc (911:911) inside the container. The user abc could therefore write to the bind-mounted directory.

There are shortcomings of rootless Podman. Some containers, for instance, require privileged Docker/Podman to publish ports with port numbers less than 1024. The port number limitation could be worked around by running

sudo sysctl net.ipv4.ip_unprivileged_port_start=0

There are other reasons why running privileged can be required, for instance,
when –cap-add cap_net_raw is neeeded. Sometimes it will not be possible to run rootless Podman because it has too few privileges.

On other hand, in situations when using rootless Podman works, the container will run with fewer privileges, which I think is a security advantage.

I understand that rootless Podman is currently not supported and there is no support for the UID/GID mapping method I demonstrated.

1 Like

I am only referring to what we support. Everything we make is opensource and you are more than welcome to modify to support your needs. We will not support those modifications though.

that all said, if you would like to modify and keep your changes persistent without forking, take a look at Customizing our Containers | LinuxServer.io this will allow you to persistently modify our containers without forking to achieve the goals you have.

1 Like