Hello there !
First, I am a debutant so I’m sorry if I do not understand at first try what you will explain to me. I can totally ask stupid things for you.
I install SeaFile 13.0.22 via docker for UnRaid.
Everything seems to work just fine, I can direct access on my network and I set up a cloudflare tunnel for external access. I can navigate trough the server without problem via my phone when I’m not home. BUT when I try to download a file, I got this error “Both token and cookie are not set”. I don’t understand what I have to do there. Can someone help me please ? 
The “Both token and cookie are not set” error typically indicates a protocol or domain mismatch. When you access Seafile via a Cloudflare tunnel (HTTPS) but the server isn’t fully aware of its external address, it might generate download links using http:// or fail to validate the session cookie.
To resolve this on Seafile 13.0.22, please check the following configurations:
1. Update Docker Environment Variables
Ensure your Docker container (Unraid template or Compose file) has the following environment variables set correctly for your external access:
SEAFILE_SERVER_HOSTNAME: Set this to your Cloudflare domain (e.g., seafile.yourdomain.com).
SEAFILE_SERVER_PROTOCOL: Set this to https.
2. Configure CSRF Trusted Origins
Starting with Seafile 11, Django’s stricter CSRF protections require you to explicitly trust your external domain.
Edit your seahub_settings.py (usually located in your appdata folder under seafile/conf/seahub_settings.py) and add the following lines:
CSRF_TRUSTED_ORIGINS = ['https://seafile.yourdomain.com']
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = 'Strict'
Note: Replace https://seafile.yourdomain.com with your actual external URL. The protocol https:// is mandatory here.
3. Cloudflare Tunnel Settings
In your Cloudflare Zero Trust dashboard, ensure that the tunnel is passing the correct headers to your local Seafile instance:
- In the Public Hostname settings for your tunnel, check under HTTP Settings.
- Ensure that the HTTP Host Header is either empty (to pass the original host) or explicitly set to your domain.
4. Restart Seafile
After making these changes, restart your Seafile container for the settings to take effect.
If the issue persists, try opening your browser’s Developer Tools (F12), go to the Network tab, and attempt the download. Look for the failing request to /seafhttp/... and check if it is being sent over http instead of https.
First, thanks for your help !
My server protocol was in HTTP so I changed it to HTTPS.
I did the change in the seahub_setting.py.
In my CloudFlare Tunnel, I changed the service type who where in HTTP to HTTPS, to have the same type everywhere. The HTTP Host Header is “Null” (for expliciting, do I only pu HTTPS or the full IP adresse ?)
After restarting I still have to use HTTP to connect to seafile locally and now I have a 502 error for cloudflare access. I looked in the browser developer tools and the failed request is send in HTTPS.
For testing purpose, I put back HTTP for the service type of my route and I just got an “Permission denied” page instead of the 502 error when I try to download a file (403 error in the browser, send in https).
So it’s a CFRS error ? Here what’s in seahub_setting beside the secret key :
TIME_ZONE = ‘Etc/UTC’
CSRF_TRUSTED_ORIGINS = [‘https:// mydomainnamewithoutthespace]
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_SAMESITE = ‘Strict’
First I suggest you check Nginx access log at the seafile server to make sure it correctly receive HTTP request.
The “Permission denied” (403 error) during file downloads in Seafile 13.0.22 is likely to be a known behavior when the internal permission check fails. Starting with Seafile 12.0, the file server component (seaf-server) must send an internal request to the web component (seahub) via 127.0.0.1 to verify your access rights before allowing a download. (You can check the log file seafile.log and fileserver.log)
To resolve this, please check and update your seahub_settings.py:
1. Update ALLOWED_HOSTS
Ensure that 127.0.0.1 is included in your ALLOWED_HOSTS list. If this setting is missing or only contains your external domain, the internal permission check will be blocked with a 403 error.
ALLOWED_HOSTS = ['yourdomain.com', '127.0.0.1']
2. Fix CSRF Syntax
In your snippet, there is a space after https:// in the CSRF_TRUSTED_ORIGINS setting. Ensure there are no spaces and the quote is closed correctly:
CSRF_TRUSTED_ORIGINS = ['https://yourdomain.com']
3. Cloudflare Tunnel Service Type
Regarding the 502 error you saw: The Cloudflare Tunnel service type should usually remain HTTP (pointing to your Seafile container’s local IP and port, e.g., http://192.168.x.x:80), because the container itself is likely not running SSL.
However, you must keep the Seafile configuration set to HTTPS so that it generates the correct links:
SEAFILE_SERVER_PROTOCOL: https
CSRF_COOKIE_SECURE: True
Note SEAFILE_SERVER_PROTOCOL is the protocol your browser will use to download files.
1 Like
All of this is hard to understand for me. Thanks for all the time you take.
Here my seafile.log :
[2026-06-06 05:00:21] [INFO] seafile-session.c(53): fileserver: web_token_expire_time = 3600
[2026-06-06 05:00:21] [INFO] seafile-session.c(65): fileserver: max_index_processing_threads= 3
[2026-06-06 05:00:21] [INFO] seafile-session.c(78): fileserver: fixed_block_size = 8388608
[2026-06-06 05:00:21] [INFO] seafile-session.c(90): fileserver: max_indexing_threads = 1
[2026-06-06 05:00:21] [INFO] seafile-session.c(103): fileserver: max_upload_size = -1
[2026-06-06 05:00:21] [INFO] ../common/seaf-utils.c(399): Use database Mysql
[2026-06-06 05:00:21] [INFO] http-server.c(196): fileserver: worker_threads = 10
[2026-06-06 05:00:21] [INFO] http-server.c(207): fileserver: verify_client_blocks = 1
[2026-06-06 05:00:21] [INFO] http-server.c(229): fileserver: cluster_shared_temp_file_mode = 600
[2026-06-06 05:00:21] [INFO] socket file exists, delete it anyway
[2026-06-06 05:00:24] [WARNING] ../common/seaf-db.c(875): Failed to connect to MySQL: Can’t connect to server on ‘seafile-mariadb’ (115)
[2026-06-06 05:00:24] [WARNING] ../common/seaf-db.c(875): Failed to connect to MySQL: Can’t connect to server on ‘seafile-mariadb’ (115)
[2026-06-06 05:00:51] [WARNING] ../common/seaf-db.c(936): Failed to prepare sql SELECT 1;: Lost connection to server during query
[2026-06-06 20:19:11] [INFO] seafile-session.c(53): fileserver: web_token_expire_time = 3600
[2026-06-06 20:19:11] [INFO] seafile-session.c(65): fileserver: max_index_processing_threads= 3
[2026-06-06 20:19:11] [INFO] seafile-session.c(78): fileserver: fixed_block_size = 8388608
[2026-06-06 20:19:11] [INFO] seafile-session.c(90): fileserver: max_indexing_threads = 1
[2026-06-06 20:19:11] [INFO] seafile-session.c(103): fileserver: max_upload_size = -1
[2026-06-06 20:19:11] [INFO] ../common/seaf-utils.c(399): Use database Mysql
[2026-06-06 20:19:11] [INFO] http-server.c(196): fileserver: worker_threads = 10
[2026-06-06 20:19:11] [INFO] http-server.c(207): fileserver: verify_client_blocks = 1
[2026-06-06 20:19:11] [INFO] http-server.c(229): fileserver: cluster_shared_temp_file_mode = 600
[2026-06-06 20:19:11] [INFO] socket file exists, delete it anyway
(As you see, I use mariadb and not Nginx so I don’t know if I can do the same things.)
I can’t find “fileserver.log”.
Where can I find ALLOWED_HOSTS ?
The CSRF syntax is good, I put the space because it create a link and I got an error from the awnser box here.
Tunnel service type is set to HTTP, the Seafile configuration is set to HTTPS.
And I got news ! When I tested again to download a file, I got again the token thing, and by changing HTTPS by HTTP in my adress bar, I got the permission denied.
BUT, I don’t know why, I was accessing via my IP adress and not the tunnel adress. By using this, I am able to download without a problem my file. So I don’t know if it’s normal or not but as we say in french “The trouble is between the chair and the keyboard”.
And know I can connect via the Android App but can’t access my files (log seems to indicate the 403 error)… But I can connect via Firefox on my phone.
It never end…
ALLOWED_HOSTS is not there by default; you need to add it manually to your seahub_settings.py file (the same file where you added the CSRF settings).
Add this line (or update it if it exists):
ALLOWED_HOSTS = ['your.tunnel-domain.com', '127.0.0.1']
Hope it can help.
Thanks for your help ! I don’t understand why I can’t connect on the Android app anymore but this is not the same issue so I will do my research before open a new thread.
At least, I can connect and download normally via browser thanks to you !