Setup fails with "Access denied for user 'root'@'localhost' (using password: NO)"

Hi all,

I’m trying to set up seafile CE (v13) on my OMV server. Unfortunately, the setup of the seafile-mysql container fails, with these messages at the end of the log:

seafile-mysql  | 2026-06-21 22:04:44 0 [Note] mariadbd: ready for connections.
seafile-mysql  | Version: '10.11.18-MariaDB-ubu2204'  socket: '/run/mysqld/mysqld.sock'  port: 3306  mariadb.org binary distribution
seafile-mysql  | 2026-06-21 22:04:58 3 [Warning] Access denied for user 'root'@'localhost' (using password: NO)
seafile-mysql  | 2026-06-21 22:04:58 4 [Warning] Access denied for user 'root'@'::1' (using password: NO)

I essentially copied the .env file from the official website with very few modifications, so I’m very confused as to what is going on.

Checks I have done:

  • Verified that the .env file contains the lines SEAFILE_MYSQL_DB_PASSWORD=PASSWORD and INIT_SEAFILE_MYSQL_ROOT_PASSWORD=ROOT_PASSWORD

  • Verified that the db service in the compose yml contains the value MYSQL_ROOT_PASSWORD=${INIT_SEAFILE_MYSQL_ROOT_PASSWORD:-}

  • Following suggestions in another topic (called Docker update v13 database access deny), I verified environment variables from within the container, see below. However, note that unlike in the linked post, there is no SEAFILE_MYSQL_DB_PASSWORDvariable, its simply MYSQL_ROOT_PASSWORD=ROOT_PASSWORDhere.

    docker exec -it seafile-mysql bash
    root@00940df780fe:/# env
    HOSTNAME=00940df780fe
    MYSQL_LOG_CONSOLE=true
    PWD=/
    MYSQL_ROOT_PASSWORD=ROOT_PASSWORD
    HOME=/root
    LANG=C.UTF-8
    LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pesd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
    MARIADB_AUTO_UPGRADE=1
    MARIADB_VERSION=1:10.11.18+maria~ubu2204
    GOSU_VERSION=1.19
    TERM=xterm
    SHLVL=1
    PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    _=/usr/bin/env
    
  • I tried additionally passing SEAFILE_MYSQL_DB_PASSWORD=PASSWORDbut that didn’t solve the issue.

Any further suggestions? Thanks for the help!

Have you modified the default yml file?

And have you changed the password in your .env file after a previous failed attempt?

If this is a fresh installation and you changed the password in your .env file after a previous failed attempt, the database may have already been initialized with a different password (or no password). MariaDB only uses the MYSQL_ROOT_PASSWORD variable during the very first run when the data directory is empty.

To ensure a clean start:

  1. Stop the containers: docker compose down
  2. Warning: This will delete all existing data in the DB. Remove the database volume directory (default is /opt/seafile-mysql/db).
  3. Restart the setup: docker compose up -d
1 Like

Thanks for the reply and the suggestions.

  1. Yes, I modified the yml files, combining the 3 files into one. That’s because I prefer to run docker through my server’s web GUI, and it only accepts a single yml and single env file per stack. I could run it through CLI though.
  2. other than that, I originally set different initial passwords. That failed, so I wiped all the volumes (including seafile-mysql/db) like you suggested, and tried again with the default passwords. The only things I changed now are the variables BASIC_STORAGE_PATH, SEAFILE_SERVER_HOSTNAME and JWT_PRIVATE_KEY, as well as the port caddy uses (changed to 8080, since 80 is in use already).

I attached the files below. (I realize that I’ll have to change sensitive info later.)

Could this somehow be related to what user is running docker?

.env
#################################
# Docker compose configurations #
#################################
COMPOSE_FILE='compose.yml'
COMPOSE_PATH_SEPARATOR=','

## Images
SEAFILE_IMAGE=seafileltd/seafile-mc:13.0-latest
SEAFILE_DB_IMAGE=mariadb:10.11
SEAFILE_REDIS_IMAGE=redis
SEAFILE_CADDY_IMAGE=lucaslorentz/caddy-docker-proxy:2.12-alpine
SEADOC_IMAGE=seafileltd/sdoc-server:2.0-latest
NOTIFICATION_SERVER_IMAGE=seafileltd/notification-server:13.0-latest
MD_IMAGE=seafileltd/seafile-md-server:13.0-latest

## Persistent Storage
BASIC_STORAGE_PATH=/srv/dev-disk-by-uuid-0E5C40F15C40D4DD/seafile-13
SEAFILE_VOLUME=$BASIC_STORAGE_PATH/seafile-data
SEAFILE_MYSQL_VOLUME=$BASIC_STORAGE_PATH/seafile-mysql/db
SEAFILE_CADDY_VOLUME=$BASIC_STORAGE_PATH/seafile-caddy
SEADOC_VOLUME=$BASIC_STORAGE_PATH/seadoc-data

#################################
#      Startup parameters       #
#################################
SEAFILE_SERVER_HOSTNAME=192.168.178.100
SEAFILE_SERVER_PROTOCOL=http
TIME_ZONE=Etc/UTC
JWT_PRIVATE_KEY=9lOxCidhJQSKUGWjXp3noqWT5ngJ7eizLUKPQn+XSJw=

#####################################
# Third-party service configuration #
#####################################

## Database
SEAFILE_MYSQL_DB_HOST=db
SEAFILE_MYSQL_DB_USER=seafile
SEAFILE_MYSQL_DB_PASSWORD=PASSWORD
SEAFILE_MYSQL_DB_CCNET_DB_NAME=ccnet_db
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=seafile_db
SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=seahub_db

## Cache
CACHE_PROVIDER=redis # or memcached

### Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=

### Memcached
MEMCACHED_HOST=memcached
MEMCACHED_PORT=11211

######################################
#        Initial variables           #
# (Only valid in first-time startup) #
######################################

## Database root password, Used to create Seafile users
INIT_SEAFILE_MYSQL_ROOT_PASSWORD=ROOT_PASSWORD

## Seafile admin user
INIT_SEAFILE_ADMIN_EMAIL=me@example.com
INIT_SEAFILE_ADMIN_PASSWORD=asecret

############################################
# Additional configurations for extensions #
############################################

## SeaDoc service
ENABLE_SEADOC=true

## Notification
ENABLE_NOTIFICATION_SERVER=false
NOTIFICATION_SERVER_URL=

## Seafile AI
ENABLE_SEAFILE_AI=false
ENABLE_FACE_RECOGNITION=false
SEAFILE_AI_LLM_TYPE=openai
SEAFILE_AI_LLM_URL=
SEAFILE_AI_LLM_KEY= # your llm key
SEAFILE_AI_LLM_MODEL=gpt-4o-mini

## Metadata server
MD_FILE_COUNT_LIMIT=100000

compose.yml
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:-}
      - SEAFILE_MYSQL_DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD}
      - MYSQL_LOG_CONSOLE=true
      - MARIADB_AUTO_UPGRADE=1
    volumes:
      - "${SEAFILE_MYSQL_VOLUME:-/opt/seafile-mysql/db}:/var/lib/mysql"
    networks:
      - seafile-net
    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:
      - seafile-net

  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}}"
    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:
      - seafile-net
  caddy:
    image: ${SEAFILE_CADDY_IMAGE:-lucaslorentz/caddy-docker-proxy:2.12-alpine}
    restart: unless-stopped
    container_name: seafile-caddy
    ports:
      - 8080:80
      - 443:443
    environment:
      - CADDY_INGRESS_NETWORKS=seafile-net
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ${SEAFILE_CADDY_VOLUME:-/opt/seafile-caddy}:/data/caddy
    networks:
      - seafile-net
    healthcheck:
      test: ["CMD-SHELL", "curl --fail http://localhost:2019/metrics || exit 1"]
      start_period: 20s
      interval: 20s
      timeout: 5s
      retries: 3
  seadoc:
    image: ${SEADOC_IMAGE:-seafileltd/sdoc-server:2.0-latest}
    container_name: seadoc
    restart: unless-stopped
    volumes:
      - ${SEADOC_VOLUME:-/opt/seadoc-data/}:/shared
    # ports:
    #   - "80:80"
    environment:
      - DB_HOST=${SEAFILE_MYSQL_DB_HOST:-db}
      - DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
      - DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
      - DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
      - DB_NAME=${SEADOC_MYSQL_DB_NAME:-${SEAFILE_MYSQL_DB_SEAHUB_DB_NAME:-seahub_db}}
      - TIME_ZONE=${TIME_ZONE:-Etc/UTC}
      - JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
      - NON_ROOT=${NON_ROOT:-false}
      - SEAHUB_SERVICE_URL=${SEAFILE_SERVICE_URL:-http://seafile}
    labels:
      caddy: ${SEAFILE_SERVER_PROTOCOL:-http}://${SEAFILE_SERVER_HOSTNAME:?Variable is not set or empty}
      caddy.1_handle_path: "/socket.io/*"
      caddy.1_handle_path.0_rewrite: "* /socket.io{uri}"
      caddy.1_handle_path.1_reverse_proxy: "{{upstreams 80}}"
      caddy.2_handle_path: "/sdoc-server/*"
      caddy.2_handle_path.0_rewrite: "* {uri}"
      caddy.2_handle_path.1_reverse_proxy: "{{upstreams 80}}"
    depends_on:
      db:
        condition: service_healthy
    networks:
      - seafile-net
networks:
  seafile-net:
    name: seafile-net

Here is an analysis by AI:

The error message Access denied for user 'root'@'localhost' (using password: NO) in the seafile-mysql logs is a strong indicator that the healthcheck script defined in the db service is attempting to connect to MariaDB as root without providing a password.

In the provided compose.yml, the db service has a healthcheck using /usr/local/bin/healthcheck.sh. When MYSQL_ROOT_PASSWORD is set, this script may fail to authenticate if it doesn’t correctly pick up the password from the environment or if it tries to connect via TCP (as indicated by the ::1 warning) where the unix_socket plugin doesn’t apply.


The official yml also use /usr/local/bin/healthcheck.sh for health check. But I don’t know why it cannot work in your case.

Thank you for this update. I’m tracking down the issue. Indeed, it seems that the health check script is the issue: from within the container, I can log using mysql -u root -p and the password in $MYSQL_ROOT_PASSWORD. So at least we know that the DB is initialized correctly. Running the health check from within the container gives me this:

bash /usr/local/bin/healthcheck.sh --connect
Warning: World-writable config file '/var/lib/mysql/.my-healthcheck.cnf' is ignored
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
Unknown error Warning: World-writable config file '/var/lib/mysql/.my-healthcheck.cnf' is ignored
ERROR 1045 (28000): Access denied for user 'root'@'::1' (using password: NO)
healthcheck connect failed

Perhaps it’s this config file that causes the issue. AI suggests changing the access rights. I’ll see what I can do about that, and come back with an update

I have solved the issue. The problem was that my data folders were located on an NTFS file system, which doesn’t support the typical Linux file permissions. Setting everything up on an ext4 partition solved the problem.