containers / podman-compose

a script to run docker-compose.yml using podman
GNU General Public License v2.0
5.08k stars 484 forks source link

Same USER as the host that can read/write to ~/. #395

Open dngray opened 2 years ago

dngray commented 2 years ago

So I am trying to build a container that has chezmoi and Vault in it. I need my $USER to be the same and $HOSTNAME in the container and have read/write access to my home directory. Chezmoi reads templates that specify both the hostname and user for template logic.

I started with: Running Docker Containers as Current Host User, but found that if I had the UID 1000:1000 in the container this wasn't mapped in my container. Perhaps I need to set this to a different UID? My subuid/subgid is:

/etc/subuid:

daniel:100000:65536

/etc/subgid:

daniel:100000:65536

I then found User IDs and (rootless) containers with Podman, but it seems that --user has to be set with podman run. Should you use the --user flag in rootless containers?, mentioned --userns=keep-id but I'd like to keep it in my compose file if possible. Apparently that can't be specified https://github.com/containers/podman-compose/issues/166, one solution there mentions specifying this in .bashrc/.zshrc, but I'd really rather use a local .env file in my docker-compose directory.

I'm not really sure if those features are what I need to solve this, so any advice would be welcome. This is what I have so far:

.env:

COMPOSE_PROJECT_NAME=chezmoi
COMPOSE_HTTP_TIMEOUT=300
COMPOSE_FILE=chezmoi-compose.yml
USER_ID=0
GROUP_ID=0
PODMAN_USERNS=keep-id

chezmoi-compose.yml:

services:
  chezmoi:
    container_name: chezmoi
    hostname: ${HOSTNAME}
    build:
      context: .
      dockerfile: ./chezmoi/Dockerfile
    security_opt:
      label: disable
    args:
        USER_ID: ${USER_ID:-0}
        GROUP_ID: ${GROUP_ID:-0}
        USER: ${USER:-0}
    volumes:
      - ${HOME}:/home/${USER}

chezmoi/Dockerfile:

FROM fedora

ARG USER_ID
ARG GROUP_ID
ARG USER

RUN latestChezmoi=$(curl -s https://api.github.com/repos/twpayne/chezmoi/releases/latest | grep -P '^(?=.*browser_download_url.*rpm)(?=.*x86_64)' | cut -d '"' -f 4) && dnf -y install $latestChezmoi

RUN dnf install -y dnf-plugins-core; dnf config-manager --add-repo https://rpm.releases.hashicorp.com/fedora/hashicorp.repo; dnf -y install vault

RUN if [ ${USER_ID:-0} -ne 0 ] && [ ${GROUP_ID:-0} -ne 0 ]; then \
    groupadd -g ${GROUP_ID} ${USER} &&\
    useradd -l -u ${USER_ID} -g ${USER} ${USER} &&\
    install -Z -d -m 0755 -o ${USER} -g ${USER} /home/${USER} ;fi

USER $USER
WORKDIR $USER
ENTRYPOINT ["tail", "-f", "/dev/null"]

I compiled this with (Incidentally I ran into https://github.com/containers/podman-compose/issues/371) :smile:

podman-compose -f chezmoi-compose.yml up

I used this to get a shell:

podman container exec -it chezmoi bash

Output:

$ podman-compose version
['podman', '--version', '']
using podman version: 3.4.4
podman-composer version  0.1.8
podman --version
podman version 3.4.4
exit code: 0

Environment: Fedora Silverblue 35

podman version
Version:      3.4.4
API Version:  3.4.4
Go Version:   go1.16.8
Built:        Thu Dec  9 08:15:07 2021
OS/Arch:      linux/amd64

Additional context

Also something else would be nice if there was a support label. I think this would be useful as some people have asked questions and they weren't really bugs or new features.

muayyad-alsadi commented 2 years ago

Please consider upgrading to 1.x using pip, you can do that rootless.

pip3 install --upgrade --user podman-compose

So basically you want a good way to pass keep-id. You can use --podman-run-args="--keep-id"

I'll see what other options we have

dngray commented 2 years ago

Please consider upgrading to 1.x using pip, you can do that rootless.

Good point, No need to overlay that with rpm-ostree is there heh.

So basically you want a good way to pass keep-id.

I think so, yes.

The main thing I can't seem to figure out is how to map my home directory as a non-root user inside the container.

For example if I use:

podman run  --userns=keep-id --volume=$HOME:/home/$USER localhost/chezmoi-docker_chezmoi

and execute the container:

podman container exec -it funny_ramanujan bash

My ID/name is correct:

uid=1000(daniel) gid=1000(daniel) groups=1000(daniel)

It's mounted as:

/dev/mapper/luks-uuid on /home/daniel type btrfs (rw,relatime,seclabel,compress=zstd:1,ssd,space_cache,subvolid=256,subvol=/home)

Permissions look okay:

ls -la /home/
drwx------. 1 daniel daniel 458 Dec 31 10:55 daniel

But I cannot access the contents:

bash-5.1$ ls -la /home/daniel/
ls: cannot open directory '/home/daniel/': Permission denied

Ideally a solution will be I can use podman-compose without having to remember all the parameters (because I'm terrible at that).

dngray commented 2 years ago

Using podman run becomes particularly impractical for my Mutt container because of all the paths.

That Redhat article also says:

As long as your container does not need root, I always recommend using the --user option to improve security further.

So it would definitely be nice to be able to do this with podman-compose.

.env:

COMPOSE_PROJECT_NAME=mail
COMPOSE_HTTP_TIMEOUT=300
COMPOSE_FILE=mail-compose.yml
USER_ID=0
GROUP_ID=0
PODMAN_USERNS=keep-id

mail-compose.yml

services:
  mail:
    container_name: mail
    hostname: ${HOSTNAME}
    build:
      context: .
      dockerfile: ./mail/Dockerfile
    security_opt:
      label: disable
    args:
        USER_ID: ${USER_ID:-0}
        GROUP_ID: ${GROUP_ID:-0}
        USER: ${USER:-0}
    volumes:
      - ${HOME}/.config/khard:/home/${USER}/.config/khard:ro
      - ${HOME}/.config/mailcap:/home/${USER}/.config/mailcap:ro
      - ${HOME}/.config/msmtp:/home/${USER}/.config/msmtp:ro
      - ${HOME}/.config/mutt:/home/${USER}/.config/mutt:ro
      - ${HOME}/.config/notmuch:/home/${USER}/.config/notmuch:ro
      - ${HOME}/.config/nvim:/home/${USER}/.config/nvim:ro
      - ${HOME}/.config/vdirsyncer:/home/${USER}/.config/vdirsyncer:ro
      - ${HOME}/.local/khard:/home/${USER}/.local/khard:ro
      - ${HOME}/.local/share/mail:/home/${USER}/.local/share/mail
      - ${HOME}/.local/share/nvim:/home/${USER}/.local/share/nvim
      - ${HOME}/.local/vdirsyncer:/home/${USER}/.local/vdirsyncer:ro
      - ${HOME}/Desktop:/home/${USER}/Desktop:ro
      - ${HOME}/Downloads:/home/${USER}/Downloads

mail/Dockerfile:

FROM fedora

ARG USER_ID
ARG GROUP_ID
ARG USER

RUN dnf install -y dnf-plugins-core; dnf copr enable -y flatcap/neomutt; dnf install -y isync khard neovim lynx msmtp notmuch pandoc vdirsyncer neomutt;

RUN if [ ${USER_ID:-0} -ne 0 ] && [ ${GROUP_ID:-0} -ne 0 ]; then \
    groupadd -g ${GROUP_ID} ${USER} &&\
    useradd -l -u ${USER_ID} -g ${USER} ${USER} &&\
    install -Z -d -m 0755 -o ${USER} -g ${USER} /home/${USER} ;fi

USER $USER
WORKDIR $USER
ENTRYPOINT ["tail", "-f", "/dev/null"]

If the args: thing is the wrong way to do this let me know. I'm still new to podman, and docker in general so I don't really know what I am doing.

muayyad-alsadi commented 2 years ago

@dngray please test latest devel branch

It now passes PODMAN_* from .env to podman

Most likely you don't need to set USER: ${USER:-0}

muayyad-alsadi commented 2 years ago

Permissions look okay:

Consider 711

chmod 711 /home/daniel
muayyad-alsadi commented 2 years ago

@dngray I've tested 700 and it worked too

my .env

PODMAN_USERNS=keep-id

my compose

version: '3'
services:
  web:
    image: busybox
    command: httpd -f -p 8123 -h /etc/
    network_mode: host
    volumes:
    - /home/alsadi:/mnt

my home is 700

$ podman-compose up -d
$ podman-compose exec web /bin/sh
$ ls /mnt/ # which is the path I mounted my home
$ md5sum /mnt/anyfile.txt
dngray commented 2 years ago

Installed via?

pip3 install https://github.com/containers/podman-compose/archive/devel.tar.gz --user
['podman', '--version', '']
using podman version: 3.4.4
podman-composer version 1.0.3
podman --version
podman version 3.4.4

.env:

PODMAN_USERNS=keep-id

compose.yml:

version: '3'
services:
  web:
    image: busybox
    command: httpd -f -p 8123 -h /etc/
    network_mode: host
    volumes:
      - /var/home/dngray:/mnt

I checked /mnt and it indeed has the permissions 0700/drwx------, however when trying to ls in that directory:

ls: can't open '/mnt': Permission denied
muayyad-alsadi commented 2 years ago

Installed via?

Yes correct. This is the way.

Try

podman-compose exec web whoami
podman-compose exec web id

Could this be selinux issue? Or silverblue / ostree related?

dngray commented 2 years ago

Looks as I'd expect.

dngray@icefloe ~/m/f/test> podman-compose exec web whoami
['podman', '--version', '']
using podman version: 3.4.4
{'default'} {'default'}
podman exec --interactive --tty test_web_1 whoami
dngray
exit code: 0
dngray@icefloe ~/m/f/test> podman-compose exec web id
['podman', '--version', '']
using podman version: 3.4.4
{'default'} {'default'}
podman exec --interactive --tty test_web_1 id
uid=1000(dngray) gid=1000(dngray)
exit code: 0
muayyad-alsadi commented 2 years ago

what can we do form our side (as far as compose is concerned)?

could it be SELinux?

muayyad-alsadi commented 2 years ago

any update?

dngray commented 2 years ago

I will try soon.

dngray commented 1 year ago

Sorry I didn't get back to this earlier. I tried this on Archlinux with:

❯ podman-compose --version
podman-compose version: 1.0.4
['podman', '--version', '']
using podman version: 4.4.4
podman-compose version 1.0.4
podman --version 
podman version 4.4.4
exit code: 0

And it seems things worked, using the devel release.

Trying with setup:

.env

COMPOSE_PROJECT_NAME=busybox
COMPOSE_HTTP_TIMEOUT=300
COMPOSE_FILE=compose.yml
PODMAN_USERNS=keep-id

compose.yml

version: '3'
services:
  test:
    image: busybox
    command: httpd -f -p 8123 -h /etc/
    network_mode: host
    volumes:
      - /var/home/dngray/test:/mnt:Z,U

I got this error:

❯ podman-compose up
podman-compose version: 1.0.4
['podman', '--version', '']
using podman version: 4.4.2
** excluding:  set()
['podman', 'ps', '--filter', 'label=io.podman.compose.project=busybox', '-a', '--format', '{{ index .Labels "io.podman.compose.config-hash"}}']
podman pod create --name=pod_busybox --infra=false --share=
93ee0bbc9f1e8089f1421583c611ccb336fcd50bb296b43dbbde4cec64c561fb
exit code: 0
podman create --name=busybox_test_1 --pod=pod_busybox --label io.podman.compose.config-hash=987c64baba58bc3d6974040d14bba13f20d81ee6a5d0aacadc39d0a87bac3671 --label io.podman.compose.project=busybox --label io.podman.compose.version=1.0.4 --label PODMAN_SYSTEMD_UNIT=podman-compose@busybox.service --label com.docker.compose.project=busybox --label com.docker.compose.project.working_dir=/var/home/dngray/busybox --label com.docker.compose.project.config_files=compose.yml --label com.docker.compose.container-number=1 --label com.docker.compose.service=test -v /var/home/dngray:/mnt --network host busybox httpd -f -p 8123 -h /etc/
Resolved "busybox" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull docker.io/library/busybox:latest...
Getting image source signatures
Copying blob 4b35f584bb4f done  
Copying config 7cfbbec896 done  
Writing manifest to image destination
Storing signatures
5fce11651a4c919bec26c8db7f38b9dee64fdd2b1447cc7b1efff9092396197c
exit code: 0
podman start -a busybox_test_1
httpd: error while loading shared libraries: /lib/libc.so.6: cannot apply additional memory protection after relocation: Permission denied
exit code: 127

If I remove the adding :Z:U to the mount point didn't help. It seems to be something about Silverblue, currently using F38.

francoism90 commented 1 year ago

@dngray Do you have any update/solution? I'm facing the same problem and also running Silverblue.

@muayyad-alsadi Could you push a new release of podman-compose? I'm using the RPM repo on FS 37.

dngray commented 1 year ago

@dngray Do you have any update/solution? I'm facing the same problem and also running Silverblue.

No I didn't. I was using the latest devel version and pip.

francoism90 commented 1 year ago

@dngray It seems this is a SELinux issue:

$ sudo setenforce permissive

I'm able to access the files now using Z,U as mount options.

Could you test? Hmm, weird why SELinux is blocking this, @muayyad-alsadi do you have any idea why?

francoism90 commented 1 year ago

Hmm, it seems to use the wrong user id 100999 instead of 1000.

francoism90 commented 1 year ago

So this works: PODMAN_USERNS=keep-id:uid=1000,gid=1000 podman-compose up

However I still need to disable SELinux for this to work:

time->Sun Apr 16 12:41:35 2023
type=AVC msg=audit(1681641695.065:959): avc:  denied  { open } for  pid=30365 comm="cat" path="/src/foo.txt" dev="dm-0" ino=9832898 scontext=system_u:system_r:container_t:s0:c32,c472 tcontext=unconfined_u:object_r:user_home_t:s0 tclass=file permissive=1
muayyad-alsadi commented 1 year ago

Does audit2allow tool have any suggestion?

francoism90 commented 1 year ago

@muayyad-alsadi Thanks, I'll take a look.

I've created a bug report: https://github.com/fedora-silverblue/issue-tracker/issues/450 This seems a distro issue, it is working on Arch, but I do not use SELinux as it requires a lot of recompiles.

francoism90 commented 1 year ago

Sorry for the spam: https://blog.christophersmart.com/2021/01/31/podman-volumes-and-selinux/

It turns out I needed to use z instead of Z as I did share a few volumes with other containers. :)

It seems to work now, but I still need to pass the uid/gid to PODMAN_USERNS.

Edit: This doesn't work, as I need to pass as it userns_mode: keep-id:uid=${UID:-1000},gid=${GID:-1000}, which doesn't seem to do anything.

It's really frustrating.

Edit 2: It doesn't pass userns_mode at all:

podman create --name=app_1 --label io.podman.compose.config-hash=123 --label io.podman.compose.project=project --label io.podman.compose.version=0.0.1 --label com.docker.compose.project=project --label com.docker.compose.project.working_dir=/var/home/user/project --label com.docker.compose.project.config_files=docker-compose.yml --label com.docker.compose.container-number=1 --label com.docker.compose.service=app -v /var/home/fuserproject/src:/src:z,rw -v /var/home/user/project/data:/data:z,rw --net bridge --network-alias app  -p 5173:5173 -u 1000:1000 -w /src --restart on-failure app
a4fe1294d77f6389ffbc4fc42439279f277342b8e344a086209b2c55942e9170

Edit 3: it seems to work when using the devel branch:

$ python3 ~/Code/podman-compose/podman_compose.py up
Error: --userns and --pod cannot be set together