Nginx Gzip Behind Nginx Reverse Proxy
I recently encountered an issue that gzip is not working on static hosted website using nginx which running behind a nginx reverse proxy.
The minimal software architecture is followed:
graph TD
subgraph PN [public network]
A[client] -- https request --> B[reverse proxy]
end
subgraph IN [app network]
subgraph INF [front end]
B -. static content .-> C[web]
end
subgraph INB [back end]
B -. REST API .-> D[api]
B -. image/file assets .-> E[s3]
B -. etc .-> F[...]
end
end
Notices that both reverse proxy
and web
in the graph is setup using nginx.
When setting gzip on
in the web nginx, the nginx gzip setting is not properly
forward to reverse proxy by default(the easiest way to check if gzip is
properly setup by looking at response header in chrome).
Even with the gzip_proxied any
, the gzip is still not working on proxied
request!
So what’s the issue?
- When nginx is config as reverse proxy, the proxy http protocal
proxy_http_version
is set to 1.0 by default. - However, the gzip http protocal
gzip_http_version
is set to 1.1 by default. - The two http version is mismatched, thence the proxied request is not benefit from gzip.
For the solution to this, I suggest set proxy_http_version
to 1.1 for the
reverse proxy configuration.
tl;dr Show me the configuration!
reverse proxy:
server {
listen 80 default;
proxy_http_version 1.1;
location / {
proxy_pass http://web:80;
}
location /api {
proxy_pass http://api:8080/api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
...
}
web:
server {
listen 80 default;
gzip on;
gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml;
gzip_proxied no-cache no-store private expired auth;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_comp_level 9;
gzip_disable "MSIE [1-6]\.";
gzip_vary on;
location / {
root /var/www/html;
try_files $uri $uri/ /index.html;
}
}