Nginx Compression Configuration Guide

Enable gzip, Brotli, and zstd compression for optimal performance

Quick Start: Basic Gzip Configuration

Add this to your nginx.conf file in the http block for immediate compression benefits:

http {
    # Enable gzip compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/javascript
        application/json
        application/xml+rss
        application/xhtml+xml
        application/x-font-ttf
        application/x-font-opentype
        application/vnd.ms-fontobject
        image/svg+xml
        image/x-icon;
    gzip_min_length 1000;
    gzip_disable "msie6";
}

Verify Configuration

# Test configuration
nginx -t

# Reload Nginx
nginx -s reload

# Test compression
curl -H "Accept-Encoding: gzip" -I https://yourdomain.com

Gzip Configuration Options Explained

gzip on/off

Enables or disables gzip compression

gzip on;

gzip_comp_level

Compression level 1-9. Level 6 is optimal for most cases

gzip_comp_level 6;

gzip_min_length

Minimum file size to compress (in bytes)

gzip_min_length 1000;

gzip_vary

Adds "Vary: Accept-Encoding" header

gzip_vary on;

gzip_proxied

Compress responses for proxied requests

gzip_proxied any;

gzip_types

MIME types to compress

gzip_types text/css;

Advanced: Brotli Compression

Brotli provides 20-26% better compression than gzip. Here's how to enable it:

1. Install Brotli Module

# For Ubuntu/Debian
apt-get install nginx-module-brotli

# For CentOS/RHEL
yum install nginx-module-brotli

# Or compile from source
git clone https://github.com/google/ngx_brotli.git
cd nginx-1.x.x
./configure --add-dynamic-module=../ngx_brotli
make modules

2. Load Brotli Modules

# Add to top of nginx.conf
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;

3. Configure Brotli

http {
    # Brotli Settings
    brotli on;
    brotli_comp_level 6;
    brotli_static on;
    brotli_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/javascript
        application/json
        application/xml+rss
        application/xhtml+xml
        application/x-font-ttf
        application/x-font-opentype
        application/vnd.ms-fontobject
        image/svg+xml
        image/x-icon;
    
    # Keep gzip as fallback
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types $brotli_types;
}

Static Pre-compression

Serve pre-compressed files to save CPU cycles:

Enable Static Gzip

location / {
    gzip_static on;
    brotli_static on;
    try_files $uri $uri/ =404;
}

Pre-compress Files

# Gzip all static files
find /var/www/html -type f \( -name "*.html" -o -name "*.css" -o -name "*.js" \) \
    -exec gzip -9 -k {} \;

# Brotli compress all static files
find /var/www/html -type f \( -name "*.html" -o -name "*.css" -o -name "*.js" \) \
    -exec brotli -q 11 -k {} \;

Automated Pre-compression Script

#!/bin/bash
# precompress.sh - Run after deployment

WEBROOT="/var/www/html"
FILETYPES="html css js json xml svg"

for type in $FILETYPES; do
    echo "Compressing .$type files..."
    find "$WEBROOT" -name "*.$type" -type f | while read file; do
        # Skip if already compressed
        [ -f "$file.gz" ] || gzip -9 -k "$file"
        [ -f "$file.br" ] || brotli -q 11 -k "$file"
    done
done

echo "Pre-compression complete!"

Location-Specific Compression

Fine-tune compression for different content types:

API Endpoints

location /api/ {
    # Lower compression for dynamic content
    gzip_comp_level 1;
    brotli_comp_level 1;
    
    # Compress JSON responses
    gzip_types application/json;
    brotli_types application/json;
}

Static Assets

location ~* \.(css|js|html|xml)$ {
    # Higher compression for static files
    gzip_comp_level 9;
    brotli_comp_level 6;
    
    # Serve pre-compressed if available
    gzip_static on;
    brotli_static on;
    
    # Cache headers
    expires 1y;
    add_header Cache-Control "public, immutable";
}

Images and Binary Files

location ~* \.(jpg|jpeg|png|gif|ico|webp|woff|woff2)$ {
    # Don't compress already compressed formats
    gzip off;
    brotli off;
    
    expires 1y;
    add_header Cache-Control "public, immutable";
}

Performance Optimization Tips

Buffer Sizes

Optimize compression buffers for your workload:

gzip_buffers 16 8k;
brotli_window 512k;

CPU vs Compression

Balance CPU usage with compression ratio:

  • Dynamic content: Level 1-4
  • Static content: Level 5-6
  • Pre-compressed: Level 9-11

Monitoring

Track compression effectiveness:

log_format compression '$remote_addr - $remote_user [$time_local] '
    '"$request" $status $bytes_sent '
    '"$http_referer" "$http_user_agent" "$gzip_ratio"';

access_log /var/log/nginx/compression.log compression;

Complete Production Configuration

Here's a comprehensive Nginx compression configuration for production:

# Load Brotli modules (if installed)
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;

http {
    # Gzip Settings
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_min_length 1000;
    gzip_disable "msie6";
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        text/x-component
        text/x-json
        application/javascript
        application/x-javascript
        application/json
        application/ld+json
        application/manifest+json
        application/xml+rss
        application/xhtml+xml
        application/x-font-ttf
        application/x-font-opentype
        application/vnd.ms-fontobject
        font/opentype
        image/svg+xml
        image/x-icon;

    # Brotli Settings
    brotli on;
    brotli_comp_level 6;
    brotli_static on;
    brotli_types $gzip_types;

    # Server configuration
    server {
        listen 443 ssl http2;
        server_name example.com;

        # SSL configuration (required for Brotli)
        ssl_certificate /path/to/cert.pem;
        ssl_certificate_key /path/to/key.pem;

        # Root directory
        root /var/www/html;

        # Default location
        location / {
            try_files $uri $uri/ =404;
            
            # Enable pre-compressed file serving
            gzip_static on;
            brotli_static on;
        }

        # API endpoints - fast compression
        location /api/ {
            gzip_comp_level 1;
            brotli_comp_level 1;
            
            proxy_pass http://backend;
            proxy_set_header Accept-Encoding "";
        }

        # Static assets - maximum compression
        location ~* \.(css|js|html|xml|json|svg)$ {
            gzip_comp_level 9;
            brotli_comp_level 6;
            gzip_static on;
            brotli_static on;
            
            expires 1y;
            add_header Cache-Control "public, immutable";
        }

        # Already compressed formats
        location ~* \.(jpg|jpeg|png|gif|webp|ico|woff|woff2|ttf|otf|eot|mp4|webm|zip|gz|br)$ {
            gzip off;
            brotli off;
            
            expires 1y;
            add_header Cache-Control "public, immutable";
        }
    }
}

Troubleshooting Common Issues

Compression Not Working

  • Check if module is loaded: nginx -V 2>&1 | grep -o with-http_gzip_module
  • Verify MIME types are correct
  • Ensure file size is above gzip_min_length
  • Check for conflicting headers from upstream

High CPU Usage

  • Lower compression levels for dynamic content
  • Use pre-compressed files for static assets
  • Implement caching to reduce compression frequency
  • Consider upgrading server resources

Testing Commands

# Check if gzip is working
curl -H "Accept-Encoding: gzip" -I https://example.com/style.css | grep -i content-encoding

# Check if Brotli is working
curl -H "Accept-Encoding: br" -I https://example.com/style.css | grep -i content-encoding

# Compare file sizes
curl -s -H "Accept-Encoding: identity" https://example.com/app.js | wc -c
curl -s -H "Accept-Encoding: gzip" https://example.com/app.js | wc -c
curl -s -H "Accept-Encoding: br" https://example.com/app.js | wc -c

Next Steps

Now that you've configured compression on Nginx, explore these related topics: