Nginx proxying to nginx: getting gzip compression to work¶

At work we use gunicorn as our wsgi runner. Like many, gunicorn advises you to run the nginx webserver in front of it. So on every server we have one or more websites with gunicorn. And an nginx in front.

Nginx takes care, of course, of serving the static files like css and javascript. Some gzipping of the results is a very, very good idea:

server { listen 80 ; server_name my . great . site ; ... gzip on ; gzip_proxied any ; gzip_types text / css text / javascript text / xml text / plain application / javascript application / x - javascript application / json ; .... }

Two notes:

The default is to only gzip html output. We also want javascript and json. So you need to configure gzip_types . (I copy-pasted this from one of my config files, apparently I needed three different javascript mimetypes… Perhaps some further research could strip that number down.)

gzip_proxied any tells nginx that gzipping is fine even for proxied requests.

Proxied requests? Yes, because we have a lot of servers and all external traffic first hits our main nginx proxy. So: we have one central server with nginx that proxies requests to the actual servers. So: nginx behind nginx:

server { listen 443; server_name my.great.site; location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://some-internal-server-name/; } ssl on; ssl_certificate ... }

Pretty standard “I listen on 443/https and proxy it on port 80 to some internal server” setup.

Works like a charm. Only drawback: gzipping does not work.

The reason? nginx defaults, in this case.

The gzip module has a gzip_http_version configuration parameter with a default of 1.1. Which means that http 1.0 requests are not gzipped, only 1.1.

The proxy module has a proxy_http_version configuration parameter with a default of 1.0. Which means that proxied requests are send from the main proxy to the actual webserver with http 1.0.

These two don’t match. There are two solutions:

Set gzip_http_version 1.0 in the nginx configs on your webservers. This switches on gzip for the http 1.0 connections coming from the proxy.

Set proxy_http_version 1.1 on the main proxy so that it sends http 1.1 connections to the webservers.

My choice originally was to do the first one. But a bug report came in for another site and now I’ve switched it on on the main proxy so that all the sites get the benefit.

Note: you might want to make different choices. Perhaps you have a caching proxy halfway? Perhaps you want the main nginx on the proxy to do the gzipping for you? Etcetera. Check whether the above tips apply to your situation :-)