External Storage Mounting Error?

Support intro

Nextcloud version : 30.0.1.2 (docker)
Operating system and version: Debian 12
Apache or nginx version: 2.12.1 (docker)
PHP version: 8.2.25

I mounted my ntfs drive in nextcloud, but whenever I browse in Files I got an error in logging (shown below):

Exception
OCA\Files_External\Service\DBConfigService::getMountById(): Argument #1 ($mountId) must be of type int, string given, called in /var/www/html/apps/files_external/lib/Service/StoragesService.php on line 138 in file '/var/www/html/apps/files_external/lib/Service/DBConfigService.php' line 48

My ntfs drive permission is set as 777. I do see the files from nextcloud, so I’m not sure what it doesn’t like.

Another error from Nextcloud memories might be related. It says it can’t index the folder I mounted even thought it display all photos correctly (log error shown below).

Failed to index folder /tamashika/files/onetouch5t/LocalStorage/Photos: Local storage path does not exist "/onetouch5t/LocalStorage/Photos/"

Here is a picture showing how I mounted my folders in ntfs drive:

Could someone tell me what the error means and how to fix it? Thanks.

My config.php file:
<?php
$CONFIG = array (
  'memcache.local' => '\\OC\\Memcache\\APCu',
  'apps_paths' =>
  array (
    0 =>
    array (
      'path' => '/var/www/html/apps',
      'url' => '/apps',
      'writable' => false,
    ),
    1 =>
    array (
      'path' => '/var/www/html/custom_apps',
      'url' => '/custom_apps',
      'writable' => true,
    ),
  ),
  'memcache.distributed' => '\\OC\\Memcache\\Redis',
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'redis' =>
  array (
    'host' => 'redis',
    'password' => '',
    'port' => 6379,
  ),
  'upgrade.disable-web' => true,
  'instanceid' => 'removed',
  'passwordsalt' => 'removed',
  'secret' => 'removed',
  'trusted_domains' =>
  array (
    0 => 'removed',
  ),
  'datadirectory' => '/var/www/html/data',
  'dbtype' => 'sqlite3',
  'version' => '30.0.1.2',
  'overwrite.cli.url' => 'https://removed',
  'installed' => true,
  'memories.db.triggers.fcu' => true,
  'memories.exiftool' => '/var/www/html/custom_apps/memories/bin-ext/exiftool-aarch64-musl',
  'memories.vod.path' => '/var/www/html/custom_apps/memories/bin-ext/go-vod-aarch64',
  'preview_max_x' => 2048,
  'preview_max_y' => 2048,
  'jpeg_quality' => '60',
  'maintenance' => false,
  'loglevel' => 3,
  'enabledPreviewProviders' =>
  array (
  ),
);

Please post the full stack trace (raw log entry).

I do see the files from nextcloud, so I’m not sure what it doesn’t like.

Can you access (open/etc) the files as well successfully? From within the Nextcloud web UI I mean.

Please post the full stack trace (raw log entry).

nextcloud.log

Can you access (open/etc) the files as well successfully? From within the Nextcloud web UI I mean.

Yes. I have opened pictures, played music files, and opened some text files to check this.

The log I provided has my IP removed.
It is exported before I opened the files, so it doesn’t have the action that I opened my files. Let me know you have to have those. I’ll reupload the log.

Thanks.

How are you mounting the volumes on the underlying host and with the Docker container?

Can you post your Compose file?

The storage drive is ntfs, and auto mounted using fstab:
UUID=removed /media/onetouch5t ntfs uid=82,gid=82,auto,nofail,rw 0 0
image

Compose File
networks:
  default:
    driver: bridge
    ipam:
      driver: default
  nextcloud_net:
    driver: bridge
    internal: true
    ipam:
      driver: default

x-nextcloud-common-envVar:
  &nextcloud-common
  MYSQL_PASSWORD=removed
  MYSQL_DATABASE=nextcloud
  MYSQL_USER=nextcloud

services:
  portainer-ce:
    container_name: portainer-ce
    image: portainer/portainer-ce
    restart: unless-stopped
    ports:
    - "8000:8000"
    - "9000:9000"
    # HTTPS
    - "9443:9443"
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - ./volumes/portainer-ce/data:/data

  nextcloud:
    image: nextcloud:fpm-alpine
    volumes:
    # Vol_nextcloud_html
    - ./volumes/nextcloud/html:/var/www/html:z
    - /media/onetouch5t/LocalStorage:/onetouch5t/LocalStorage
    container_name: nextcloud
    restart: unless-stopped
    environment:
    - <<=*nextcloud-common
    - TZ=${TZ:-Etc/UTC}
    - MYSQL_HOST=nextcloud_db
    - REDIS_HOST=redis
    depends_on:
    - nextcloud_db
    - redis
    networks:
    - default
    - nextcloud_net

  nextcloud_db:
    image: mariadb:10.6
    command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
    volumes:
    - ./volumes/nextcloud/db:/var/lib/mysql:Z
    container_name: nextcloud_db
    restart: unless-stopped
    environment:
    - <<=*nextcloud-common
    - MYSQL_ROOT_PASSWORD=removed
    networks:
    - nextcloud_net

  redis:
    container_name: nextcloud_redis
    image: redis:alpine
    restart: unless-stopped
    networks:
      - nextcloud_net

  cron:
    container_name: nextcloud_cron
    image: nextcloud:fpm-alpine
    restart: unless-stopped
    volumes:
      # Vol_nextcloud_html
      - ./volumes/nextcloud/html:/var/www/html:z
    entrypoint: /cron.sh
    depends_on:
      - nextcloud_db
      - redis
    networks:
      - nextcloud_net

  nginxProxyManager:
    image: 'jc21/nginx-proxy-manager:latest'
    container_name: nginxProxyManager
    restart: unless-stopped
    ports:
      # These ports are in format :
    - '80:80'   # Public HTTP Port
    - '443:443'   # Public HTTPS Port
    - '81:81'   # Admin Web Port
      # Add any other Stream port you want to expose
      # - '21:21' # FTP
    # Uncomment the next line if you uncomment anything in the section
    # environment:
      # Uncomment this if you want to change the location of
      # the SQLite DB file within the container
      # DB_SQLITE_FILE: "/data/database.sqlite"
      # Uncomment this if IPv6 is not enabled on your host
      # DISABLE_IPV6: 'true'
    environment:
      REAL_IP_HEADER: "X-Real-IP"
      TRUSTED_PROXIES: "172.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16"
    volumes:
    - ./volumes/nginxProxyManager/data:/data
    - ./volumes/nginxProxyManager/letsencrypt:/etc/letsencrypt
    # Vol_nextcloud_html
    - ./volumes/nextcloud/html:/var/www/html:ro,z
    networks:
    - default

  duckdns:
    environment:
      TOKEN: removed
      SUBDOMAINS: removed
      PUID: 1000
      PGID: 1000
    container_name: duckdns
    build: https://github.com/ukkopahis/docker-duckdns.git
    network_mode: host
    restart: unless-stopped

Might worth to mention that I had apline installed before. The id has already been changed to 82.
image

nginx config
# Path to the root of your installation
root /var/www/html;
# set max upload size
client_max_body_size 512M;
client_body_timeout 300s;
fastcgi_buffers 64 4K;
# Enable gzip but do not remove ETag headers
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
# Pagespeed is not supported by Nextcloud, so if your server is built
# with the `ngx_pagespeed` module, uncomment this line to disable it.
#pagespeed off;
# The settings allows you to optimize the HTTP2 bandwidth.
# See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/
# for tuning hints
client_body_buffer_size 512k;
# HTTP response headers borrowed from Nextcloud `.htaccess`
add_header Referrer-Policy                   "no-referrer"       always;
add_header X-Content-Type-Options            "nosniff"           always;
add_header X-Download-Options                "noopen"            always;
add_header X-Frame-Options                   "SAMEORIGIN"        always;
add_header X-Permitted-Cross-Domain-Policies "none"              always;
add_header X-Robots-Tag                      "noindex, nofollow" always;
add_header X-XSS-Protection                  "1; mode=block"     always;

# Remove X-Powered-By, which is an information leak
fastcgi_hide_header X-Powered-By;

# Set .mjs and .wasm MIME types
# Either include it in the default mime.types list
# and include that list explicitly or add the file extension
# only for Nextcloud like below:
include mime.types;
types {
text/javascript js mjs;

}
# Specify how to handle directories -- specifying `/index.php$request_uri`
# here as the fallback means that Nginx always exhibits the desired behaviour
# when a client requests a path that corresponds to a directory that exists
# on the server. In particular, if that directory contains an index.php file,
# that file is correctly served; if it doesn't, then the request is passed to
# the front-end controller. This consistent behaviour means that we don't need
# to specify custom rules for certain paths (e.g. images and other assets,
# `/updater`, `/ocs-provider`), and thus
# `try_files $uri $uri/ /index.php$request_uri`
# always provides the desired behaviour.
index index.php index.html /index.php$request_uri;
# Rule borrowed from `.htaccess` to handle Microsoft DAV clients
location = / {
    if ( $http_user_agent ~ ^DavClnt ) {
        return 302 /remote.php/webdav/$is_args$args;
    }
}
location = /robots.txt {
    allow all;
    log_not_found off;
    access_log off;
}
# Make a regex exception for `/.well-known` so that clients can still
# access it despite the existence of the regex rule
# `location ~ /(\.|autotest|...)` which would otherwise handle requests
# for `/.well-known`.
location ^~ /.well-known {
    # The rules in this block are an adaptation of the rules
    # in `.htaccess` that concern `/.well-known`.
    location = /.well-known/carddav { return 301 /remote.php/dav/; }
    location = /.well-known/caldav  { return 301 /remote.php/dav/; }
    location /.well-known/acme-challenge    { try_files $uri $uri/ =404; }
    location /.well-known/pki-validation    { try_files $uri $uri/ =404; }
    # Let Nextcloud's API for `/.well-known` URIs handle all other
    # requests by passing them to the front-end controller.
    return 301 /index.php$request_uri;
}
# Rules borrowed from `.htaccess` to hide certain paths from clients
location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)  { return 404; }
location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console)                { return 404; }
# Ensure this block, which passes PHP files to the PHP process, is above the blocks
# which handle static assets (as seen below). If this block is not declared first,
# then Nginx will encounter an infinite rewriting loop when it prepends `/index.php`
# to the URI, resulting in a HTTP 500 error response.
location ~ \.php(?:$|/) {
    # Required for legacy support
    rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri;
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    set $path_info $fastcgi_path_info;
    try_files $fastcgi_script_name =404;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $path_info;
    #fastcgi_param HTTPS on;
    fastcgi_param modHeadersAvailable true;         # Avoid sending the security headers twice
    fastcgi_param front_controller_active true;     # Enable pretty urls
    fastcgi_pass nextcloud:9000;
    fastcgi_intercept_errors on;
    fastcgi_request_buffering off;
    fastcgi_max_temp_file_size 0;
}

location ~ \.(?:css|js|svg|gif)$ {
    try_files $uri /index.php$request_uri;
    expires 6M;         # Cache-Control policy borrowed from `.htaccess`
    access_log off;     # Optional: Don't log access to assets
}
location ~ \.woff2?$ {
    try_files $uri /index.php$request_uri;
    expires 7d;         # Cache-Control policy borrowed from `.htaccess`
    access_log off;     # Optional: Don't log access to assets
}
# Rule borrowed from `.htaccess`
location /remote {
    return 301 /remote.php$request_uri;
}
location / {
    try_files $uri $uri/ /index.php$request_uri;
}

Do I need to create a “onetouch5t/LocalStorage” folder in nextcloud before mounting it in External Storage app?
I tried to just mount something on the same hard drive without the “/” in this external storage app but I still have the same issue.
Not sure what’s the right way of using it…

I disabled my cron container and run crontab from my host (pi4) and now the issue seems to be gone…

Your cron container needs to have exactly the same volumes mounted on it as your app (nextcloud) container.

Do I need to share the volume (with :z)
like this?

What about nginx? Does it need to have exactly the same volume mounted in my app (nextcloud) too?

Ok for future reference, I found my answer regarding to my first question (post below). The cron job has to have the same volume as the app and it doesn’t seem that I need to make them share the volume (with :z).

I can’t find anything regarding to the nignx, but I don’t think we need to share the same volume since it is not documented anywhere.

When using the FPM-based image, the web server container needs at least read-only access to the same volumes (with some exceptions for certain file structures). See example here.