Permission Issues - Help Needed - (more) advanced Nextcloud Docker Install

NOTE: This is a long post, apologies in advance.

Topic: Having trouble getting a working Nextcloud instance installed via docker compose. I believe this is related to using bind-mounts for the volumes causing permissions issues when starting the container. I am trying to use a semi-custom docker install using the image found here as an example. I will attempt to post most relevant details of my setup here, and the actual error logs I am seeing.

I will note - I have setup Nextcloud very similarly on a previous server around 5 years ago, although this used Docker volumes as opposed to bind-mounts which is why I likely did not have permission issues. For this new home server, I need to use bind-mounts as the physical storage layout is different.

I have been following along these excellent guides from @wwe here and @estebanium here to help me, but my configuration is slightly different so not sure where I might be turning wrong.

The Basics

  • Nextcloud Server version (e.g., 29.x.x):
    • latest, 30
  • Operating system and version (e.g., Ubuntu 24.04):
    • OpenMediaVault 7 (Debian 12)
  • Web server and version (e.g, Apache 2.4.25):
    • Apache, latest
  • Reverse proxy and version _(e.g. nginx 1.27.2)
    • Caddy, latest, although I only use this to reverse proxy internally to my LAN using a pihole as the DNS lookup. I do use local tls certs via the Caddyfile.
  • PHP version (e.g, 8.3):
    • latest
  • Is this the first time you’ve seen this error? (Yes / No):
    • Yes
  • When did this problem seem to first start?
    • Attempting to pull the container up/install
  • Installation method (e.g. AlO, NCP, Bare Metal/Archive, etc.)
    • Docker compose
  • Are you using CloudfIare, mod_security, or similar? (Yes / No)
    • No

Summary of the issue you are facing:

Issues with permissions, the logs (below) are showing it with Redis, but I think there is more permissions issues than just that. I believe it is due to using bind-mouts in my setup and something wrong there…

Upon pulling up the container(s) nextcloud appears to just continually keep trying to restart, all the other containers seem to be running fine.

Steps to replicate it (hint: details matter!):

  1. Server has 3 total drives, 1 is simply OS (OMV), 1 is a small SSD (used to run docker services), 1 is an HDD for storing media.

So my system looks like this:
OMV OS - dev/sda
SSD - dev/sdb
HDD1 - dev/sdc

  1. Docker is run through the OMV interface and setup like so (per default OMV guide here and here):
Docker_AppData -> /dev/sdb (SSD) -> [root:root | admin = read/write, users = no access, Others - no access]
     this is env var ${PATH_TO_APPDATA} in the compose.yaml below

Docker_Data -> /dev/sdc (HDD1) -> [root:users| drwxrwsr-x]
     this is env var ${PATH_TO_DATA} in the compose.yaml below

Docker (itself) - /dev/sdb  (SSD) -> [root:root | drwx--x---]
  1. I created a seperate user via the OMV interface to run the docker containers. We will call this user “DOCKER_USER” with a UID of 1002 and GID of 100. this user was given permission to the _ssh, sambashare, sudo and users groups. This user was also given read/write permissions to the “Docker_AppData” and “Docker_Data” and “Docker” directories via the OMV interface (they are called “shared folders” in OMV, a way to manage directories via the GUI).

  2. I created a docker-compose.yaml, a Dockerfile, a php.ini file, a reddis-session.ini file, a supervisord.conf file and remoteip.conf file per the above guides and my previous install. I will put the contents of each file below as well. The Dockerfile and docker-compose.yaml were created via the OMV docker interface. The rest of the files were created and put into their respective locations with permissions changed per the docker-compose.yaml (following the guides linked above). The structure on my drives then looks something like this:

/dev/sdb (SSD)
    |-/Docker_Appdata [ root:users | drwxrwsr-x (0666)]
        |- /nextcloud [root:root| drwx------ (700)]
            |- nextcloud.yaml [root:root | -rw------- (600)]
            |- php.ini [DOCKER_USER:users | -rwxrwxrwx (777)]
            |- reddis-session.ini [DOCKER_USER:users | -rwxrwxrwx (777)]
            |- remoteip.conf [DOCKER_USER:users | -rw-r--r--(644)]
            |- supervisord.conf [DOCKER_USER:users | -rwxrwxrwx (777)]
    |- /docker [root:root | drwx--x--- (710)]

/dev/sdc (HDD1)
    |- /Docker_Data [root:users | drwxrwsr-x (0666)]
        |- /nextcloud [DOCKER_USER:users | drwxr-sr-x (0666)]
             |- data [DOCKER_USER:users | drwxr-sr-x (0666)]
             |- big_temp_file [DOCKER_USER:users | drwxr-sr-x (0666)]
        |- /ncdb [DOCKER_USER:users | drwxr-sr-x (0666)]
    
  1. I then build the Dockerfile image, and pull the container up using the OMV interface which is just calling docker-compose up -d. (file contents below.)
  2. The containers get pulled up, and after that the nextcloud container keeps restarting, giving the error logs below.

Log entries

Output of log from docker (via OMV interface):

imaginary-1  | Imaginary has started
ncdb         | 2025-02-15 13:09:42-05:00 [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:11.6.2+maria~ubu2404 started.
ncdb         | 2025-02-15 13:09:42-05:00 [Note] [Entrypoint]: MariaDB upgrade not required
ncdb         | 2025-02-15 13:09:42 0 [Note] Starting MariaDB 11.6.2-MariaDB-ubu2404-log source revision d8dad8c3b54cd09fefce7bc3b9749f427eed9709 server_uid Vd/ZhQ9/1UDIkuJiKG/mWrlg94k= as process 1
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: Compressed tables use zlib 1.3
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: Number of transaction pools: 1
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: Using crc32 + pclmulqdq instructions
ncdb         | 2025-02-15 13:09:43 0 [Note] mariadbd: O_TMPFILE is not supported on /tmp (disabling future attempts)
ncdb         | 2025-02-15 13:09:43 0 [Warning] mariadbd: io_uring_queue_init() failed with errno 95
ncdb         | 2025-02-15 13:09:43 0 [Warning] InnoDB: liburing disabled: falling back to innodb_use_native_aio=OFF
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: Initializing buffer pool, total size = 128.000MiB, chunk size = 2.000MiB
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: Completed initialization of buffer pool
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: File system buffers for log disabled (block size=4096 bytes)
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: End of log at LSN=47629
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: Opened 3 undo tablespaces
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: 128 rollback segments in 3 undo tablespaces are active.
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: Setting file './ibtmp1' size to 12.000MiB. Physically writing the file full; Please wait ...
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: File './ibtmp1' size is now 12.000MiB.
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: log sequence number 47629; transaction id 14
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
ncdb         | 2025-02-15 13:09:43 0 [Note] Plugin 'FEEDBACK' is disabled.
ncdb         | 2025-02-15 13:09:43 0 [Note] Plugin 'wsrep-provider' is disabled.
ncdb         | 2025-02-15 13:09:43 0 [Note] InnoDB: Buffer pool(s) load completed at 250215 13:09:43
ncdb         | 2025-02-15 13:09:43 0 [Note] Binary log 'binlog.000001' is not purged because less than 'slave_connections_needed_for_purge' slaves have processed it
ncdb         | 2025-02-15 13:09:44 0 [Note] Server socket created on IP: '0.0.0.0'.
ncdb         | 2025-02-15 13:09:44 0 [Note] Server socket created on IP: '::'.
ncdb         | 2025-02-15 13:09:44 0 [Note] mariadbd: Event Scheduler: Loaded 0 events
ncdb         | 2025-02-15 13:09:44 0 [Note] mariadbd: ready for connections.
ncdb         | Version: '11.6.2-MariaDB-ubu2404-log'  socket: '/run/mysqld/mysqld.sock'  port: 3306  mariadb.org binary distribution
ncredis      | 1:C 15 Feb 2025 18:09:42.092 # WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can also cause failures without low memory condition, see https://github.com/jemalloc/jemalloc/issues/1328. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
ncredis      | 1:C 15 Feb 2025 18:09:42.092 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
ncredis      | 1:C 15 Feb 2025 18:09:42.092 * Redis version=7.4.2, bits=64, commit=00000000, modified=0, pid=1, just started
ncredis      | 1:C 15 Feb 2025 18:09:42.092 * Configuration loaded
ncredis      | 1:M 15 Feb 2025 18:09:42.092 * monotonic clock: POSIX clock_gettime
ncredis      | 1:M 15 Feb 2025 18:09:42.093 * Running mode=standalone, port=6379.
ncredis      | 1:M 15 Feb 2025 18:09:42.093 * Server initialized
ncredis      | 1:M 15 Feb 2025 18:09:42.093 * Ready to accept connections tcp
nextcloud    | Configuring Redis as session handler
nextcloud    | /entrypoint.sh: 137: cannot create /var/www/html/nextcloud-init-sync.lock: Permission denied
nextcloud    | Configuring Redis as session handler
nextcloud    | /entrypoint.sh: 137: cannot create /var/www/html/nextcloud-init-sync.lock: Permission denied
nextcloud    | Configuring Redis as session handler
nextcloud    | /entrypoint.sh: 137: cannot create /var/www/html/nextcloud-init-sync.lock: Permission denied
nextcloud    | Configuring Redis as session handler
nextcloud    | /entrypoint.sh: 137: cannot create /var/www/html/nextcloud-init-sync.lock: Permission denied
nextcloud    | Configuring Redis as session handler
nextcloud    | /entrypoint.sh: 137: cannot create /var/www/html/nextcloud-init-sync.lock: Permission denied
nextcloud    | Configuring Redis as session handler
nextcloud    | /entrypoint.sh: 137: cannot create /var/www/html/nextcloud-init-sync.lock: Permission denied
nextcloud    | Configuring Redis as session handler
nextcloud    | /entrypoint.sh: 137: cannot create /var/www/html/nextcloud-init-sync.lock: Permission denied
nextcloud    | Configuring Redis as session handler
nextcloud    | /entrypoint.sh: 137: cannot create /var/www/html/nextcloud-init-sync.lock: Permission denied
nextcloud    | Configuring Redis as session handler
nextcloud    | /entrypoint.sh: 137: cannot create /var/www/html/nextcloud-init-sync.lock: Permission denied
nextcloud    | Configuring Redis as session handler
nextcloud    | /entrypoint.sh: 137: cannot create /var/www/html/nextcloud-init-sync.lock: Permission denied
nextcloud    | Configuring Redis as session handler
nextcloud    | /entrypoint.sh: 137: cannot create /var/www/html/nextcloud-init-sync.lock: Permission denied

Configuration

Nextcloud

Posting the contents of the files I listed below.

DOCKERFILE: pretty much this, but with minor tweaks

FROM nextcloud:apache
    
RUN set -ex; \
    \
    apt-get update; \
    apt-get install -y --no-install-recommends \
        ffmpeg \
        ghostscript \
        libmagickcore-6.q16-6-extra \
        procps \
        smbclient \
        supervisor \
#       libreoffice \
    ; \
    rm -rf /var/lib/apt/lists/*

RUN set -ex; \
    \
    savedAptMark="$(apt-mark showmanual)"; \
    \
    apt-get update; \
    apt-get install -y --no-install-recommends \
        libbz2-dev \
        libc-client-dev \
        libkrb5-dev \
        libsmbclient-dev \
    ; \
    \
    docker-php-ext-configure imap --with-kerberos --with-imap-ssl; \
    docker-php-ext-install \
        bz2 \
        imap \
    ; \
    pecl install smbclient; \
    docker-php-ext-enable smbclient; \
    \
# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
    apt-mark auto '.*' > /dev/null; \
    apt-mark manual $savedAptMark; \
    ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \
        | awk '/=>/ { so = $(NF-1); if (index(so, "/usr/local/") == 1) { next }; gsub("^/(usr/)?", "", so); print so }' \
        | sort -u \
        | xargs -r dpkg-query --search \
        | cut -d: -f1 \
        | sort -u \
        | xargs -rt apt-mark manual; \
    \
    apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
    rm -rf /var/lib/apt/lists/*

RUN mkdir -p \
    /var/log/supervisord \
    /var/run/supervisord \
;

RUN mkdir -p \
    /var/big_temp_file/ \
;
#changed the line below from www-data:root
RUN chown -R www-data:www-data /var/big_temp_file/ \
;

RUN chmod 755 /var/big_temp_file/ \
;

COPY supervisord.conf /

ENV NEXTCLOUD_UPDATE=1

CMD ["/usr/bin/supervisord", "-c", "/supervisord.conf"]

compose.yaml

services:
  app:
    build: ./
    user: 1002:100
    container_name: nextcloud
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    volumes:
      - ${PATH_TO_APPDATA}/nextcloud:/var/www/html
      - ${PATH_TO_APPDATA}/nextcloud/apps:/var/www/html/custom_apps
      - ${PATH_TO_DATA}/nextcloud/data:/var/www/html/data
      - ${PATH_TO_APPDATA}/nextcloud/config:/var/www/html/config
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
      - ${PATH_TO_APPDATA}/nextcloud/php.ini:/usr/local/etc/php/conf.d/big_upload.ini
      - ${PATH_TO_DATA}/nextcloud/big_temp_file:/var/big_temp_file
      - ${PATH_TO_APPDATA}/nextcloud/redis-session.ini:/usr/local/etc/php/conf.d/redis-session.ini
      # https://github.com/nextcloud/docker/issues/182
      - ${PATH_TO_APPDATA}/nextcloud/remoteip.conf:/etc/apache2/conf-available/remoteip.conf:ro
    restart: unless-stopped
    environment:
      - MYSQL_HOST=db
      - MYSQL_DATABASE=ncdb
      - MYSQL_USER=user
      - MYSQL_PASSWORD=password
      - REDIS_HOST=redis
      - NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.mylan.local
      - APACHE_DISABLE_REWRITE_IP=1
      - TRUSTED_PROXIES=172.16.0.0/24 192.168.1.0/24
      - OVERWRITEHOST=nextcloud.mylan.local
      - overwrite.cli.url=https://nextcloud.mylan.local
      - OVERWRITEPROTOCOL=https
      - TEMP_DIRECTORY=/var/big_temp_file/
      - NEXTCLOUD_DATA_DIR=${PATH_TO_DATA}/nextcloud/data
    ports:
     - 8083:80
    networks:
      - caddy-net
      - nextcloud-net

  db:
    image: mariadb #:10.11
    command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
    user: 1002:100
    restart: unless-stopped
    container_name: ncdb
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      start_period: 10s
      interval: 30s
      timeout: 5s
      retries: 3
    volumes:
      - ${PATH_TO_DATA}/ncdb:/var/lib/mysql
      - /etc/localtime:/etc/localtime:ro
      - /etc/timezone:/etc/timezone:ro
    environment:
      - MYSQL_ROOT_PASSWORD=rootpassword
      - MYSQL_PASSWORD=password
      - MYSQL_DATABASE=ncdb
      - MYSQL_USER=user
    networks:
      - nextcloud-net

  redis:
    image: redis:bookworm
    container_name: ncredis
    restart: unless-stopped
    command:
      - --save ""
    user: 1002:100
    healthcheck:
      test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
      start_period: 10s
      interval: 30s
      retries: 3
      timeout: 3s
    networks:
      - nextcloud-net

  imaginary:
    image: nextcloud/aio-imaginary:latest
    restart: unless-stopped
    user: 1002:100
    expose:
      - "9000"
    depends_on:
      - app  
    cap_add:
      - SYS_NICE
    tmpfs:
      - /tmp
    networks:
      - nextcloud-net
      
networks:
  caddy-net:
    external: true
  nextcloud-net:
    external: true

php.ini - this file is created and located in the system prior to pulling up the compose file

post_max_size = 10G
max_input_time = 7200
max_execution_time = 7200
memory_limit = 1024M
upload_tmp_dir = /var/big_temp_file/
output_buffering = 0

redis-session.ini - this file is created and located in the system prior to pulling up the compose file

session.save_handler = redis
session.save_path = "tcp://redis:6379"
redis.session.locking_enabled = 1
redis.session.lock_retries = -1
redis.session.lock_wait_time = 10000

remoteip.conf - included per the guide here, again created and located prior to pulling up the compose file

#cat remoteip.conf
RemoteIPHeader X-Real-Ip
#RemoteIPTrustedProxy 10.0.0.0/8
#RemoteIPTrustedProxy 172.16.0.0/12
#RemoteIPTrustedProxy 192.168.0.0/16
# https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html
# The RemoteIPInternalProxy directive adds one or more addresses (or address blocks)
# to trust as presenting a valid RemoteIPHeader value of the useragent IP.
# Unlike the RemoteIPTrustedProxy directive, any IP address presented in this header,
# including private intranet addresses, are trusted when passed from these proxies.
RemoteIPInternalProxy 172.16.0.0/24
RemoteIPInternalProxy 192.168.1.0/24

supervisord.conf - a minor tweak on the file from here. Again, created and located appropriately before pulling up the compose file

[supervisord]
user=www-data #included this line due to permission issues 
nodaemon=true
logfile=/var/log/supervisord/supervisord.log
pidfile=/var/run/supervisord/supervisord.pid
childlogdir=/var/log/supervisord/
logfile_maxbytes=50MB                           ; maximum size of logfile before rotation
logfile_backups=10                              ; number of backed up logfiles
loglevel=error
user=www-data

[program:apache2]
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
command=apache2-foreground

[program:cron]
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
command=/cron.sh

I think that about does it as far as information I can include. If anyone has any thoughts or inputs on where I am going wrong or things to try I would gladly accept recommendations. Hopefully I can get this resolved, as I LOVED using nextcloud on my home NAS for files and want to get it going on my new NAS. If I can add any details or expand on anything please let me know.

Thank you.

I would recommend you try to reproduce the issue with standard components, standard docker image and minimum customization. your setup far too complicated to see problem immediately and likely not many run similar setup and could repro it easily. e.g. cron runs different and if the system runs fine without cron you can focus there and sort out the rest of the system.

Regarding your problem - the two guides you reference look similar at the first glance but also have fundamental differences - you can mot mix and match you should choose one and follow it from the start to the end.

this two commands look contrary for me

(I’m not sure if NC image uses the --user argument from service to create www-data)… and definitely this

doesn’t look right. I would recommend you review Linux file permissions concept. x marks the file executable which is definitely not required for config files. right permission is 755 for folders and 640 for files.

I also have no clue if OMV openmediavault has it’s own specialties so please

  • start from scratch and setup basic system without any customizations
  • once this runs, continue adding your desired tweaks one by one
  • if you see issue you focus on troubleshooting the last steps
1 Like

@wwe

This is good advice. I simplified my configuration as you recommended and was able to get an initial working install (no custom image). Still have a few kinks to work out but overall it’s working. Reread your guide, and the community GitHub page for correct usage which helped tremendously.

I will keep working it out and make a post back here if I can get the custom image to work, I think it might be valuable for some users that are in a similar use case as me, where they want full(ish) nextcloud build in docker, served up locally behind a reverse proxy.

Thank you. Will reply back if I get stuck or if I have a solution.

2 Likes