The Best Price for IPv4/IPv6 Lease – Any RIR & Any Geo-LocationOrder Now
Hostperl

Configure Nginx Gzip Compression on Ubuntu VPS

By Raman Kumar

Share:

Updated on Jun 30, 2026

Configure Nginx Gzip Compression on Ubuntu VPS

Why Gzip Compression Belongs on Every Production VPS

Uncompressed web responses are one of the most common causes of slow page loads that nobody investigates. If your Ubuntu VPS is serving HTML, CSS, JavaScript, or JSON without compression, browsers are downloading files two to five times larger than they need to be. For a typical WordPress or application page, that's the difference between a 400 KB payload and a 90 KB one.

Nginx has built-in gzip support, and enabling it costs almost nothing in CPU overhead while delivering measurable improvements to Time to First Byte (TTFB) and overall page weight. This tutorial walks through the full setup — from the core config block to testing that compression is actually working — on Ubuntu 22.04 or 24.04.

What You'll Need Before You Start

  • An Ubuntu VPS with Nginx installed (any version from 1.18 onward works)
  • Root or sudo SSH access
  • A domain or IP address you can send test requests to

If you're running a shared hosting plan and hitting limits around performance or config access, this kind of tuning is one of the clearest signals that a move to a VPS is worth it. The cPanel shared hosting limits guide covers that decision in detail.

Step 1 — Locate Your Nginx Configuration Files

On Ubuntu, Nginx config lives in /etc/nginx/. The main file is nginx.conf, and site-specific configs sit under /etc/nginx/sites-available/. Gzip settings belong in the http block, which means they usually go into the main nginx.conf or a dedicated include file.

Check what's already in your nginx.conf:

sudo nano /etc/nginx/nginx.conf

Look for an existing gzip on; line. Many default Nginx installs include a commented-out gzip block. You'll either uncomment and extend it, or add a new block entirely.

Step 2 — Add the Gzip Configuration Block

Inside the http { } block in nginx.conf, add or update the following. This is a solid production-ready set of directives:

##
# Gzip Settings
##

gzip on;
gzip_disable "msie6";

gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;

gzip_types
  application/atom+xml
  application/geo+json
  application/javascript
  application/x-javascript
  application/json
  application/ld+json
  application/manifest+json
  application/rdf+xml
  application/rss+xml
  application/vnd.ms-fontobject
  application/wasm
  application/x-web-app-manifest+json
  application/xhtml+xml
  application/xml
  font/eot
  font/otf
  font/ttf
  image/bmp
  image/svg+xml
  text/cache-manifest
  text/calendar
  text/css
  text/javascript
  text/markdown
  text/plain
  text/vcard
  text/vnd.rim.location.xloc
  text/vtt
  text/x-component
  text/x-cross-domain-policy
  text/xml;

A few things worth explaining here:

  • gzip_comp_level 6 — A value between 5 and 6 is the practical sweet spot. Level 9 gives marginally smaller files but burns noticeably more CPU. Level 1 is fast but underwhelming on compression ratios.
  • gzip_min_length 256 — Compressing files smaller than 256 bytes wastes CPU and can actually increase the payload size due to header overhead. This threshold is sensible for most traffic.
  • gzip_vary on — Adds a Vary: Accept-Encoding response header. Essential if your content passes through a CDN or caching proxy, otherwise the cache may serve compressed content to clients that don't support it.
  • gzip_proxied any — Enables compression for proxied requests. If you're running Nginx in front of a PHP-FPM, Node, or Python backend, you want this on.

Notice that image/jpeg, image/png, and image/webp are not in the list. Those formats are already compressed. Adding them wastes CPU with no benefit.

Step 3 — Test and Reload Nginx

Always validate your config before reloading. A syntax error will take Nginx down on reload.

sudo nginx -t

You should see:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

If it passes, reload without dropping active connections:

sudo systemctl reload nginx

Step 4 — Verify Gzip Is Working

Don't skip this. Configs can look correct and still not compress responses — usually because a content type was missed or a nested server block overrides the http-level setting.

Use curl to check directly from your server or your local terminal:

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

Look for this in the response headers:

Content-Encoding: gzip

If you see it, compression is live. If you don't, check whether the URL returns a content type that's in your gzip_types list. HTML from the root URL is typically text/html — which Nginx compresses by default regardless of the gzip_types directive, so that's a good first test.

For a more thorough check, use the --compressed flag to also verify the response decompresses cleanly:

curl --compressed -o /dev/null -s -w "%{size_download} bytes downloaded\n" https://yourdomain.com/

Compare that against a request without the flag to see actual compression savings on your content.

Per-Site Overrides in Server Blocks

Sometimes you'll want to enable or disable gzip differently per domain. You can add gzip directives directly inside a server { } or location { } block, and they'll override the global settings.

For example, to disable compression for a specific API endpoint that already handles its own encoding:

location /api/binary-stream {
  gzip off;
  proxy_pass http://127.0.0.1:8080;
}

Or to enable compression only for a specific virtual host and leave others uncompressed:

server {
  listen 80;
  server_name assets.example.com;

  gzip on;
  gzip_comp_level 5;
  gzip_types text/css application/javascript image/svg+xml;
}

If you're running multiple sites under Nginx, the virtual host setup guide covers the block structure in detail — the principles translate directly to Nginx server blocks.

Combining Gzip with Static File Caching

Gzip handles the transfer size. Browser caching handles repeat visits. Both together make a bigger difference than either alone.

Add a location block that sets cache headers for common static assets:

location ~* \.(css|js|svg|woff2|ico)$ {
  expires 30d;
  add_header Cache-Control "public, no-transform";
}

The no-transform directive tells intermediate proxies not to re-encode the content — important when you're also using gzip, since double-encoding can corrupt files.

A Note on Security Headers and Compression

If you've already configured security headers on your VPS, make sure your gzip setup doesn't conflict with any add_header directives in nested blocks. In Nginx, add_header in a child block (like location) replaces all headers set in parent blocks — not supplements them. This is a common source of headers silently disappearing.

The ModSecurity WAF setup guide includes examples of header management alongside other Nginx directives that are worth reviewing if you're running a hardened config.

Troubleshooting Common Gzip Problems

Compression works for HTML but not CSS or JS
Check that text/css and application/javascript are in your gzip_types list. Note that text/javascript and application/javascript are different MIME types — include both to cover all servers and content types.

CDN shows uncompressed responses
Make sure gzip_vary on is set. Without the Vary: Accept-Encoding header, CDNs like Cloudflare may cache the first response they receive (possibly uncompressed) and serve it to all clients.

Nginx returns an error after reload
Run sudo nginx -t and check for syntax issues. Also run sudo journalctl -u nginx --since "5 minutes ago" to see the actual error message. A missing semicolon or a typo in a MIME type will cause a config parse failure.

Gzip not applying to proxied responses
If Nginx is proxying to a backend app (Node, PHP-FPM, etc.) and compression isn't showing on those responses, ensure gzip_proxied any; is set and that the backend isn't already setting a Content-Encoding header itself. Double-encoding will cause the response to fail.

Running this on a Hostperl VPS gives you full root access to your Nginx config — no restrictions, no ticket requests to enable compression. Our managed and unmanaged VPS plans come with Ubuntu 22.04 and 24.04 support, SSD storage, and NZ-based support you can actually reach. If your traffic has outgrown shared hosting, the VPS vs shared hosting comparison is a practical place to start the decision.

Frequently Asked Questions

Does enabling gzip compression affect server CPU usage significantly?

At compression level 6, the CPU overhead is minimal on most VPS workloads. You'd need to be serving thousands of simultaneous large responses before it becomes measurable. The bandwidth savings almost always outweigh it.

Should I use gzip or Brotli on Nginx?

Brotli offers slightly better compression ratios than gzip (typically 10–20% smaller on text assets) but requires the ngx_brotli module, which isn't included in standard Nginx packages. Gzip works out of the box and is supported by every browser in use. If you need Brotli, enable both — serve Brotli to clients that request it and fall back to gzip for others.

Will gzip compression break any file types?

No, as long as you stick to compressible content types. Nginx won't compress already-compressed formats like JPEG, PNG, WebP, or ZIP if you don't include them in gzip_types. The configuration above explicitly excludes binary and pre-compressed formats.

How do I confirm my compression ratio for a specific file?

Run: curl -H "Accept-Encoding: gzip" https://yourdomain.com/style.css | wc -c for compressed size, then compare against curl https://yourdomain.com/style.css | wc -c without the header. The ratio between the two figures tells you how much bandwidth gzip is saving on that asset.