How to upgrade with compose and docker volumes

Having just migrated from nextcloud bare-metal to nextcloud docker-compose, I have now just run into my first upgrade, which fails due to Operation not permitted and permission denied errors.

In my setup, I have /var/www/html as a docker volume. The docker volume internally has the permissions ‘www-data:www-data’ for all nextcloud/php files. My data volume is /var/www/data thus isolated from the html bits.

During start of nextcloud, it wants to upgrade from to which internally uses ‘rsync’ from the entrypoint to copy the installation files to my volume. But this is where the problems start, because the container is doing this step as root, instead of www-data, it now cannot copy/create files anymore. Changing the volume (from the /var/lib/docker/volumes/…/_data) to root:root (but keeping www-data on config.php), adding o+w and running the container with 'cap-add fowner,chown.

This gets me through the upgrade, but have to then ‘undo’ my chown/o+w-ing, and start NC again.

However, I then am greeted with nextcloud-init-sync.lock; but I may have had this issue before as well as I found o+w bit to have been set on the root of my volume … though I have safely removed that again as it’s enough to just have the file with root:root permissions. This does indicate that the volume needs access for two users, www-data for the php files during ‘runtime’ and root for nextcloud-init-sync.lock for startup.

I’m sure this isn’t the way/intended behavior is it? What am I doing wrong?

P.S. No idea why or how or even if important, but I’m also getting
Warning: /var/www/html/config/autoconfig.php differs from the latest version of this image at /usr/src/nextcloud/config/autoconfig.php
Warning: /var/www/html/config/redis.config.php differs from the latest version of this image at /usr/src/nextcloud/config/redis.config.php
Warning: /var/www/html/config/s3.config.php differs from the latest version of this image at /usr/src/nextcloud/config/s3.config.php
Warning: /var/www/html/config/smtp.config.php differs from the latest version of this image at /usr/src/nextcloud/config/smtp.config.php
Warning: /var/www/html/config/upgrade-disable-web.config.php differs from the latest version of this image at /usr/src/nextcloud/config/upgrade-disable-web.config.php
as part of my upgrade. I can just copy these files no problem, but wondered why the upgrade didn’t do this itself. Those files are mostly not existing …

I can’t follow the problem well. Please review Docker upgrade procedure. By default the container runs as root and starts the webserver as www-data. I’m doing such upgrade since years without issues.

1 Like

Please post your actual Docker Compose. Are you running a customized image?

I can just copy these files no problem, but wondered why the upgrade didn’t do this itself. Those files are mostly not existing …

This is a new bit of code that detects if you have out-of-date config files in your installation. The docs describing what it means and what to do about it are here.

So that doc lists as upgrade steps:

$ docker-compose pull
$ docker-compose up -d

I’m pretty sure I can’t mess that up much :stuck_out_tongue:

But no, not running a customized image. My compose config is the following:

  nextcloud: {}


      - setgid
      - setuid
      - all
      - postgresql
      - redis
      - common.env
      - ./nextcloud/server.env
      - postgresql_socket:/run/postgresql:rw
      - redis_socket:/run/redis:rw
      - ./nextcloud/user.ini:/var/www/html/.user.ini:rw
      - nextcloud:/var/www/html:rw
      - /srv/nextcloud_userdata:/var/www/data:rw
      - ./nextcloud/opcache.ini:/usr/local/etc/php/conf.d/opcache-recommended.ini:ro
      - nextcloud
      - nginx
      - "80/tcp"
    restart: unless-stopped
      test: runuser --user www-data -- php -f /var/www/html/cron.php
      interval: 5m
      timeout: 10m
      start_period: 1m

While I want to upgrade to the fpm image at some point, this is what I have right now. Redis I want to change for the foss thing also at some point …

In common.env, there’s nothing more then TZ='Europe/Amsterdam' and in server.env I have


Where VIRTUAL_HOST is used by docker-gen, but not relevant to this container itself.

opcache.ini was my trying to solve nextcloud setupcheck complaining about opcache. Haven’t gotten this to work, as I change values, it keeps complaining. So I left it at this for now.


and finally user.ini, like server.env to increase large files being able to be uploaded.


But this is probably all un-relevant. The upgrade fails because the entrypoint script cannot rsync the files to /var/www/html. This is because as per migration guide

docker-compose exec app chown -R www-data:www-data /var/www/html/config

We should chown everything to www-data. Obviously, while checking this again right now, I noticed that maybe I was a bit to overzealous with my chowning. I changed ownership of /var/www/html instead of just config and custom_apps. So i’ll switch the standard nextcloud files to root:root! It makes sense, nobody should be able to edit those files …

Lets see if the next upgrade will cause the same issues with root:root permissions.

Btw, I am aware of the autoconfiguration scripts. I even wrote a patch once that I failed to submit :stuck_out_tongue: but this could be due to the same reason as above. Wrong permissions caused things to fail.

Probably no dev reading this; but maybe it’s an idea to split out config (and custom apps, but I’m sure that’s already possibly) like data so we can keep the config isolated from the code. Permissions become more obvious and easy to handle in that case. I do get that it’s tricky because config.php holds the locations of folders …

that’s true but many people don’t read/follow the docs for this reason we always ask!

I was curious if cap_add/cap_drop order might be a problem but seems to be OK according to Docker-Compose: order of cap_drop and cap_add? - #3 by thediveo - Compose - Docker Community Forums this is the most noticeable difference from default - check if it works without this directive in the future

I would expect root can rsync files of another user but not other way round. As you can see in my guide Nextcloud docker-compose setup with notify_push (2024) apps, config and data are owned by the limited container user (which IMHO translates to www-data by default)

you are right it is possible (see the guide above) or container docs > additional volumes