Nginx + reverse proxy issues

Currently have two setups both using reverse proxies. One is with apache24 and I’m a bit more familiar with. The other nginx which I am converting my all my services to. There are two hosts, one at 127.0.10.3 which is the seafile server. The web server with nginx and apache24 is at 127.0.10.1. This is running on FreeBSD 11-STABLE.

The apache configuration works perfectly. Here is the config:
vhost.conf:
<VirtualHost *:443>
ServerName seafile.domain.com
ServerAlias seafile.domain.com
TransferLog “/var/log/httpd-access.log”

  Protocols h2 http/1.1
  Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
  
  RewriteEngine On
  ProxyPass /seafhttp http://127.0.10.3:8082
  ProxyPassReverse /seafhttp http://127.0.10.3:8082
  RewriteRule ^/seafhttp - [QSA,L]
  SetEnvIf Request_URI . proxy-fcgi-pathinfo=unescape
  SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
# The .well-known is for letsencrypt
  ProxyPassMatch ^(?!/.well-known) fcgi://127.0.10.3:8000
  SSLEngine on
  SSLCertificateFile "/usr/local/etc/letsencrypt/live/seafile.domain.com/cert.pem"
  SSLCertificateKeyFile "/usr/local/etc/letsencrypt/live/seafile.domain.com/privkey.pem"
  SSLCACertificateFile "/usr/local/etc/letsencrypt/live/seafile.domain.com/chain.pem"
</VirtualHost>

So i’v been using this for quite awhile and it works perfectly. With nginx, I ran into one issue. The /seafhttp proxy is returning this:
HTTP/1.0 400 Bad Request
Content-Type: text/plain
I tried different configurations and just couldn’t figure out why this error is occurring. I decided to get rid of my complex config and provide a simple one and it still fails. Here is the simple config.

nginx.conf:
#user nobody;
worker_processes 1;

# This default error log path is compiled-in to make sure configuration parsing
# errors are logged somewhere, especially during unattended boot when stderr
# isn't normally logged anywhere. This path will be touched on every nginx
# start regardless of error log location configured here. See
# https://trac.nginx.org/nginx/ticket/147 for more info.
#
#error_log  /var/log/nginx/error.log;
#

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

server {
        listen       80;
        server_name  seafile.domain.com;
        rewrite ^ https://$http_host$request_uri? permanent;    # force redirect http to https
        server_tokens off;
    }
    server {
        listen 443;
        ssl on;
        ssl_certificate /usr/local/etc/letsencrypt/live/seafile.domain.com/cert.pem;        # path to your cacert.pem
        ssl_certificate_key /usr/local/etc/letsencrypt/live/seafile.domain.com/privkey.pem;    # path to your privkey.pem
        ssl_trusted_certificate /usr/local/etc/letsencrypt/live/seafile.domain.com/chain.pem;
        server_name seafile.domain.com;
        ssl_session_timeout 5m;
        ssl_session_cache shared:SSL:5m;

        # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
#        ssl_dhparam /etc/nginx/dhparam.pem;

        # secure settings (A+ at SSL Labs ssltest at time of writing)
        # see https://wiki.mozilla.org/Security/Server_Side_TLS#Nginx
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:EC
DHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES128
-SHA:DHE-RSA-SEED-SHA:DHE-RSA-CAMELLIA128-SHA:HIGH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS';
        ssl_prefer_server_ciphers on;

        proxy_set_header X-Forwarded-For $remote_addr;

        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
        server_tokens off;

        location / {
            fastcgi_pass    127.0.10.3:8000;
            fastcgi_param   SCRIPT_FILENAME     $document_root$fastcgi_script_name;
            fastcgi_param   PATH_INFO           $fastcgi_script_name;

            fastcgi_param   SERVER_PROTOCOL        $server_protocol;
            fastcgi_param   QUERY_STRING        $query_string;
            fastcgi_param   REQUEST_METHOD      $request_method;
            fastcgi_param   CONTENT_TYPE        $content_type;
            fastcgi_param   CONTENT_LENGTH      $content_length;
            fastcgi_param   SERVER_ADDR         $server_addr;
            fastcgi_param   SERVER_PORT         $server_port;
            fastcgi_param   SERVER_NAME         $server_name;
            fastcgi_param   REMOTE_ADDR         $remote_addr;
            fastcgi_param   HTTPS               on;
            fastcgi_param   HTTP_SCHEME         https;

            access_log      /var/log/nginx/seahub.access.log;
            error_log       /var/log/nginx/seahub.error.log;
            fastcgi_read_timeout 36000;
            client_max_body_size 0;
        }
        location /seafhttp {
            rewrite ^/seafhttp(.*)$ $1 break;
            proxy_pass http://127.0.10.3:8082;
            client_max_body_size 0;
            proxy_connect_timeout  36000s;
            proxy_read_timeout  36000s;
            proxy_send_timeout  36000s;
            send_timeout  36000s;
        }
    }
}

If anyone has an idea why the nginx config is failing I would appreciate it!

Best regards,
Ultima

I found the issue, it seems that nginx proxy http version defaults to 1 and http 1.0 does not support Transfer-Encoding type chunked. The fix is bumping the version to 1.1 like so:

proxy_http_version 1.1;

This should probably be added to docs.

1 Like