How to enable gzip on proxy servers on nginx

I use often Gunicorn as web server for django applications.

Usually I use Apache but I’m starting to use nginx as webserver to serve both the static files and the proxied gunicorn response.

I need to do something like what I’ve done with Apache to compress the response after I received from django since I’ve noticed that in my case compressing it before using @gzip_page decorator is more detrimental to performance than doing it after.

Here an essential mysite.conf to put in /etc/nginx/conf.d.

server {
    listen      80;
    server_name .example.com other.domain.example.com;
    charset     utf-8;
    # max upload size
    client_max_body_size 75M;
    # Enable gzip for proxied requests and static files
    gzip on;
    gzip_proxied any;
    gzip_vary on;
    gzip_http_version 1.1;
    gzip_types application/javascript application/json text/css text/xml;
    gzip_comp_level 4;
    # Serve static files via nginx
    location /media  {
        alias /usr/local/etc/files/mysite/media_root;
    }
    location /static {
        alias /usr/local/etc/files/mysite/static_root;
    }
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        # Serve dynamic requests via gunicorn on custom port (e.g. 8585)
        # and gzip the response
        if (!-f $request_filename) {
            proxy_pass http://localhost:8585;
            break;
        }
    }
}

In this way, content by Gunicorn is served to nginx and before to send it to client nginx gzip it, here with a compression level of 4 of 9. A compression between 1 and 4 is generally acceptable for any text content, avoiding to stress the CPU too much for a small compression gain.

Even the static files like css and javascript are served compressed for client with HTTP 1.1 support. You can add more type to compress including the mime type on the gzip_types row.

Read also on the same topic: How to enable gzip on proxy servers on Apache

Reference:

How to enable gzip on proxy servers on Apache

I’m starting to use the gunicorn django app using supervisord. Here my configuration:

  • Varnish: port 80
  • Apache: port 8080
  • gunicorn: port 4180 (/path/to/my/manage.py run_gunicorn localhost:4180)

Only the port 80 is exposed to other clients than localhost. The Varnish default backend is Apache (localhost:8080). I have a Drupal installation and a django installation on the same machine: since I want to expose django on the same domain at a defined location, I add to Apache this location:

ProxyRequests Off
ProxyPreserveHost On

Order deny,allow
Allow from all

# on port 4180 gunicorn is running
# @see /etc/supervisor.conf
ProxyPass /foo http://localhost:4180/
ProxyPassReverse /foo http://localhost:4180/
Order allow,deny
Allow from all
AddOutputFilterByType DEFLATE text/html

You can omit AddOutputFilterByType DEFLATE text/html: here I just take the response from gunicorn, compress and then serve to the client in this way:

(client) -> varnish -> apache -> gunicorn

(client)
                (X-Varnish-Cache: MISS) 

Here an example of what I get:
Image

It’s a big page, but using gzip from 2.2 MB of the uncompressed page I get 417 KB gzipped text/html, less than 1/4 of the original!

Read also on the same topic: How to enable gzip on proxy servers on nginx

Improve Drupal performance

I use YSlow to check a Drupal site performance. Here some tips to get an A with Drupal 5.x.

Step 1: Fewer HTTP requests:

  • Aggregate CSS (/admin/settings/performance)
  • Aggregate JS with Javascript Aggregator (experimental). To avoid JavaScript errors in some modules (i.e. TinyMCE), you can use the dirscard list patch by derjochenmeyer on the dev version (it’ll be added to the next release). To Drupal 6.x users: Drupal 6.x comes with a native JS Aggregator support, so you don’t need an additional module.
  • Reduce CSS background images: select carefully your theme.

Step 2: Compress pages on-the-fly:
Many modern browsers support Gzip compression. Through .htaccess, you can tell your server to serve gzipped HTML pages, JavaScript and CSS files (or any other text file, since images like JPG and PNG are compressed natively). You can use two approach, depending on your server settings, just add on bottom of your .htaccess:

  1. PHP flag method (compress only php served pages):
    # via-PHP compression (only with compatible browsers)
    php_flag zlib.output_compression On
  2. Apache mod_deflate method (preferred method where available)
    # Enable file compression by MIME type
    AddOutputFilterByType DEFLATE text/html text/plain text/xml
    AddOutputFilterByType DEFLATE application/x-javascript
    AddOutputFilterByType DEFLATE text/javascript
    AddOutputFilterByType DEFLATE text/css
    # Exclude Not compatible browsers (uncomment to activate)
    # BrowserMatch ^Mozilla/4 gzip-only-text/html
    # BrowserMatch ^Mozilla/4\.0[678] no-gzip
    # BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

    Using this method, you can compress HTML pages, JavaScript, CSS files specifying ;MIME type

See also / references