Help solving Contradictory Scheme Headers issue with Nginx Reverse Proxy on a remote machine

So I am setting up a seafile instance on my homelab, but the provided defaults do not work with my existing setup. I had to convert the Docker compose files to Podman Quadlet files since my server uses rootless Podman rather than Docker. Here’s my environment file for Seafile:

seafile-server.env

DB_HOST=localhost
DB_PORT=3306
DB_USER=seafile
DB_ROOT_PASSWD=${redacted}
DB_PASSWORD=${redacted}
SEAFILE_MYSQL_DB_CCNET_DB_NAME=ccnet_db
SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=seafile_db
SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=seahub_db
TIME_ZONE=America/Chicago
INIT_SEAFILE_ADMIN_EMAIL=${redacted}
INIT_SEAFILE_ADMIN_PASSWORD=${redacted}
SEAFILE_SERVER_HOSTNAME=cloud.linuxdragon.dev
SEAFILE_SERVER_PROTOCOL=http
SITE_ROOT=/
NON_ROOT=false
JWT_PRIVATE_KEY=${redacted}
SEAFILE_LOG_TO_STDOUT=true
ENABLE_SEADOC=true
SEADOC_SERVER_URL=https://cloud.linuxdragon.dev/sdoc-server

I share this because I there is a possibility that I’ve misconfigured Seafile itself…

The issue, then, is that when I try to navigate to Seafile, I get a 400 Bad Request status code, with a slightly more helpful message of Contradictory Scheme headers. So the most likely culprit is the Nginx reverse proxy I run on another machine.

81-cloud.linuxdragon.dev.conf

# vim: filetype=nginx

# HTTPS PORT 443 CONFIGURATION
server {
    server_name         cloud.linuxdragon.dev;
    listen [::]:443     ssl;
    listen 443          ssl;
    http2               on;

    location / {
        proxy_pass                              http://homelab:1080;

        include /etc/nginx/headers.conf.d/5-reverse_proxy-headers.conf;
        include /etc/nginx/headers.conf.d/0-security-headers.conf;
        include /etc/nginx/headers.conf.d/4-container-headers.conf;

        proxy_read_timeout                      310s;
        client_max_body_size                    0;

    }

    include /etc/nginx/ssl.conf.d/0-options-ssl.conf;
    include /etc/nginx/ssl.conf.d/3-linuxdragon.dev-ssl.conf;

}


# HTTP PORT 80 CONFIGURATION
server {
    if ($host = cloud.linuxdragon.dev) {
        return 301 https://$host$request_uri;
    }


    server_name         cloud.linuxdragon.dev;
    listen 80;
    listen [::]:80;
    return 404;
}

I have a very manageable and replicable system in place already, which is why I do not need or want to use Caddy. When I want to spin up another service on my homelab, I literally add the subdomain to the cert (since I don’t use wildcards for SSL) with Certbot, and copy the nginx configuration file from another service. All I have to change is the name of the new configuration file, the server_name config option, and the port in the proxy_pass config option (homelab is mapped via this system’s /etc/hosts file). Here are the files referenced by the include directive above.

5-reverse_proxy-headers.conf

proxy_http_version                      1.1;
proxy_set_header Upgrade                $http_upgrade;
proxy_set_header Connection             "Upgrade";
proxy_set_header Host                   $http_host;
proxy_set_header X-Forwarded-Host       $server_name;
proxy_set_header X-Real-IP              $remote_addr;
proxy_set_header X-Forwarded-For        $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto      $scheme;
proxy_set_header X-Forwarded-Protocol   $scheme;
proxy_redirect                          off;

0-security-headers.conf

# vim: filetype=nginx
# Security Headers

add_header  X-XSS_Protection            0;
add_header  Strict-Transport-Security   "max-age=31536000; includeSubDomains; preload";
add_header  X-Content-Type-Options      "nosniff";
add_header  Referrer-Policy             "no-referrer";
add_header  Permissions-Policy          "geolocation=(),midi=(),sync-xhr=(),microphone=(),camera=(),magnetometer=(),gyroscope=(),fullscreen=(self),payment=()";

4-container-headers.conf

#vim: filetype=nginx

add_header X-Frame-Options          "SAMEORIGIN";
add_header Content-Security-Policy  "default-src 'none'; base-uri 'self'; form-action 'self'; frame-src 'self'; frame-ancestors 'self'; script-src 'self' blob: 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' https://fonts.codedragon.dev; font-src 'self' data: *; manifest-src 'self' data: *; img-src 'self' data: *; connect-src 'self' wss:;";
add_header X-Robots-Tag             "noindex, noarchive, nofollow";

3-linuxdragon.dev-ssl.conf

# vim: filetype=nginx

# SSL Certificates Paths
ssl_certificate             /etc/letsencrypt/live/linuxdragon.dev/fullchain.pem;
ssl_certificate_key         /etc/letsencrypt/live/linuxdragon.dev/privkey.pem;
ssl_trusted_certificate     /etc/letsencrypt/live/linuxdragon.dev/chain.pem;

0-options-ssl.conf

# vim: filetype=nginx

# Enable session resumption to improve https performance
ssl_session_cache       shared:le_nginx_SSL:10m;
ssl_session_timeout         1440m;
ssl_session_tickets         off;

# Set the ssl server cipher preferences
ssl_protocols           TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers   on;
ssl_ciphers             "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";

#OCSP Stapling
# ssl_dhparam           /etc/letsencrypt/ssl-dhparams.pem;
# ssl_stapling          on;
# ssl_stapling_verify       on;

I compared your nginx config to mine, and googled some of the configs options you have that I don’t. I think you might just need to comment out the “proxy_set_header X-Forwarded-Protocol” line based on this that I found.

As far as I can tell, X-Forwarded-Protocol was replaced by X-Forwarded-Proto, so you don’t need both anyway, but having both can upset gunicorn which is part of seafile.

1 Like

Tysm. I was banging my head against a wall every day after work last week on this problem. Many of my other services do not seem to care, but I have been having intermittent connection issues with HA (also Python based) that this might reaolve those too.

1 Like