Metadata not working

I’ve upgraded my Docker Seafile 12 to 13 and wanted to give the metadata server a try. It all seems fine, but seafevents.log does not states anything related to metadata. On the webinterface I now get the option to enable extensive properties, but when I try to do so I get Internal server error. seahub.log gives this:

[2026-07-21 11:40:53] [ERROR] seahub.repo_metadata.apis:167 put HTTPConnectionPool(host='127.0.0.1', port=8889): Max retries exceeded with url: /add-init-metadata-task?repo_id=8779d765-e6d4-463b-9e1c-c0673f9c0d38&username=***%40outlook.com (Caused by NewConnectionError("HTTPConnection(host='127.0.0.1', port=8889): Failed to establish a new connection: [Errno 111] Connection refused"))

[2026-07-21 11:40:53] [ERROR] django.request:253 log_response Internal Server Error: /api/v2.1/repos/8779d765-e6d4-463b-9e1c-c0673f9c0d38/metadata/

To me it seems the internal meta data server is not started? I’m running everything inside Portainer in a single stack and have an external Caddy as a reverse proxy. Everything else seems to work fine.

This is my compose file in Portainer:

services:
  db:
    image: ${SEAFILE_DB_IMAGE:-mariadb:10.11}
    container_name: seafile-mysql
    restart: unless-stopped
    environment:
      - MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
      - MYSQL_LOG_CONSOLE=true
      - MARIADB_AUTO_UPGRADE=1
    volumes:
      - "${SEAFILE_MYSQL_VOLUME:-/opt/seafile-mysql/db}:/var/lib/mysql"
    networks:
      - caddy-network
    healthcheck:
      test:
        [
          "CMD",
          "/usr/local/bin/healthcheck.sh",
          "--connect",
          "--mariadbupgrade",
          "--innodb_initialized",
        ]
      interval: 20s
      start_period: 30s
      timeout: 5s
      retries: 10

  redis:
    image: ${SEAFILE_REDIS_IMAGE:-redis}
    container_name: seafile-redis
    restart: unless-stopped
    command:
      - /bin/sh
      - -c
      - redis-server --requirepass "$$REDIS_PASSWORD"
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD:-}
    networks:
      - caddy-network

  seafile:
    image: ${SEAFILE_IMAGE:-seafileltd/seafile-mc:13.0-latest}
    container_name: seafile
    restart: unless-stopped
    # ports:
    #   - "80:80"
    volumes:
      - ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared
    environment:
      - SEAFILE_MYSQL_DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
      - SEAFILE_MYSQL_DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
      - SEAFILE_MYSQL_DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
      - SEAFILE_MYSQL_DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - INIT_SEAFILE_MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}
      - SEAFILE_MYSQL_DB_CCNET_DB_NAME=${SEAFILE_MYSQL_DB_CCNET_DB_NAME:-ccnet_db}
      - SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=${SEAFILE_MYSQL_DB_SEAFILE_DB_NAME:-seafile_db}
      - SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=${SEAFILE_MYSQL_DB_SEAHUB_DB_NAME:-seahub_db}
      - TIME_ZONE=${TIME_ZONE:-Etc/UTC}
      - INIT_SEAFILE_ADMIN_EMAIL=${INIT_SEAFILE_ADMIN_EMAIL:-me@example.com}
      - INIT_SEAFILE_ADMIN_PASSWORD=${INIT_SEAFILE_ADMIN_PASSWORD:-asecret}
      - SEAFILE_SERVER_HOSTNAME=${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      - SEAFILE_SERVER_PROTOCOL=${SEAFILE_SERVER_PROTOCOL:-http}
      - SITE_ROOT=${SITE_ROOT:-/}
      - NON_ROOT=${NON_ROOT:-false}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - SEAFILE_LOG_TO_STDOUT=${SEAFILE_LOG_TO_STDOUT:-false}
      - ENABLE_GO_FILESERVER=${ENABLE_GO_FILESERVER:-true}
      - ENABLE_SEADOC=${ENABLE_SEADOC:-true}
      - SEADOC_SERVER_URL=${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}/sdoc-server
      - CACHE_PROVIDER=${CACHE_PROVIDER:-redis}
      - REDIS_HOST=${REDIS_HOST:-redis}
      - REDIS_PORT=${REDIS_PORT:-6379}
      - REDIS_PASSWORD=${REDIS_PASSWORD:-}
      - MEMCACHED_HOST=${MEMCACHED_HOST:-memcached}
      - MEMCACHED_PORT=${MEMCACHED_PORT:-11211}
      - ENABLE_NOTIFICATION_SERVER=${ENABLE_NOTIFICATION_SERVER:-false}
      - INNER_NOTIFICATION_SERVER_URL=${INNER_NOTIFICATION_SERVER_URL:-http://notification-server:8083}
      - NOTIFICATION_SERVER_URL=${NOTIFICATION_SERVER_URL:-${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}/notification}
      - ENABLE_SEAFILE_AI=${ENABLE_SEAFILE_AI:-false}
      - ENABLE_FACE_RECOGNITION=${ENABLE_FACE_RECOGNITION:-false}
      - SEAFILE_AI_SERVER_URL=${SEAFILE_AI_SERVER_URL:-http://seafile-ai:8888}
      - SEAFILE_AI_SECRET_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - MD_FILE_COUNT_LIMIT=${MD_FILE_COUNT_LIMIT:-100000}
    labels:
      # caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      # caddy.reverse_proxy: "{{upstreams 80}}"
      caddy_0: https://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      caddy_0.reverse_proxy: "{{upstreams 80}}"
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:80 || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - caddy-network

  notification-server:
    image: ${NOTIFICATION_SERVER_IMAGE:-seafileltd/notification-server:13.0-latest}
    container_name: notification-server
    restart: always
    volumes:
      - ${SEAFILE_VOLUME:-/opt/seafile-data}/seafile/logs:/shared/seafile/logs
    # ports:
    #   - "8083:8083"
    environment:
      - SEAFILE_MYSQL_DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
      - SEAFILE_MYSQL_DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
      - SEAFILE_MYSQL_DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
      - SEAFILE_MYSQL_DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - SEAFILE_MYSQL_DB_CCNET_DB_NAME=${SEAFILE_MYSQL_DB_CCNET_DB_NAME:-ccnet_db}
      - SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=${SEAFILE_MYSQL_DB_SEAFILE_DB_NAME:-seafile_db}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - SEAFILE_LOG_TO_STDOUT=${SEAFILE_LOG_TO_STDOUT:-false}
      - NOTIFICATION_SERVER_LOG_LEVEL=${NOTIFICATION_SERVER_LOG_LEVEL:-info}
    labels:
      # caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      # caddy.1_handle_path: "/notification*"
      # caddy.1_handle_path.0_rewrite: "* {uri}"
      # caddy.1_handle_path.1_reverse_proxy: "{{upstreams 8083}}"
      caddy: https://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      caddy.1_handle_path: "/notification*"
      caddy.1_handle_path.0_rewrite: "* {uri}"
      caddy.1_handle_path.1_reverse_proxy: "{{upstreams 8083}}"
    depends_on:
      db:
        condition: service_healthy
      seafile:
        condition: service_healthy
    networks:
      - caddy-network

  seafile-md-server:
    image: ${MD_IMAGE:-seafileltd/seafile-md-server:13.0-latest}
    container_name: seafile-md-server
    restart: unless-stopped
    volumes:
      - ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared
    #ports:
      # - ${MD_PORT:-8084}:${MD_PORT:-8084}
    environment:
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - SEAFILE_MYSQL_DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
      - SEAFILE_MYSQL_DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
      - SEAFILE_MYSQL_DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
      - SEAFILE_MYSQL_DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=${SEAFILE_MYSQL_DB_SEAFILE_DB_NAME:-seafile_db}
      - SEAFILE_LOG_TO_STDOUT=${SEAFILE_LOG_TO_STDOUT:-false}
      - MD_PORT=${MD_PORT:-8084}
      - MD_LOG_LEVEL=${MD_LOG_LEVEL:-info}
      - MD_MAX_CACHE_SIZE=${MD_MAX_CACHE_SIZE:-1GB}
      - MD_CHECK_UPDATE_INTERVAL=${MD_CHECK_UPDATE_INTERVAL:-30m}
      - MD_FILE_COUNT_LIMIT=${MD_FILE_COUNT_LIMIT:-100000}
      - SEAF_SERVER_STORAGE_TYPE=${SEAF_SERVER_STORAGE_TYPE:-}
      - MD_STORAGE_TYPE=${MD_STORAGE_TYPE:-disk}
      - S3_COMMIT_BUCKET=${S3_COMMIT_BUCKET:-}
      - S3_FS_BUCKET=${S3_FS_BUCKET:-}
      - S3_BLOCK_BUCKET=${S3_BLOCK_BUCKET:-}
      - S3_MD_BUCKET=${S3_MD_BUCKET:-}
      - S3_HOST=${S3_HOST:-}
      - S3_AWS_REGION=${S3_AWS_REGION:-}
      - S3_USE_HTTPS=${S3_USE_HTTPS:-true}
      - S3_PATH_STYLE_REQUEST=${S3_PATH_STYLE_REQUEST:-false}
      - S3_KEY_ID=${S3_KEY_ID:-}
      - S3_SECRET_KEY=${S3_SECRET_KEY:-}
      - S3_USE_V4_SIGNATURE=${S3_USE_V4_SIGNATURE:-true}
      - S3_SSE_C_KEY=${S3_SSE_C_KEY:-}
      - MD_CEPH_CONFIG=${MD_CEPH_CONFI:-} 
      - MD_CEPH_POOL=${MD_CEPH_POOL:-}
      - MD_CEPH_CLIENT_ID=${MD_CEPH_CLIENT_ID:-}
      - CACHE_PROVIDER=${CACHE_PROVIDER:-redis}
      - REDIS_HOST=${REDIS_HOST:-redis}
      - REDIS_PORT=${REDIS_PORT:-6379}
      - REDIS_PASSWORD=${REDIS_PASSWORD:-}
    depends_on:
      db:
        condition: service_healthy
      seafile:
        condition: service_healthy
    networks:
      - caddy-network


networks:
  caddy-network:
    external: true

The error occurs because the Metadata Server is a new, separate component in Seafile 13 that must be deployed as an additional container. It is not bundled within the main seafile-mc image.

To fix this, you need to add the md-server service to your Docker Compose file and configure Seahub to communicate with it.

1. Add the Metadata Server service

Add the following to your services section in your Portainer stack:

  md-server:
    image: seafileltd/seafile-md-server:13.0-latest
    container_name: seafile-md-server
    restart: unless-stopped
    volumes:
      - ${SEAFILE_VOLUME:-/opt/seafile-data}:/shared
    environment:
      - TIME_ZONE=${TIME_ZONE:-Etc/UTC}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - REDIS_HOST=${REDIS_HOST:-redis}
      - REDIS_PORT=${REDIS_PORT:-6379}
      - REDIS_PASSWORD=${REDIS_PASSWORD:-}
      - SEAFILE_SERVER_HOSTNAME=${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      - SEAFILE_SERVER_PROTOCOL=${SEAFILE_SERVER_PROTOCOL:-http}
    networks:
      - caddy-network

2. Update Seafile container environment

In your existing seafile service environment variables, ensure you have these set so Seahub knows where to find the metadata server:

      - ENABLE_METADATA_MANAGEMENT=true
      - METADATA_SERVER_URL=http://md-server:8084

(Note: Use the service name md-server defined in step 1. The default port is 8084).

3. Apply changes

Update the stack in Portainer. Once the new container is running, Seahub should be able to connect to the metadata server, and you’ll be able to enable extensive properties without the “Internal server error”.

For more details, you can refer to the official documentation:
Seafile Admin Manual - Metadata Server

I thought I had disabled NON_ROOT but it was still enabled and I had set root as owner of all seafile-data files. This caused some issues. After setting NON_ROOT back to false everything works. However, on a 2TB library of photos and videos, it seems to be extermely slow when enabling the extensive properties, is this normal?

Yes, it is normal for the initial process to be slow, especially on a large library.

When you enable extensive properties, the Metadata Server must perform a full history traversal and extract information (such as dimensions for photos and videos) for every file. This is handled as a background “slow task” pipeline.

A few things to keep in mind regarding performance in Seafile 13.0:

  • File Count Limit: The metadata feature is currently recommended for libraries with fewer than 100,000 files. The default limit is controlled by MD_FILE_COUNT_LIMIT, which is set to 100,000. If your 2TB library exceeds this count, the initialization may take a long time or skip files beyond the limit.
  • Monitoring Progress: You can monitor the background task progress by checking the seafevents.log (look for slow_task_handler entries) or by inspecting the logs of the seafile-md-server container.
  • Future Optimizations: Further performance improvements for libraries with more than 100,000 files are planned for Seafile 14.0.

For more technical details on how the metadata server handles these tasks, you can refer to the Metadata Server documentation.