TandoorRecipes / recipes

Application for managing recipes, planning meals, building shopping lists and much much more!
https://docs.tandoor.dev
Other
5.56k stars 589 forks source link

Run processes inside container as non-root user #1257

Open graduatio opened 2 years ago

graduatio commented 2 years ago

Is your feature request related to a problem? Please describe. The processes inside the recipes container currently run as user root. This is potentially problematic for security reasons.

Describe the solution you'd like Whenever possible the processes should run as non-root user.

graduatio commented 2 years ago

I tried to run all containers (nginx, postgres and recipes) as a non-root user. The nginx and postgres docker documentations describe how the containers can run as an arbitrary non-privileged user. I followed the steps below:

For the nginx container:

For the recipe container:

Before I started the containers:

With this setup the database and the nginx server seem to work properly. Tandoor can be accessed by opening the ip-address. But the docker-compose logs show permission errors of the recipes container which cannot change files in /opt/recipes when executing the commands in boot.sh. This error occures because opt/recipes was created by user root. Changing the owner of the files inside the container manually resolves the problem temporarily. Maybe this issue can be resolved by setting a default user and changing the owner of opt/recipes in the Dockerfile.

vabene1111 commented 2 years ago

thanks, i will take a look at this at some point when the more pressing features are taken care of

Akruidenberg commented 1 year ago

Any progress so far. I would like to run the recipe container rootless. The trick of @graduatio is working, only manually .

graduatio commented 1 year ago

@Akruidenberg unfortunately the processes in the default container still run as user root. To simplify the modification process of the recipe container to run as a non-root user I currently use following docker-compose.yaml in combination with an additional Dockerfile in ./recipes:

docker-compose.yaml

version: "3"
services:
  db_recipes:
    restart: always
    image: postgres:alpine
    volumes:
      - ./postgresql:/var/lib/postgresql/data
    env_file:
      - ./.env

  web_recipes:
    build: ./recipes/
    user: "${UID}:${GID}"
    restart: always
    env_file:
      - ./.env
    volumes:
      - staticfiles:/opt/recipes/staticfiles
      - nginx_config:/opt/recipes/nginx/conf.d
      - ./mediafiles:/opt/recipes/mediafiles
    depends_on:
      - db_recipes

  nginx_recipes:
    image: nginx:mainline-alpine
    restart: always
    ports:
      - 80:80
    env_file:
      - ./.env
    depends_on:
      - web_recipes
    volumes:
      - nginx_config:/etc/nginx/conf.d:ro
      - staticfiles:/static:ro
      - ./mediafiles:/media:ro

volumes:
  nginx_config:
  staticfiles:

Dockerfile

FROM vabene1111/recipes:latest
RUN adduser -D --uid 999 tandoor
RUN chown -R 999:999 /opt/recipes
USER 999:999
ENTRYPOINT ["/opt/recipes/boot.sh"]

TheUID and GID have to be specified in the .env file and should match the values in the Dockerfile.

Akruidenberg commented 1 year ago

@graduatio thanks. Will try it out

dsm1212 commented 11 months ago

Any update on this? With the advent of rootless docker, most containers support setting user now through compose or env vars. This is the only one I have left that doesn't support it.

smilerz commented 11 months ago

Feel free to submit a PR with an updated Dockerfile.

dsm1212 commented 10 months ago

Ok, so the issue really is that during startup django writes a file to /opt/recipes/cookbook/static. For me it was just one file (django_js_reverse/reverse.js). But that tree is all owned by root so if the container is started with a user then that copy fails. Aside from that you just have to make sure that all volumes are chown to the user you are using. Is there a point in the build where this static folder is created we could just change the default permissions inside the image on /opt/recipes/cookbook/static/*? I don't know enough about what is going on to know if it is always just this one file or could be the whole tree.

To confirm it worked I just used a build with chmod -R 777 /opt/recipes/cookbook/static.

rettops commented 5 months ago

What worked for me is to map the cookbook/static directory along with the others in my docker-compose.yml:

    volumes:
      - ./recipes_data/staticfiles:/opt/recipes/staticfiles
      - ./recipes_data/cookbook/static:/opt/recipes/cookbook/static
      - ./recipes_data/mediafiles:/opt/recipes/mediafiles
dsm1212 commented 5 months ago

What worked for me is to map the cookbook/static directory along with the others in my docker-compose.yml:


    volumes:
     ...
      - ./recipes_data/cookbook/static:/opt/recipes/cookbook/static

I tried this and cookbook/static just ended up containing the django_js_reversed/reverse.js file. But this cookbook/static folder has a ton of contents in the image and the app doesn't work without them. Did you copy the files out of the image? That would make updating hard. However, I did find that if I mapped this subfolder which contains the one file that gets copied it works though, so thanks for the suggestion:

rettops commented 5 months ago

Hmm. You're right, my cookbook/static directory ended up containing only the django_js_reverse directory, but the app seemed to work fine. In any case, your solution is probably better, because it's more surgical. I think you may have a typo, because my copy of the app expects a django_js_reverse directory rather than django_js_reversed.

On Thu, Jun 6, 2024 at 8:21 PM dsm1212 @.***> wrote:

What worked for me is to map the cookbook/static directory along with the others in my docker-compose.yml:

volumes:
 ...
  - ./recipes_data/cookbook/static:/opt/recipes/cookbook/static

I tried this and cookbook/static just ended up containing the django_js_reversed/reverse.js file. But this cookbook/static folder has a ton of contents in the image and the app doesn't work without them. Did you copy the files out of the image? That would make updating hard. However, I did find that if I mapped this subfolder which contains the one file that gets copied it works though, so thanks for the suggestion:

- ./recipes_data/cookbook/static/django_js_reversed:/opt/recipes/cookbook/static/django_js_reversed

— Reply to this email directly, view it on GitHub https://github.com/TandoorRecipes/recipes/issues/1257#issuecomment-2153777022, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAERLSFGIU2YQJ4VHCNUSGLZGERLXAVCNFSM6AAAAABI52B7PWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDCNJTG43TOMBSGI . You are receiving this because you commented.Message ID: @.***>