Connecting Seafile Client 9.0.19 to Seafile 13 CE - network error: Operation cancelled

Hi

I freshly installed Seafile 13 CE on. Debian 13 server.

I was able to connect SeaDrive Client to rhe Server.

When I try and connect a Seafile Client 9.0.19, then I get error message after a whle:

Network error: Operation cancelled

I found some tips that it could be that the time setting is incorrect, but I believe this sin’t the case here and the timectl is running on the server.

Does someone have an idea what tis could be?

Edit: I was able to connect an ipad with the ios app.

It seems like the sync client is encountering a timeout or a network abort during the connection process. Since SeaDrive and the iOS app are working, the server itself is likely functional.

To narrow this down, please try the following:

  1. Check Client Logs: Look into the applet.log file on the machine where the Seafile Client is installed. You can usually find this in the logs folder within the Seafile installation directory or your user profile. This might contain a more specific error code.
  2. IPv6 vs. IPv4: Sometimes the client attempts to connect via IPv6 while the server or proxy only listens on IPv4 (or vice versa). If your server is on a local network, try connecting via the IP address instead of the hostname to see if DNS resolution is causing the hang.
  3. Proxy Settings: Check if there is a proxy configured in the Seafile Client settings (Settings → Network). Try setting it to “No proxy” explicitly.
  4. Debian 13 Compatibility: Since Debian 13 is very new and uses OpenSSL 3.x, there might be a compatibility issue with how the Qt-based client handles the TLS handshake. Ensure your client machine’s OS is fully updated.

If the logs show a specific error like “TLS initialization failed” or a specific HTTP status code, please share that here.

Hello @daniel.pan

Thanks a lot for your help already.

  1. applet.log: I checked the log file and this is the error I get when trying to connect with the seafile sync client:

    [08/07/26 08:55:00]beginResetModel called on RepoTreeModel(0xacc82a700) without calling endResetModel first
    [08/07/26 08:55:00]beginResetModel called on RepoFilterProxyModel(0xacba22a80) without calling endResetModel first
    [08/07/26 08:55:00]endResetModel called on RepoTreeModel(0xacc82a700) without calling beginResetModel first
    [08/07/26 08:55:00]endResetModel called on RepoFilterProxyModel(0xacba22a80) without calling beginResetModel first
    [08/07/26 08:55:16]Network Error:
    SSL handshake failed: Error during SSL handshake: error:0A000438:SSL routines::tlsv1 alert internal error
    [08/07/26 08:56:49]ServerStatusService: ignore request for host “server.example.com”
    [08/07/26 08:56:49][network detector] got a network failure: 5
    [08/07/26 08:56:49][api] network error for https://server.example.com/api2/auth-token/: Operation canceled
    
    [08/07/26 08:56:53]Network Error:
    Operation canceled
    [08/07/26 08:56:59][network detector] resetting the qt network access manager
    
  2. IPv6 vs IPv4: I believe this is generally a good idea and I wonder how else I could make sure it uses the right protocol. My server is a headless server running in a datacenter, so not a local machine unfortunately. But i tried connecting in any case. The outcome from the applet.log is this (as expected I guess):

    [08/07/26 08:54:17]Network Error:
    SSL handshake failed: Error during SSL handshake: error:0A000438:SSL routines::tlsv1 alert internal error
    [08/07/26 08:54:30]ServerStatusService: ignore request for host “46.4.xxx.xxx”
    [08/07/26 08:54:30]failed to parse json:‘[’ or ‘{’ expected near end of file
    
    [08/07/26 08:54:32]Failed to login: Internal Server Error
    [08/07/26 08:54:35]ServerStatusService: ignore request for host “46.4.xxx.xxx”
    [08/07/26 08:54:35][api] network error for https://46.4.xxx.xxx/api2/auth-token/: SSL handshake failed: Error during SSL handshake: error:0A000438:SSL routines::tlsv1 alert internal error
    
    [08/07/26 08:54:37]Network Error:
    SSL handshake failed: Error during SSL handshake: error:0A000438:SSL routines::tlsv1 alert internal error
    [08/07/26 08:54:48]ServerStatusService: ignore request for host “46.4.xxx.xxx”
    [08/07/26 08:54:48][api] network error for https://46.4.xxx.xxx/api2/auth-token/: SSL handshake failed: Error during SSL handshake: error:0A000438:SSL routines::tlsv1 alert internal error
    
  3. Proxy settings: I did set the setting to “none” but unfortunately this didn’t change anything.

  4. Debian 13 Compatibility: My client is running on MacOS. there is an update available and I will run this in a bit. I tried to connect to the new seafile server with a windows clieht and the connection took time - but it worked and it connected! The appplet.log of the windows machine shows the following:
    [08/07/26 09:13:35]ServerStatusService: ignore request for host “``server.example.com``”
    [08/07/26 09:13:35]ServerStatusService: ignore request for host “``server.example.com``”
    [08/07/26 09:13:35]beginResetModel called on RepoTreeModel(0x1a983435200) without calling endResetModel first
    [08/07/26 09:13:35]beginResetModel called on RepoFilterProxyModel(0x1a983444af0) without calling endResetModel first
    [08/07/26 09:13:35]endResetModel called on RepoTreeModel(0x1a983435200) without calling beginResetModel first
    [08/07/26 09:13:35]endResetModel called on RepoFilterProxyModel(0x1a983444af0) without calling beginResetModel first
    [08/07/26 09:17:54]beginResetModel called on RepoTreeModel(0x1a983435200) without calling endResetModel first
    [08/07/26 09:17:54]beginResetModel called on RepoFilterProxyModel(0x1a983444af0) without calling endResetModel first
    [08/07/26 09:17:54]endResetModel called on RepoTreeModel(0x1a983435200) without calling beginResetModel first
    [08/07/26 09:17:54]endResetModel called on RepoFilterProxyModel(0x1a983444af0) without calling beginResetModel first

I will now update MacOS and will then see if it works there as well and get back in this thread..

Edit after updating: Updating MacOS to Tahoe 26.6.1 didn’t fix the issue. Curious topic …

On MacOS it’s a LibreSSL 3.3.6 installed, which seems to be from 2021. OpenSSL on Debian 13 server is 3.5.6

I still believe that IPv4 vs IPv6 could somehow be an issue or the TLS handshake.

Maybe it’s better to run Seafile on Debian 12 for now.

I might give this a try.

The error SSL handshake failed: Error during SSL handshake: error:0A000438:SSL routines::tlsv1 alert internal error is quite specific. The “alert internal error” means that your server (Nginx or Apache) encountered a problem during the handshake and explicitly told the client to abort.

Since SeaDrive and the Windows client work, the server is generally healthy, but the macOS Sync Client (which uses a different networking stack based on Qt) is hitting a specific security constraint on your Debian 13 server.

To resolve this, please try the following steps:

  1. Check Server-Side Error Logs:
    The most important step is to check your Nginx (or Apache) error logs on the server while you attempt to connect.

    • For Nginx: tail -f /var/log/nginx/error.log
    • Look for entries like SSL_do_handshake() failed or OCSP_basic_verify() failed.
  2. OCSP Stapling:
    If you have ssl_stapling on; in your Nginx config, the “internal error” alert often occurs if the server cannot reach the Certificate Authority’s OCSP responder. Try temporarily disabling it to see if the client connects:

    ssl_stapling off;
    ssl_stapling_verify off;
    
  3. TLS Version & Ciphers:
    Debian 13 uses OpenSSL 3, which has much stricter default security levels. Ensure your Nginx configuration allows TLS 1.2 in addition to TLS 1.3:

    ssl_protocols TLSv1.2 TLSv1.3;
    

    Also, ensure you are using a broad enough set of ciphers. The macOS Sync Client may be trying to use a cipher that OpenSSL 3 on Debian 13 considers “weak” by default.

  4. Debian 13 OpenSSL Security Level:
    Debian 13 might be set to Security Level 2 by default. You can test if this is the cause by modifying /etc/ssl/openssl.cnf on the server and changing CipherString = DEFAULT@SECLEVEL=2 to @SECLEVEL=1 (only for testing purposes to identify the cause).

Since you mentioned you might try Debian 12, that would likely “fix” it because Debian 12’s OpenSSL configuration is slightly less restrictive, but checking the Nginx error log first should reveal the exact reason for the handshake rejection.

Thank you Daniel

I will certainly have a look at this.

I didn’t configure any Nginx on Debian, I only ran the Docker installation.

But I will check and let you know.

Hi @daniel.pan

Thanks a lot again for your help.

I will still try and install this on a Debian 12 machine. That’s next.

Please see below my checks on the points you suggested to check.

Maybe there is something entirely wrong with my installation, since I am not using NGINX on the server side.

  1. Check Server-Side Error Logs:
    I don’t have nginx installed on the Debian system, only using the Caddy in docker.

    So I get the error message:
    tail: cannot open ‘/var/log/nginx/error.log’ for reading: No such file or directory

  2. OCSP Stapling
    We don’t have the nginx config.
    Could I adjust this in the Caddy settings?

  3. TLS Version & Ciphers:
    We don’t have the nginx config.
    Could I adjust this in the Caddy settings?

  4. Debian 13 OpenSSL Security Level:
    This line doesn’t exist in the openssl.conf file: CipherString = DEFAULT@SECLEVEL=2

EDIT:

I looked at the Caddy log within Docker, which seems to indicate inssues with TLS.

The section below keeps showing up constantly within the log file.

Maybe I can (or had to) set up TLS in the docker Caddy config.

{“level”:“info”,“ts”:1786356152.2307122,“logger”:“http.auto_https”,“msg”:“server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS”,“server_name”:“srv0”,“https_port”:443}
{“level”:“info”,“ts”:1786356152.2307808,“logger”:“http.auto_https”,“msg”:“enabling automatic HTTP->HTTPS redirects”,“server_name”:“srv0”}
{“level”:“info”,“ts”:1786356152.2325802,“logger”:“http”,“msg”:“enabling HTTP/3 listener”,“addr”:“:443”}
{“level”:“info”,“ts”:1786356152.2326276,“logger”:“http.log”,“msg”:“server running”,“name”:“srv0”,“protocols”:[“h1”,“h2”,“h3”]}
{“level”:“warn”,“ts”:1786356152.2327988,“logger”:“http”,“msg”:“HTTP/2 skipped because it requires TLS”,“network”:“tcp”,“addr”:“:80”}
{“level”:“warn”,“ts”:1786356152.2328265,“logger”:“http”,“msg”:“HTTP/3 skipped because it requires TLS”,“network”:“tcp”,“addr”:“:80”}
{“level”:“info”,“ts”:1786356152.2328455,“logger”:“http.log”,“msg”:“server running”,“name”:“remaining_auto_https_redirects”,“protocols”:[“h1”,“h2”,“h3”]}
{“level”:“info”,“ts”:1786356152.2328618,“logger”:“http”,“msg”:“enabling automatic TLS certificate management”,“domains”:[“server.example11.com”]}
{“level”:“info”,“ts”:1786356152.2329638,“logger”:“http”,“msg”:“servers shutting down with eternal grace period”}
{“level”:“info”,“ts”:1786356152.2334797,“msg”:“autosaved config (load with --resume flag)”,“file”:“/config/caddy/autosave.json”}
{“level”:“info”,“ts”:1786356152.2335267,“logger”:“admin.api”,“msg”:“load complete”}
{“level”:“info”,“ts”:1786356152.2337928,“logger”:“docker-proxy”,“msg”:“Successfully configured”,“server”:“localhost”}
{“level”:“info”,“ts”:1786356152.2348225,“logger”:“admin”,“msg”:“stopped previous server”,“address”:“localhost:2019”}
{“level”:“info”,“ts”:1786356155.1501803,“logger”:“docker-proxy”,“msg”:“New Caddyfile”,“caddyfile”:“https://server.example11.com {\n\thandle_path /socket.io/* {\n\t\trewrite * /socket.io{uri}\n\t\treverse_proxy :80\n\t}\n\thandle_path /sdoc-server/* {\n\t\trewrite * {uri}\n\t\treverse_proxy :80\n\t}\n\treverse_proxy 172.18.0.3:80\n}\n”}
{“level”:“info”,“ts”:1786356155.151546,“logger”:“docker-proxy”,“msg”:“New Config JSON”,“json”:“{“apps”:{“http”:{“servers”:{“srv0”:{“listen”:[“:443”],“routes”:[{“match”:[{“host”:[“server.example11.com”]}],“handle”:[{“handler”:“subroute”,“routes”:[{“group”:“group2”,“handle”:[{“handler”:“subroute”,“routes”:[{“handle”:[{“handler”:“rewrite”,“strip_path_prefix”:“/sdoc-server”}]},{“group”:“group1”,“handle”:[{“handler”:“rewrite”,“uri”:“{http.request.uri}”}]},{“handle”:[{“handler”:“reverse_proxy”,“upstreams”:[{“dial”:“:80”}]}]}]}],“match”:[{“path”:[“/sdoc-server/“]}]},{“group”:“group2”,“handle”:[{“handler”:“subroute”,“routes”:[{“handle”:[{“handler”:“rewrite”,“strip_path_prefix”:”/socket.io"}]},{“group”:“group0”,“handle”:[{“handler”:“rewrite”,“uri”:“/socket.io{http.request.uri}”}]},{“handle”:[{“handler”:“reverse_proxy”,“upstreams”:[{“dial”:“:80”}]}]}]}],“match”:[{“path”:["/socket.io/”]}]},{“handle”:[{“handler”:“reverse_proxy”,“upstreams”:[{“dial”:“172.18.0.3:80”}]}]}]}],“terminal”:true}]}}}}}”}
{“level”:“info”,“ts”:1786356155.151587,“logger”:“docker-proxy”,“msg”:“Sending configuration to”,“server”:“localhost”}
{“level”:“info”,“ts”:1786356155.1524997,“logger”:“admin.api”,“msg”:“received request”,“method”:“POST”,“host”:“localhost:2019”,“uri”:“/load”,“remote_ip”:“127.0.0.1”,“remote_port”:“56748”,“headers”:{“User-Agent”:[“Go-http-client/1.1”],“Content-Length”:[“940”],“Content-Type”:[“application/json”],“Accept-Encoding”:[“gzip”]}}
{“level”:“info”,“ts”:1786356155.153319,“logger”:“admin”,“msg”:“admin endpoint started”,“address”:“localhost:2019”,“enforce_origin”:false,“origins”:[“//[::1]:2019”,“//127.0.0.1:2019”,“//localhost:2019”]}
{“level”:“info”,“ts”:1786356155.1534424,“logger”:“http.auto_https”,“msg”:“server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS”,“server_name”:“srv0”,“https_port”:443}
{“level”:“info”,“ts”:1786356155.1534657,“logger”:“http.auto_https”,“msg”:“enabling automatic HTTP->HTTPS redirects”,“server_name”:“srv0”}
{“level”:“info”,“ts”:1786356155.1539829,“logger”:“http”,“msg”:“enabling HTTP/3 listener”,“addr”:“:443”}
{“level”:“info”,“ts”:1786356155.1539965,“logger”:“http.log”,“msg”:“server running”,“name”:“srv0”,“protocols”:[“h1”,“h2”,“h3”]}
{“level”:“warn”,“ts”:1786356155.1540425,“logger”:“http”,“msg”:“HTTP/2 skipped because it requires TLS”,“network”:“tcp”,“addr”:“:80”}
{“level”:“warn”,“ts”:1786356155.1540504,“logger”:“http”,“msg”:“HTTP/3 skipped because it requires TLS”,“network”:“tcp”,“addr”:“:80”}
{“level”:“info”,“ts”:1786356155.154055,“logger”:“http.log”,“msg”:“server running”,“name”:“remaining_auto_https_redirects”,“protocols”:[“h1”,“h2”,“h3”]}
{“level”:“info”,“ts”:1786356155.154061,“logger”:“http”,“msg”:“enabling automatic TLS certificate management”,“domains”:[“server.example11.com”]}
{“level”:“info”,“ts”:1786356155.154099,“logger”:“http”,“msg”:“servers shutting down with eternal grace period”}
{“level”:“info”,“ts”:1786356155.154297,“msg”:“autosaved config (load with --resume flag)”,“file”:“/config/caddy/autosave.json”}
{“level”:“info”,“ts”:1786356155.1543105,“logger”:“admin.api”,“msg”:“load complete”}
{“level”:“info”,“ts”:1786356155.1544318,“logger”:“docker-proxy”,“msg”:“Successfully configured”,“server”:“localhost”}
{“level”:“info”,“ts”:1786356155.1555426,“logger”:“admin”,“msg”:“stopped previous server”,“address”:“localhost:2019”}

Edit 2:

I am wondering if it might have anything to do with the firewall.

I actually do use UFW and haven’t got IPTables installed. I am not used to work with that. I only open ports 22, 443 and 80 usually.

Could there be in issue with this of seafile docker containers talking to each other?

Since you are using Caddy via caddy-docker-proxy, the settings on your Debian host’s /etc/ssl/openssl.cnf will not affect the Caddy container. Caddy uses its own internal Go-based TLS stack.

The logs you provided reveal a few critical issues that are likely causing the “internal error” during the TLS handshake:

  1. Upstream Resolution Failure: In your Caddy log, the reverse_proxy for /socket.io/* and /sdoc-server/* is showing as :80 (missing the hostname). This usually happens when the Caddy docker-proxy template cannot resolve the service name. You should ensure your seafile-server.yml and seadoc.yml use the service name seafile instead of relying on automatic detection if it’s failing.
  2. Configuration Flapping: The logs show Caddy is constantly reloading and “stopping previous server.” This frequent instability can cause handshake failures if the client tries to connect while the policy is being rebuilt.
  3. Redundant WebSocket Labels: There is a known issue where redundant labels in seadoc.yml or notification-server.yml can cause configuration conflicts in Caddy. Specifically, if you have labels manually defining the WebSocket proxy while it’s also being handled automatically, it can lead to the behavior you’re seeing. You may want to check this guide for a similar fix: Fixing Caddy configuration conflicts.

Recommended Steps:

  • Fix Docker Labels: Check your seafile-server.yml and seadoc.yml. Instead of using static IPs like 172.18.0.3, ensure you are using the service names defined in your compose file.
  • Check SNI: Ensure the SEAFILE_SERVER_HOSTNAME in your .env file exactly matches the domain you are using in the client. If Caddy receives a request for a domain it doesn’t recognize or hasn’t successfully obtained a certificate for, it will throw a TLS alert.
  • Check Firewall: Since you mentioned UFW, ensure that the Docker network is not being blocked from communicating internally. However, the tlsv1 alert internal error is specifically a TLS-level rejection from Caddy, meaning the client reached Caddy, but Caddy chose to abort.
  • Simplify for Testing: Temporarily disable SeaDoc (set ENABLE_SEADOC=false and remove seadoc.yml from COMPOSE_FILE) to see if the sync client can connect to the core Seafile service. This will help determine if the conflict is caused by the SeaDoc labels.

If you continue to see “internal error” in the logs after stabilizing the config, please share the labels section of your seafile-server.yml.

  1. Upstream Resolution Failure / Fix docker labels:
    During setup, I haven’t adjusted anything inside the seafile-server.yml

    I didn’t see that I was supposed to do that in the Setup community edition Manual.

    I only adjusted the .env file, which looks like this:

#################################

Docker compose configurations

#################################
COMPOSE_FILE=‘seafile-server.yml,caddy.yml,seadoc.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=/opt
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=cloud.example.com
SEAFILE_SERVER_PROTOCOL=https
TIME_ZONE=Europe/Berlin
JWT_PRIVATE_KEY=xxxxxxxxxxxxxxxxx
NON_ROOT=true

#####################################

Third-party service configuration

#####################################

Database

SEAFILE_MYSQL_DB_HOST=db
SEAFILE_MYSQL_DB_USER=seafile
SEAFILE_MYSQL_DB_PASSWORD=xxxxxxxx
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=xxxxxxxxxxxxxx

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=xxxxxxx

Seafile admin user







INIT_SEAFILE_ADMIN_PASSWORD=xxxxxxxxxx

############################################

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

My seafile-server.yml looks like this:

Should I adjust all the values in the “environment:” section?

Please also see the requested labels section

GNU nano 8.4                                                seafile-server.yml
command:
- /bin/sh
- -c
- exec redis-server --requirepass “$$REDIS_PASSWORD” --save “” --appendonly no
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 >
- 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

networks:
seafile-net:
name: seafile-net
  1. Redundant WebSocket Labels:
    I disabled seadoc in the env setting and restarted the seafile server with “docker compose down” and “docker compose up -d”
    That didn’t fix the initial issue.

    EDIT: I then saw that I was supposed to remove the seadoc.yml from compose as well. After doing that and do docker down and up again, I could connect with the seafile client !

Please note: After docker compose up -d, it takes 5 minutes until caddy has started. For 5 minutes I get the “502 Bad gateway” in the browser. It feels like this takes too long, or is this normal?

SO next step is to fix the seadoc.yml file, I guess.

Please also have a look at the seafile.log, with the warning of a conflicting server name.

And why does it say “Nginx ready”?

*** Running /etc/my_init.d/01_create_data_links.sh...
*** Booting runit daemon...
*** Runit started as PID 15
*** Running /scripts/enterpoint.sh...
2026-08-11 09:55:17 Nginx ready 
2026-08-11 09:55:17 Create linux user seafile in container, please wait. 
nginx: [warn] conflicting server name "" on 0.0.0.0:80, ignored
2026-08-11 10:00:37 This is an idle script (infinite loop) to keep container running. 
nginx: [warn] conflicting server name "" on 0.0.0.0:80, ignored
[2026-08-11 10:00:38] Skip running setup-seafile-mysql.py because there is existing seafile-data folder.
[08/11/2026 10:00:38][upgrade]: The container was recreated, start fix the media symlinks
mv: not replacing '/shared/seafile/seahub-data/avatars/default-non-register.jpg'
mv: not replacing '/shared/seafile/seahub-data/avatars/default.png'
mv: not replacing '/shared/seafile/seahub-data/avatars/groups'
[08/11/2026 10:00:38][upgrade]: Done

Starting seafile server, please wait ...
Seafile server started

Done.

Starting seahub at port 8000 ...

Seahub is started

Done.

EDIT2:

Seadoc.yml

services:

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=${SEAHUB_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

EDIT3:

Seafile client connects but is buggy. I get the “waiting circle” when refreshing the integrated “cloud file browser”.

Seadrive client doesn’t seem to properly populate the changes to the server (anymore).

Something is just wrong and I will redo the server, trying it again with a fresh start.

Hi

I did tons of checks and re and re and re-installations of various Debian and Ubuntu servers today.

The issue is simply the firewall.

If UFW is running during the first docker compose up -d ,then it causes the above issues.

If IP Tables is running, then docker adds various rules to the IPTables and the seafile server was running, but not reachable at all from the internet.

For me, my best solution at the time is to create a fresh server (can be Debian 13), then install docker according to the manuals but NOT install any firewall.

Once Seafile is started with docker compose up -d and works well, then install UFW and open SSH, HTTP and HTTPS ports and enable the firwall - and that works.

Also worked after a restart.

But it can be felt that the speed of the website is higher when no firewall is running. UFW causes a small lag. So there is room for improvement.

I assume in case someone wants to do docker compose down then UFW should be disabled prior to running Docker compose up -d again.

Again, this is the best I could do to make this work for me.

@daniel.pan I believe that ideally the correct setup of a firewall should be added to the manual and the user shouldn’t be left alone with it based on the docker installation files.

Would you agree?

What do others think?

For me, this is way too complex.

I am not an expert but I am running Seafile without docker since Seafile Version 2 and never had to know these things.That was the beauty of Seafile for me.

I am not sure about the AI answers by the way,

Thanks for considering

About Firewall (UFW):

While you mentioned opening ports 22, 80, and 443, ensure that UFW is not blocking the internal communication between Docker containers. Docker typically manages iptables rules directly to allow container-to-container traffic, but sometimes UFW rules can interfere with how Docker’s bridge network handles external-to-internal routing.

Personally we don’t have such issues in many of our managed installation. We don’t touch firewall settings at all.

I think including firewall related document to Seafile manual will make it quite complex, and is out of the scope of Seafile manual.

Hi @daniel.pan

I have been running the server with UFW now since a while.

All works ok.

Starting UFW after the first docker compose up -d seems to help.

I thought adding this as a hint or advising what firewall to use to the seafile docs could help other users as well, but I don’t have your experience. You will know what’s the right thing to do for sure.

I will ask in the Seafile Server section how and what other users use a firewall for Debian or Ubuntu together with Seafile in docker, maybe that gives a bit of an inside also for other users then.

I will close this topic here, which I hope helps everybody.