What is the best way to compress backend to nginx reverse proxy data?

We are going to be running a nginx reverse proxy that will pull data from a backend via the internet.

What we mean by via the internet is the backend machine will not be on a lan with the front facing reverse proxy.

We were thinking it would be nice to grip these requests prior to sending them over the internet.

The way I see it it should work something like this:

Client requests content with a accept-encoding header or gzip.

Reverse proxy sends this to the backend server.

Backend compresses this content since a accept encoding header of gzip was sent.

Request sent all the way up the chain compressed.

This we can all do as its pretty straight forward. The question I have is how will this work if we have gzip compression enabled on the nginx reverse proxy side?

Will nginx try to gzip content that is already gzipped?

Hope this makes sense. Thank you.

UPDATE 1:

I understand the implications of caching already (and this serving) gzipped content. We would modify the cache key to include the accept encoding header, and thus serve (and cache) the properly compressed / uncompressed content according to what the user agent can accept.


No, there is no problem with setting gzip on the reverse proxy and the backend server. At least I never had any issues. The proxy will recognize the already gzipped content and simply deliver it.

If you want any content to be gzipped from the backend simply add the appropriate header.

proxy_set_header Accept-Encoding "gzip";

  1. http://nginx.org/en/docs/http/ngx_http_gzip_module.html#gzip_http_version - the HTTP request version required for gzip to compress responses on the back-end is by default 1.1.

  2. http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_http_version - the HTTP request version used by default by the proxy module is 1.0

This means that by default is that your browser GET 1.1 request transforms itself into a GET 1.0 request when proxy requests it from the back-end. The back-end needs 1.1 to perform gzip compression, and so does not compress the response.

My suggestion is to use proxy_http_version 1.1; on the reverse proxy, and the standard gzip on; etc. settings in the back-end server.

There are two additional things to optimize this. One is the setting of 'gzip_static' (an extra module). When a request is made to 'index.html', this setting looks for and delivers an 'index.html.gz' file, if it exists. This has a positive impact on CPU usage, since the compression is not performed on the fly.

As for the other part of your question, what actually gets compressed is set with the gzip_types option. By default, only text/html gets compressed. If you have gzip files, you should be careful to exclude them. If you use the * option (compress everything), then also compressed files will be compressed with gzip before being sent. This isn't optimal for most images (jpg, png, gif), as they have some sort of LZW compression layer already implemented. Compressing a compressed file thus results only in small decrease or even increase of size, while using significant CPU resources to perform the compression. You should carefully examine what you want to compress based on frequency of requests and the type of content that's requested (or it's compression ratio). In terms of images, optimizing them with extra tooling (optipng, etc.) is more effective than turning on gzip compression.