CSRF verification failed

I’m getting a CSRF Verification failed error with a newly setup seafile installation

it’s running on Unraid and through Cloudflare as setup from a guide on Reddit: “Guide for installing the latest version of Seafile on Unraid with online connection through Cloudflare Tunnel” by GusFit

everything seems to work locally, and I can get to the login page through the cloudflare tunnel, but as soon as I go to login, I get: forbidden (403) CSRF Verification Failed. request aborted

I’ve added CSRF_TRUSTED_ORIGINS with no effect

This is driving me crazy now, been trying to sort this for a week and have started fresh about 5 times now, still no luck! any help would be appreciated!

It seems that the guide might not cover everything needed for a fully functional setup on the internet. Have you ensured that the SERVICE_URL and FILE_SERVER_ROOT variables in your seahub_settings.py are set to use HTTPS? This is crucial for proper operation when accessing Seafile over the internet. If these are already set correctly, there might be additional configurations needed, especially regarding the Cloudflare Tunnel setup and ensuring all necessary headers and security settings are in place.

Additionally, during the installation of the Seafile container, make sure to set the following environment variables in your Docker configuration to ensure proper operation behind a proxy:

SEAFILE_SERVER_LETSENCRYPT=false
SEAFILE_SERVER_HOSTNAME=seafile.domain.com
FORCE_HTTPS_IN_CONF=true

Also, ensure that you have added the following line in your seahub_settings.py file, including the square brackets:

CSRF_TRUSTED_ORIGINS = ["https://seafile.domain.com"]

To better assist you, could you please provide the complete content of your seahub_settings.py file? This will help us ensure that all necessary configurations are in place and correctly set up. Thank you!

Thanks for your reply!

I’ve just checked, they weren’t on HTTPS, but they are now - unfortunately with no effect

I was missing:

SEAFILE_SERVER_HOSTNAME=seafile.domain.com
FORCE_HTTPS_IN_CONF=true

in my docker container template, but have added them and re-run the template, with no change either,

Seahub_settings.py below (Domain and passwords etc. blanked out with ** ):

# -*- coding: utf-8 -*-
SECRET_KEY = " ** "
SERVICE_URL = "https:// ** "
FILE_SERVER_ROOT = "https:// ** /seafhttp"

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'seahub_db',
        'USER': 'seafile',
        'PASSWORD': ' ** ',
        'HOST': 'seafile-mariadb',
        'PORT': '3306',
        'OPTIONS': {'charset': 'utf8mb4'},
    }
}


CACHES = {
    'default': {
        'BACKEND': 'django_pylibmc.memcached.PyLibMCCache',
        'LOCATION': 'memcached:11211',
    },
    'locmem': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
    },
}
COMPRESS_CACHE_BACKEND = 'locmem'
TIME_ZONE = 'Etc/UTC'

    ALLOWED_HOSTS = [' ** ']

    CSRF_COOKIE_SECURE = True
    
    CSRF_COOKIE_SAMESITE = 'Strict'
    
    CSRF_TRUSTED_ORIGINS = ['https://  ** ']

My compose file is as below (again details removed with ** ):

services:
  db:
    image: mariadb:10.11
    container_name: seafile-mysql
    environment:
      - MYSQL_ROOT_PASSWORD= **   
      - MYSQL_LOG_CONSOLE=true
      - MARIADB_AUTO_UPGRADE=1
    volumes:
      - /mnt/user/appdata/seafile/db:/var/lib/mysql  
    networks:
      - seafile-net

  memcached:
    image: memcached:1.6.18
    container_name: seafile-memcached
    entrypoint: memcached -m 256
    networks:
      - seafile-net
          
  seafile:
    image: seafileltd/seafile-mc:11.0-latest
    container_name: seafile
    ports:
      - "8080:80"
      - "8081:8081" 
    volumes:
      - /mnt/user/appdata/seafile/data:/shared  
    environment:
      - DB_HOST=db
      - DB_ROOT_PASSWD= **   
      - TIME_ZONE=Etc/GMT  
      - SEAFILE_ADMIN_EMAIL= ** 
      - SEAFILE_ADMIN_PASSWORD= **     
      - SEAFILE_SERVER_HOSTNAME=seafile. ** .uk
      - FORCE_HTTPS_IN_CONF=true
      - SEAFILE_SERVER_LETSENCRYPT=false   
    depends_on:
      - db
      - memcached
    networks:
      - seafile-net

networks:
  seafile-net:

seafile.NGINX.conf if that helps too:

# -*- mode: nginx -*-
# Auto generated at 12/05/2024 08:44:00
server {
listen 80;
server_name seafile. ** .uk;

    client_max_body_size 10m;

    location / {
        proxy_pass http://127.0.0.1:8000/;
        proxy_read_timeout 310s;
        proxy_set_header Host $http_host;
        proxy_set_header Forwarded "for=$remote_addr;proto=$scheme";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Connection "";
        proxy_http_version 1.1;

        client_max_body_size 0;
        access_log      /var/log/nginx/seahub.access.log seafileformat;
        error_log       /var/log/nginx/seahub.error.log;
    }

    location /seafhttp {
        rewrite ^/seafhttp(.*)$ $1 break;
        proxy_pass http://127.0.0.1:8082;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size 0;
        proxy_connect_timeout  36000s;
        proxy_read_timeout  36000s;
        proxy_request_buffering off;
        access_log      /var/log/nginx/seafhttp.access.log seafileformat;
        error_log       /var/log/nginx/seafhttp.error.log;
    }

    location /notification/ping {
        proxy_pass http://127.0.0.1:8083/ping;
        access_log      /var/log/nginx/notification.access.log seafileformat;
        error_log       /var/log/nginx/notification.error.log;
    }

    location /notification {
        proxy_pass http://127.0.0.1:8083/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        access_log      /var/log/nginx/notification.access.log seafileformat;
        error_log       /var/log/nginx/notification.error.log;
    }

    location /seafdav {
        proxy_pass         http://127.0.0.1:8080;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_read_timeout  1200s;
        client_max_body_size 0;

        access_log      /var/log/nginx/seafdav.access.log seafileformat;
        error_log       /var/log/nginx/seafdav.error.log;
    }

    location /media {
        root /opt/seafile/seafile-server-latest/seahub;
    }

}

I noticed your port mapping is non-standard. The typical Seafile configuration uses:

ports:
  - "80:80"
  - "443:443"  # for HTTPS

But you’re mapping to different ports. Before we proceed with HTTPS configuration:

Questions Needing Clarification

  • Are you using a reverse proxy (like SWAG, Nginx Proxy Manager, or others)?
  • What’s the specific reason for using these alternate ports?
  • Could you share in a single post:
    • Your reverse proxy configuration (if using one)
    • The reason for this specific port mapping choice

You can edit your forum post to include all these details at once, which would help us provide a more accurate solution without needing to modify Seafile’s internal Nginx configuration.

Edit

Please also share your exact seahub_settings.py file content. When sharing:

  • Replace your real domain with “domain.com
  • Replace any sensitive data (passwords, keys, etc.) with “****”
  • Maintain the exact same formatting, spacing, and indentation as in your server file
  • Keep all comments and empty lines exactly as they appear

I’m not sure on the reasoning for those specific ports - that was just the way they were from the compose file I was using - I had seen this before though and set them to 443:443, but this just results in:

Error response from daemon: driver failed programming external connectivity on endpoint seafile (54adc8ee1481c20d93cb4e1511a946df46cbb5d2fe9dda3e3c053caf76cc7a0c): Error starting userland proxy: listen tcp4 0.0.0.0:443: bind: address already in use

I’ve not got a reverse proxy setup - I’m using a Cloudflare Tunnel

seahub_settings.py below:

# -*- coding: utf-8 -*-
SECRET_KEY = "**************************************************"
SERVICE_URL = "https://domain.com"
FILE_SERVER_ROOT = "https://domain.com/seafhttp"

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'seahub_db',
        'USER': 'seafile',
        'PASSWORD': '************************************',
        'HOST': 'seafile-mariadb',
        'PORT': '3306',
        'OPTIONS': {'charset': 'utf8mb4'},
    }
}


CACHES = {
    'default': {
        'BACKEND': 'django_pylibmc.memcached.PyLibMCCache',
        'LOCATION': 'memcached:11211',
    },
    'locmem': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
    },
}
COMPRESS_CACHE_BACKEND = 'locmem'
TIME_ZONE = 'Etc/UTC'

    ### New in version 11
    # For security consideration, please set to match the host/domain of your site, e.g., ALLOWED_HOSTS = ['.example.com'].
    # Please refer https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts for details.
    ALLOWED_HOSTS = ['domain.com']
    
    # Whether to use a secure cookie for the CSRF cookie
    # https://docs.djangoproject.com/en/3.2/ref/settings/#csrf-cookie-secure
    CSRF_COOKIE_SECURE = True
    
    # The value of the SameSite flag on the CSRF cookie
    # https://docs.djangoproject.com/en/3.2/ref/settings/#csrf-cookie-samesite
    CSRF_COOKIE_SAMESITE = 'Strict'
    
    # https://docs.djangoproject.com/en/3.2/ref/settings/#csrf-trusted-origins
    CSRF_TRUSTED_ORIGINS = ['https://domain.com']
    
    # Try to fix CSRF bug in new version 11 beta
    # Found the real fix, don't need this anymore
    #CSRF_TRUSTED_ORIGINS = ["https://file.example.com"]
    # DEBUG=True

Port Mapping Solution

For your Docker configuration, use these port mappings:

ports:
  - "8080:80"
  - "8443:443"

Check Port 443 Usage

To identify which service is currently using port 443 on your Linux machine, run this command:

sudo lsof -i :443

or alternatively:

sudo netstat -tulpn | grep :443

The error you’re seeing (listen tcp4 0.0.0.0:443: bind: address already in use) indicates that port 443 is already in use, likely by your Cloudflare Tunnel service.

Important Missing Information

While you mentioned using Cloudflare Tunnel, I notice you haven’t provided complete information about your setup. To properly assist you, please provide:

  • Your Cloudflare Tunnel configuration details
  • Information about other web services running on your machine
  • Clarification on whether you’re using any other reverse proxy

> THIS I VERY IMPORTANT QUESTION IF YOU HAVE ONE OR NOT

Without understanding your complete infrastructure context, we risk providing partial solutions that might not integrate well with your existing setup. Could you please share these details so we can provide a comprehensive solution

Thanks,

I have set the ports to the ones you mentioned - all still working as before, could still access from internal address, but CSRF Verification error on external,

Port usage:

sudo lsof -i :443
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx   4141 root   10u  IPv4  11027      0t0  TCP SERVERNAME:https (LISTEN)
nginx   7766 root   10u  IPv4  11027      0t0  TCP SERVERNAME:https (LISTEN)
sudo netstat -tulpn | grep :443
tcp        0      0 127.0.0.1:443           0.0.0.0:*               LISTEN      4141/nginx: master  

My cloudflare should be setup identical to the one shown in Spaceinvaderone’s video and is as below:

Tunnel type: HTTP (setting it to HTTPS gives me a 502 bad gateway error)
URL is set to the servers IP:8080
There’s no subdomain or path setup before/after the main domain name.

There’s a bunch more settings in Cloudflare, but I havent touched them so they should all be on default settings,

This is the only service running on this machine, and Cloudflare is the only proxy I’m using - this machine was built up with Unraid from a clean installation, and just has Seafile running on it, so there shouldnt be anything to interfere.

I don’t have time to look into this in depth right now, but one quick suggestion: in Cloudflare, I always set SSL/TLS to FULL - it’s a common fix I use. I can’t remember the exact technical reason, but you should try changing this setting. I’ll come back later to edit this response with more detailed information.

Try it and send your feedback.

That’s alright, thanks for helping out so much,

Just tried setting SSL/TLS to full, no change unfortunately though,

try HTTPS and port 8443 here

image

But if i see your conf you have NGINX on your environnement right ?

image

But maybe it is the Nginx from seafile i don’t know exactly

Just tried that, still no luck, brings up a 502 bad gareway error - with port 8080 I can still access the login page, it’s just when I press login that it goes to CSRF Verification Error

The NGINX in there should be the one from Seafile - not sure why there’s two instances in there though

Can you check the console in your browser after you login to the page please

Not much in there:

/favicon.ico:1 
        
        
       Failed to load resource: the server responded with a status of 404 ()
login/:1 
        
        
       Failed to load resource: the server responded with a status of 403 ()

Ok not realy usefull can you send the container seafile log please just from the seafile container

sudo docker log seafile

assuming your container is “seafile”

This is the most recent:

Seahub is started

Done.

2024-12-10 18:21:16 Waiting Nginx 
2024-12-10 18:21:16 Nginx ready 
2024-12-10 18:21:16 This is an idle script (infinite loop) to keep container running. 

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

Done.

Starting seahub at port 8000 ...

Seahub is started

Done.

I can’t help you more with your configuration sorry i don’t have any other idea, or use SWAG and follow my guide

Thanks - I’ll give that a try, going to wipe everything and start from scratch with it, and will let you know if it all works!

Very good idea, sometime we make so many change for testing and after a long days we can’t remember what we need undo, keep going :slight_smile: