docker icon indicating copy to clipboard operation
docker copied to clipboard

Make cron.php be executed by UID provided at startup.

Open Moltey opened this issue 3 years ago • 14 comments

Expectation:

Cron should execute cron.php with the UID the container is started with (in case a UID is provided).

Status Quo:

Cron.php is executed with www-data, which is UID 33 / 34 (depends on distribution) in the container.

Result: Cron fails to execute cron.php withe the appropriate user.

Details:

Due to security reasons, I am running all my containers rootless and with seperated user accounts. I think rootless non-root execution will be the future of containerization anyways.

I utilize user 1008 for nextcloud.

Nextcloud recognizes this fact and reminds the user that cron is to be executed by the same user in the web interface:

Use system cron service to call the cron.php file every 5 minutes. The cron.php needs to be executed by the system user "1008".

Therefore, I want to start the cron container with the same UID as the app:

$ podman run -d \
  --name=nextcloud-cron \
  --pod=nextcloud \
  --restart unless-stopped \
  --runtime crun \
  --user 1008:1008 \
  -v ~/nc/html:/var/www/html:z \
  -v ~/nc/data:/var/www/data:z \
  --cap-add=CAP_NET_BIND_SERVICE \
  --cap-add=CAP_SETGID \
  --cap-add=CAP_SETUID \
  --entrypoint=/cron.sh \
  docker.io/library/nextcloud:latest

The containers works, file access is fine for UID 1008 - however, the execution of cron.php fails:

crond: USER www-data pid   4 cmd php -f /var/www/html/cron.php
Could not open input file: /var/www/html/cron.php

Nevermind, as "www-data" would be UID 33 and not the appropriate user anyways (should be 1008, as announced by nextcloud). File access for UID 1008 is working fine though.

If I change the UID of www-data in passwd to the designated UID 1008 and passthrough the passwd to the container, the execution fails:

Passwd line:

www-data:x:1008:33:www-data:/var/www:/usr/sbin/nologin

Additional passthrough of passwd for the start of podman:

  -v ~/nc/passwd:/etc/passwd:ro \

Output of the cron-log:

crond: USER www-data pid   2 cmd php -f /var/www/html/cron.php
This account is currently not available.

There is a solution, but it is crap: The execution of cron-php via host works fine:

$ podman exec --user 1008 -t nextcloud-cron php -f /var/www/html/cron.php

Desperate users could execute this line via crond of the host but hopefully you agree that this is not what we want to see ;)

Moltey avatar Apr 27 '22 21:04 Moltey

This might be a duplicate of https://github.com/nextcloud/docker/issues/359

J0WI avatar Apr 28 '22 18:04 J0WI

I have a similar issue and I have tried different images, removed and reinstalled multiple times and cron doesn't run as it's supposed to. Here are the details of my setup (please excused me as I'm new to self hosting but have spent huge number of hours trying to solve this issue)

OS - Windows Distro - WSL2 kernel and Ubuntu Nextcloud - Latest version with mariadb and redis Issue - Selecting Cron in setting doesn't do anything Solutions tried -

  1. Removed and reinstalled nextcloud, Ubuntu, WSL - Still no solution
  2. Install an image along with cron container - Didn't help
  3. Tried sudo crontab -u www-data -e and adding the cron line + service cron start - service cron status shows running but didn't help
  4. Tried docker exec -u 33 -t nextcloud php -f /var/www/html/cron.php - It runs but this is a manual one time activity post which cron is not running
  5. Tried crontab -e on ubuntu and adding cron line */5 **** php -f /var/www/html/cron.php - No help it doesn't run
  6. in all cases tried provide absolute php path - Still didn't work
  7. Tried system timer as mentioned in doc however systemd doesn't work as it gives an error about PID. Tried alternate command for init and still didn't work
  8. I still tried few other's that I forgot to document to review but none helped run cron

I'm finally reaching out here to see if anyone could help

Thanks,

vicky-bs avatar May 11 '22 13:05 vicky-bs

@J0WI: #359 fixes the UID/GID issue with apache (in the "app" container), but the "cron" container that runs the cron jobs, the user is hard coded as www-data:

https://github.com/nextcloud/docker/blob/6e7695e4439e18900ce4435de359d8ece6b6a35f/Dockerfile-alpine.template#L10-L11

So what ends up happening is, apache runs as a non-root user as per the UID:GID, but cron runs as www-data and fails repeatedly with permission errors.

@Moltey: I have implemented another solution:

I override the cron.sh to change the www-data hardcoding:

#!/bin/sh
set -eu

adduser --disabled-password --gecos "" --uid "$APACHE_UID" user

mv /var/spool/cron/crontabs/www-data /var/spool/cron/crontabs/user
exec busybox crond -f -l 0 -L /dev/stdout

then I mount it (read-only) within my "app" container, and pass the appropriate APACHE_UID to my "cron" container:

services:
  ...
  app:
    ...
    volumes:
    - ./cron.sh:/cron.sh:ro
    ...
  cron:
    ...
    volumes_from:
    - app:rw
    environment:
      APACHE_UID: 1008

That's the key idea, but I implemented a couple of other hacks to be able to edit the crontab file directly from the host -- it's reloaded automatically in the "cron" container.

@J0WI: I think the app (not cron) entrypoint should create a new user with the UID:GID and add move the cron job (from www-data) to that user. Then the cron container would work as expected without any additional hacks

SaswatPadhi avatar Nov 09 '22 03:11 SaswatPadhi

I tried to move a simple echo "*/5 * * * * php -f /var/www/html/cron.php" | busybox crontab - script to the cron.sh entrypoint itself, but unfortunately busybox does not allow to run crontab as non-root: https://git.busybox.net/busybox/tree/miscutils/crontab.c?h=1_35_stable#n110

J0WI avatar Nov 25 '22 20:11 J0WI

Yes, busybox requires crond to run as root.

The current entrypoint script does run it as root. The problem is just that the crontab file (at /var/spool/cron/crontabs) is under the wrong user (www-data). When the nextcloud container runs with a non-root UID (using --user), the crontab file should actually be renamed to that user's name in place of www-data, to avoid permission issues.

As you have noticed, it's currently not possible to run the cron container as a non-root user, although nextcloud container can run as a non-root user. Currently, even when the cron container is run as root, the cron jobs fail with permission errors.

As for security, the cron container only runs the crond process as root. The actual cron tasks (php) are run with the respective user's UID, which is www-data currently.

SaswatPadhi avatar Nov 25 '22 20:11 SaswatPadhi

At this point, I think it's easier to just run your own docker run -v my_nextcloud:/var/www/html --user my_user nextcloud:fpm-alpine sh -c 'while true; do php -f /var/www/html/cron.php; sleep 5m; done'. Or, as already mentioned above, just use a timer on your host that runs docker exec ....

There is no trivial way to run the cron script as non-root and detect whatever user is used in the other container.

J0WI avatar Nov 26 '22 14:11 J0WI

The bug report is about making cron.php be executed by the right UID, not crond.

I think you are mixing up the cron daemon with cron scripts (or crontabs).

There is no trivial way to run the cron script as non-root

False. They (var/spool/cron/crontabs/www-data) already do, just as the wrong user.

SaswatPadhi avatar Nov 26 '22 17:11 SaswatPadhi

If you run the cron container as root, it can run crond and manage crontabsfor all users. However, the cron container has no knowledge of the user that runs in the other PHP container. You have to specify the user. The above example executes cron.php as my_user.

J0WI avatar Nov 26 '22 20:11 J0WI

At this point, I think it's easier to just run your own docker run -v my_nextcloud:/var/www/html --user my_user nextcloud:fpm-alpine sh -c 'while true; do php -f /var/www/html/cron.php; sleep 5m; done'. Or, as already mentioned above, just use a timer on your host that runs docker exec ....

There is no trivial way to run the cron script as non-root and detect whatever user is used in the other container.

Can we please agree that this is a very nasty workaround? 😄

In ended up calling cron.php via the crontab of the host machine which is not satisfying, neither.

IMHO, this is a design issue you might want to consider in one of the next major releases.

Moltey avatar Nov 27 '22 12:11 Moltey

This is somewhat covered in https://github.com/nextcloud/docker/pull/1901

J0WI avatar Feb 08 '23 15:02 J0WI

Running crond (the daemon) as non-root and running the cron.php file (the cron job) as non-root are two different things.

SaswatPadhi avatar Feb 09 '23 04:02 SaswatPadhi

I attempted to use the nextcloud cron container, but it didn't work as described in this issue. The container was configured to run as a non-root user using the user option with a specific UID and GID, but the cronjob failed. I believe it is not worth using it as it needs to run as root. Running containers as root is generally not recommended due to security reasons.

I decided to set up a cronjob on my LXC host. I added a cronjob for a non-root user who is also not part of the sudo group, to run the cron script inside the nextcloud container using docker exec.

*/5 * * * * docker exec -u 1000:1000 nextcloud_container  php ./cron.php

To check that the cronjob ran successfully, I searched the syslog for the cron script using this command:

grep -a "cron.php" /var/log/syslog

This solution will work for me until Nextcloud decides to address the issue.

remus-selea avatar Apr 08 '23 15:04 remus-selea

I ended up building a custom image with supercronic, couldn't get crond to work as non-root either.

ARG NEXTCLOUD_VERSION
FROM nextcloud:${NEXTCLOUD_VERSION}-apache

ENV SUPERCRONIC_VERSION="v0.2.25"
ENV SUPERCRONIC_PACKAGE="supercronic-linux-amd64"
ENV SUPERCRONIC_SHA1SUM="642f4f5a2b67f3400b5ea71ff24f18c0a7d77d49"

ENV SUPERCRONIC_URL="https://github.com/aptible/supercronic/releases/download/$SUPERCRONIC_VERSION/$SUPERCRONIC_PACKAGE"

RUN curl --fail --silent --show-error --location --output /supercronic "${SUPERCRONIC_URL}" && \
    echo "${SUPERCRONIC_SHA1SUM}  /supercronic" | sha1sum -c -                              && \
    chmod +x /supercronic

RUN echo "${CRON:-"*/10 * * * *"} php -f /var/www/html/cron.php" > /crontab

ENTRYPOINT ["/supercronic", "/crontab"]

chylex avatar Jun 17 '23 05:06 chylex