Run Docker container as unprivileged user, allow PUID/PGID selection#722
Run Docker container as unprivileged user, allow PUID/PGID selection#722lkubb wants to merge 14 commits intodgtlmoon:masterfrom
Conversation
|
|
||
| set -eu | ||
|
|
||
| # If the first argument looks like a flag, assume we want to run changedetection |
There was a problem hiding this comment.
hmmm what is the problem you're trying to solve here?
There was a problem hiding this comment.
Assuming you're referring to the line below: If the container is e.g. run with docker-compose run changedetection -c, this would run python ./changedetection.py -d /datastore -c inside the container. It's mostly a convention, nothing that's necessary, just nice to have. If you prefer it removed, no worries. :)
dgtlmoon
left a comment
There was a problem hiding this comment.
see PR comments - mainly about being sure it's actually /datastore ?
5534b50 to
314c310
Compare
| libxslt-dev \ | ||
| zlib1g-dev && \ | ||
| rm -rf /var/lib/apt/lists/*; \ | ||
| useradd -u 911 -U -d /datastore -s /bin/false changedetection && \ |
There was a problem hiding this comment.
why 911 ? :) Is it better to choose a UID > 1000 ?
There was a problem hiding this comment.
It's the standard one used by linuxserver.io and makes it a system user, but a higher default one like 3000 is fine as well imho. Would you prefer the default changed? It can be chosen freely anyways (docker-entrypoint.sh:L16-20).
|
also need to test this on an existing install which used root.root |
|
@lkubb biggest one so far, gosu not found |
0f6a310 to
e26de1f
Compare
|
hmm when it's running as test, it needs to use |
|
somehow needs a var passed to |
|
a) Introduce a new env var |
This is fine if theres a comment above like |
|
I added |
|
needs but why not just |
|
Because usually, there is no good reason for an application to be able to modify itself. We could of course disable all that with a build arg specifically for the workflow, but I would be very hesitant to |
|
haha I love tests, what looked like a simple PR always shows up something so |
From what I can tell, it creates it as ============================= test session starts ==============================
platform linux -- Python 3.10.9, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /app/changedetectionio, configfile: pytest.ini
plugins: flask-1.2.0
collected 1 item
tests/test_backup.py::test_backup
[...]
> with open("download.zip", 'wb') as f:
E PermissionError: [Errno 13] Permission denied: 'download.zip' |
|
Oops right you are, that test needs fixing so its using the |
|
Or better is that it doesnt even write the file to disk and just stores it memory |
|
to be honest the whole memory test thing is not needed.. you can remove it, or on another PR, it didnt really add anything interesting :) |
29afe61 to
467315d
Compare
|
Alright, I chose to just remove writing the file since the rest of the code does not interfere. |
|
agreed, no problems, some things seem like a nice idea - but just get in the way |
|
sometimes there are "random" fails, i'll keep an eye on it |
👍 It's still complaining that |
... to be able to install extra packages via pip
|
The SMTP tests were failing because |
|
Alright, all tests are passing now. For most setups, the entrypoint script should automatically chown the datastore to the correct user. The one exception is in case it is a network share mount, where it might fail. In this case, admins must ensure the correct In case this logic causes any problems, it can be skipped completely by setting the I'd really like to wrap this PR up soon since it has been going for nearly two and a half years. :) |
|
amazing thanks, will have a play with it - yeah its one of those "might break something at some time for somewhere" commits but it NEEDS to be in the codebase |
|
can you think of some test cases to try? like i already have a datastore owned by some user and... |
|
Unless otherwise noted, everything assumes 0755/0644 dir/file permissions (or 0 for others, just not 7/6). First, I would verify everything works as before when Then, with a root-owned (populated) local datastore:
Then chown -R the datastore to 1234:5678 and do 1 again. You should check that running the container rootless (still?) works with 1 (/4) (so root here is actually the local user account, PUID/PGID are relative to the user namespace). I'd probably check that correctly setup NFS/SAMBA mounts work. Tbh I'm not familiar with the application architecture, so I'm not sure if there are any other paths that should be tested.
Edit2: The entrypoint now only checks if the datastore is writable and tries to chown -R it if it's not. |
better than doing it every time, some datasets are pretty big |
This got lost during a rebase, it's not necessary anymore since the env var is set inside the container by default and changedetection respects it.
|
Alright, the entrypoint now checks writability of the datastore by the designated PUID:PGID combination and only intervenes if that fails. I'll adjust the proposed test cases above. |
| pass | ||
| # On Windows, create and use a default path. | ||
| if os.name == 'nt': | ||
| elif os.name == 'nt': |
There was a problem hiding this comment.
No, it would then not respect the DATASTORE_PATH defined by the user (or the default one set during container build time).
|
Thanks for this work! It seems that all tests pass, there are no conflicts with the base branch, and still this PR hasn't been updated for the past 5 months. Is there anything preventing it to be merged? |
|
@dgtlmoon is there any chance to get this pr merged? it looks like it is ready to go - and while the current container is running as root and writing files as root I am not able to backup the files running borg backup as unprivileged user: I have high hopes that this PR could solve my issue. thanks |
3cdc658 to
549e167
Compare
|
Thanks all, its a been a while, so I re-rolled it into #3900 , please, I would like your feedback :) |
Currently, the container process runs with root privileges. This cannot be changed, even by specifying PUID/PGID (as suggested in
docker-compose.yml).This PR migrates to running as an unprivileged user and makes it possible to specify PUID/PGID environment variables to choose UID/GID. Migration of existing data owned by root is handled transparently.
A side-effect is that the /app directory is read-only to the python process, I'm not sure if that is a problem since I'm not familiar with the architecture of changedetection.
I also took the liberty to clean up the Dockerfile (and apt cache) a bit, hope that's not a problem. :) Please feel free to suggest changes or deny the PR, if it does not fit your vision.
Fixes #565.