containers / podlet

Generate Podman Quadlet files from a Podman command, compose file, or existing object
https://crates.io/crates/podlet
Mozilla Public License 2.0
422 stars 12 forks source link

Readme container doc: map user into podlet container #50

Closed rugk closed 8 months ago

rugk commented 8 months ago

I am curious why you would suggest that. I have just spend useless time debugging why my path could not be found, because I blindly copied that command and thought it was just a 1:1 mapping.

If podlet does not support user systemd directories, it should also not support that in the container due to some strange mapping, should it? If it does support that, then no reason to re-map it, it should work as usual, should not it?

rugk commented 8 months ago

Ah now I see why you did this: When you use the -u a (likely running as root) containered podlet thinks it has system permission and thus should use the system's systemd path /usr/share/containers/systemd/. Thus, remapping the path solves this.

However, the disadvantage is that you still get a wrong output: Wrote to file: /usr/share/containers/systemd/….container

As such, IMHO, this is still nor idea.

I tried using -u to switch to user execution, but then you have the problem your user likely does not exist in the docker container. This can be solved by using your $UID instead…

I am already at, but this still fails due to permission errors:

alias podlet='podman run --rm -u $(id -u) --security-opt label=disable -v "$PWD":"$PWD:Z" -v "$HOME/.config/containers/systemd/":"$HOME/.config/containers/systemd/:Z" -w "$PWD" --pull=newer quay.io/k9withabone/podlet'

--userns=keep-id also does not seem to make a difference… uff

rugk commented 8 months ago

Okay with keep-id it should actually work. i tested it with a bash shell and it works.

Is this maybe actually a problem in podlet? Because it seems to try to use

$ podlet -u --install --overwrite compose  docker-compose.yml
Error: 
   0: Failed to create/open file: [THE_PWD]/.config/containers/systemd/grocy.container
   1: No such file or directory (os error 2)

Location:
   src/cli.rs:526

Suggestion: Make sure the directory exists and you have write permissions for the file

Backtrace omitted. Run with RUST_BACKTRACE=1 environment variable to display it.
Run with RUST_BACKTRACE=full to include source snippets.

Ah no of course, it uses $HOME, but does not have this, so we need to pass this through, too.

# https://github.com/k9withabone/podlet#in-a-container
alias podlet='podman run --rm --userns keep-id -e HOME --user $(id -u) -v "$PWD":"$PWD:Z" -v "$HOME/.config/containers/systemd/":"$HOME/.config/containers/systemd/:Z" -w "$PWD" --pull=newer quay.io/k9withabone/podlet'

Finally works.

k9withabone commented 8 months ago

blindly copied that command

Blindly copying a command (especially from the internet) is never a good idea.

@Nitrousoxide could you take a look at this PR?

@rugk I don't use podlet (or command line applications in general) in a container, so I don't know what the best practices are and am not the best person to review this. I mostly use containers for self-hosted web services and am by no means an expert on containers/podman. @Nitrousoxide is the one who originally wrote the suggested command for using podlet in a container, so maybe they can explain this better?

With rootless podman, by default, the root user inside a container corresponds to the user running podman. However, Fedora CoreOS might have different defaults than this. I personally use Fedora Workstation and Server, but have no experience with CoreOS. The podlet --unit-directory option changes its behavior based on whether podlet thinks it's running as root. From podlet --help:

  -u, --unit-directory
          Generate a file in the podman unit directory instead of printing to stdout

          Conflicts with the --file option

          Equivalent to `--file $XDG_CONFIG_HOME/containers/systemd/` for non-root users, or `--file /etc/containers/systemd/` for root.

          The name of the file can be specified with the --name option.

          [aliases: unit-dir]

So the example podman command mapping the user's quadlet unit directory ($HOME/.config/containers/systemd/) to the system's (/etc/containers/systemd/) inside the container makes sense. Since podlet as root inside the container maps to the user running podman, there also shouldn't be permission issues.

The only downside, from what I can tell, is that podlet reports saving the file to a different path than perhaps naively expected when using the --unit-directory option. But running applications inside a container always have quirks around file system paths.

Nitrousoxide commented 8 months ago

https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html is the readme for quadlet

~/.config/containers/systemd/ is a perfectly valid place to drop the quadlets (and is what a systemctl --user daemon-reload would look at when generating new .service files so that aspect is a fine change.)

I don't think the :z suffux is needed here since the command is excluding any selinux labeling with --security-opt label=disable set since it's envisioning that you might run this anywhere in home (including $HOME), to pick up the compose file to convert into quadlet files. using selinux labels like :z shouldn't matter then.

If you're looking to run this in a specific location in home where selinux relabeling won't screw something up then it might be okay. In that case though you should remove the --security-opt label=disable flag.

As to the user issue: this is the info on how it handles user namespace https://docs.podman.io/en/v4.6.1/markdown/options/userns.container.html

Generally, if you are going to run a container that might pick up anything in $HOME I'd either run it as the default user namespace (where root in the container is the user running podman, usually user 1000 if you are the only user on the machines) then you're fine. The container cannot grab more permissions than the user has, so it can't do anything with a "real root"

Since this container is expected to run anywhere on $HOME to pick up an arbitrary docker-compose.yml file and convert it, running it in the user-ns or as the default (where user 0 in the container is the user running podman) is probably preferable. Though you can do --userns keep-id and set the user running in the container to be --user $(id -u). That's perfectly valid as well. It is effectively running as the same user either way.

rugk commented 8 months ago

I don't think the :z suffux is needed here since the command is excluding any selinux labeling with --security-opt label=disable set since it's envisioning that you might run this anywhere in home (including $HOME), to pick up the compose file to convert into quadlet files. using selinux labels like :z shouldn't matter then. […] In that case though you should remove the --security-opt label=disable flag.

See https://github.com/k9withabone/podlet/pull/51 for now. I've split the feature into two PRs, so you can merge one or the other only. Also, in this PR there is no :z suffix. The other ones removes relabeling.

running it in the user-ns or as the default (where user 0 in the container is the user running podman) is probably preferable.

You mean the behavior before: root inside the container, user outside. The problem here was explained by me before:

When you use the -u a (likely running as root) containered podlet thinks it has system permission and thus should use the system's systemd path /usr/share/containers/systemd/. Thus, remapping the path solves this.

However, the disadvantage is that you still get a wrong output: Wrote to file: /usr/share/containers/systemd/….container

So it technically works, but it causes confusing console output (with the "wrong" path) for the user. This PR intends to solve this and cause the "correct" console output with the actual path. @k9withabone also said this:

The only downside, from what I can tell, is that podlet reports saving the file to a different path than perhaps naively expected when using the --unit-directory option

So again, this is what this PR solves. And I see no disadvantage in mapping the user namespace and user into it? I know the previous solution also works, but this is better, is not it? Or are there any other disadvantages?

Nitrousoxide commented 8 months ago

I don't see any problem with the user-ns change. You'd want to use the podman ns in most containers to increase separation between the host and containers, but here you want a short-lived container to grab an arbitary compose file from (presumably) somewhere in $HOME and drop the converted .container, .volume, and .network files into the quadlet search path.

As you said, avoiding using root inside the container is usually preferable, since even if it doesn't actually grant any real additional permission in (non rootful) podman, it does lead to less confusion as to what the permission set available to the app is in the container and stdout logs.

k9withabone commented 8 months ago

So again, this is what this PR solves.

Honestly, I was having a hard time telling what the goal of this PR was. Now that I do understand it seems like a good change to me.

I think adding -e XDG_CONFIG_HOME to the command would also be a good idea as it might be set to something other than ~/.config/ and that is what podlet and quadlet check first.

rugk commented 8 months ago

Thanks, yeah. My PR was a bit unclear due to me experimenting with it at the same time, so sorry for that. Also quoted the variables, while I was at it. See https://www.shellcheck.net/wiki/SC2086

k9withabone commented 8 months ago

This looks good to merge to me. Unless anyone has objections I'll merge this tomorrow. I'll probably do a squash merge so that the commit history is a little clearer.