iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
Antihost offers Linux VPS plans with full root access, unlimited traffic on a 1 Gbps port and a 14-day free trial.
Enable NGINX gzip in the shared http block, include the active MIME registry, and explicitly list the response types you want compressed. NGINX decides eligibility from the response Content-Type, not from a filename extension. That is why a CSS or JavaScript file can remain uncompressed even when gzip on; is present: its MIME mapping may be missing or overridden, the response may be below gzip_min_length, the client may not have negotiated gzip, or a proxy policy may exclude it.
How NGINX decides whether to compress
The ngx_http_gzip_module is a response filter. With gzip on;, NGINX can compress an eligible response while sending it to a client that advertises gzip support. Two separate decisions are involved:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
- Is gzip enabled? The default is off.
- Is this response type eligible? The default
gzip_typesvalue includes onlytext/html. Additional types must be listed explicitly.
NGINX compares gzip_types with the response MIME value in Content-Type. It does not compare the requested URL’s suffix. A URL ending in .css is compressed only when NGINX maps that file to text/css and that MIME type is listed in gzip_types. An unknown extension that falls back to application/octet-stream will not match a CSS or JavaScript entry.
The request-to-response decision
- The request is routed to a particular
serverandlocationblock. - NGINX determines the response MIME type from the active
typesmappings. If no mapping applies,default_typeis used. - The client request is checked for gzip negotiation, normally the
Accept-Encoding: gzipheader. - NGINX checks the response length against
gzip_min_length. - For an upstream response,
gzip_proxiedcan add another policy decision. - If every condition permits compression, NGINX sends
Content-Encoding: gzip. Withgzip_vary on;, it also sendsVary: Accept-Encodingso caches distinguish compressed and uncompressed variants.
Use a correct baseline configuration
Put shared compression and MIME settings in the active http block unless a narrower scope is deliberate. The following example covers common text, data, vector, font, and WebAssembly responses:
#1 Best Overall
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
gzip on;
gzip_vary on;
gzip_min_length 1000;
gzip_types
text/plain
text/css
text/xml
application/xml
application/json
application/javascript
application/rss+xml
application/atom+xml
image/svg+xml
font/woff
font/woff2
application/wasm;
# server blocks follow here
}
gzip and gzip_types are valid in http, server, and location contexts. Keeping the directives in http gives all virtual hosts the same policy; place them lower only when a particular site or path genuinely needs different behavior. The listed types are added to NGINX’s built-in text/html entry.
What each setting controls
| Directive | Baseline or default | Purpose |
|---|---|---|
gzip |
off | Enables runtime gzip filtering. |
gzip_types |
text/html |
Adds response MIME types eligible for compression; it does not select extensions. |
gzip_vary |
off unless enabled | Adds Vary: Accept-Encoding when enabled, helping caches keep negotiated variants separate. |
gzip_min_length |
module default if omitted | Skips responses shorter than the configured threshold. The example uses 1000. |
gzip_proxied |
no special proxy allowance unless configured | Controls compression decisions for responses received from an upstream proxy. |
default_type |
often text/plain unless set by the package configuration |
Supplies a MIME type when no extension mapping applies. The example deliberately uses application/octet-stream; that fallback will not match the text entries above. |
Enable gzip safely, step by step
1. Find the configuration that is actually loaded
Packages commonly start with a main file such as /etc/nginx/nginx.conf and include files from a conf.d or sites-enabled directory. Do not assume that the file you edited is active. The expanded configuration command in the verification section shows every included file and is the authoritative way to check.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errors2. Add the MIME include and gzip policy
Inside the active http block, ensure the MIME registry is included before the virtual-server definitions, then add the gzip directives from the baseline example. If your distribution stores the registry at a different path, use that package’s existing path rather than creating a second, conflicting registry.
3. Check for narrower overrides
A server or location block can define its own types, default_type, gzip, or gzip_types values. Such a block can make one asset directory behave differently from the rest of the site. Search the expanded configuration for the affected hostname and URI, and remove an accidental override or make the narrower policy complete.
4. Validate before reloading
sudo nginx -t
Proceed only when the command reports a successful syntax and configuration test. Then reload the service using the service manager used by your system, for example:
sudo systemctl reload nginx
A reload applies the new workers without needlessly stopping existing connections. If validation fails, fix the reported file and line first; do not reload a configuration that has not passed nginx -t.
Fix missing or incorrect MIME types
NGINX sets Content-Type from its MIME metadata. The standard registry contains mappings for common web assets, including the following:
| Extension | Expected Content-Type |
Include in gzip_types? |
|---|---|---|
.css |
text/css |
Yes |
.js and modern JavaScript module files |
application/javascript |
Yes |
.json |
application/json |
Yes |
.svg |
image/svg+xml |
Yes |
.woff |
font/woff |
Only when testing shows a worthwhile benefit |
.woff2 |
font/woff2 |
Only when testing shows a worthwhile benefit |
.xml |
application/xml or text/xml, depending on the mapping |
List the value actually returned |
.wasm |
application/wasm |
Yes |
Confirm the mapping before changing it
Request the exact asset and inspect its headers. If a stylesheet returns application/octet-stream, the compression list is not the first problem: the MIME mapping is wrong or not loaded. If it returns text/css but lacks gzip, investigate negotiation, length, proxy policy, or a configuration override instead.
Add a genuinely missing mapping
The safest fix is to add the mapping to the MIME registry that your active configuration already includes, or to correct that registry’s existing entry. A mapping has the form:
types {
application/wasm wasm;
}
Do not place a small replacement types block in a narrow location and assume it augments every inherited mapping. A later types or default_type setting can change the result for that context. After editing, inspect the expanded configuration and test a real response. Once the response has the intended MIME value, add that exact value to gzip_types if it is not already present.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Why adding an extension to gzip_types fails
This does not work:
gzip_types css js json;
gzip_types accepts MIME values, not suffixes. The working form uses values such as text/css, application/javascript, and application/json. Avoid using gzip_types * as a blanket repair: binary files and formats that are already compressed can consume CPU without reducing the payload.
Why CSS or JavaScript is still not compressed
The client did not negotiate gzip
Compression is negotiated per request. A browser normally sends Accept-Encoding: gzip, but a diagnostic client, health check, or intermediary may not. Test with an explicit header so that the result is unambiguous:
curl -sS -D - -o /dev/null -H 'Accept-Encoding: gzip' https://example.com/assets/app.css
Look for both the expected Content-Type and Content-Encoding: gzip. Without the request header, an uncompressed response is expected and does not prove the server policy is broken.
The response is below the minimum length
NGINX can deliberately skip small responses. If the asset is shorter than gzip_min_length, lower the threshold for your workload or test a larger representative file. Do not infer behavior from a tiny development stylesheet when production bundles are much larger.
Free tools Windows power users keep installed
One-click scans. No signup required.
The MIME value does not match
Inspect the returned value character for character. A JavaScript file served as text/plain, application/octet-stream, or an unexpected vendor type will not match application/javascript. Either correct the mapping or add the actual, intentional MIME value to gzip_types; correcting the mapping is preferable because it also fixes browser behavior and caching metadata.
A location or server block overrides the shared policy
Static assets are often handled by a dedicated location. Check that location for gzip off;, its own gzip_types, a replacement types block, or a default_type that catches the files before the normal registry does. Confirm the request is reaching the intended server block by checking the hostname, listen address, and location pattern in the active configuration.
The response comes from an upstream proxy
When NGINX receives a response from an application server, gzip_proxied controls whether that response may be compressed. A policy intended for static files does not automatically permit every proxied response. Inspect the upstream-related headers and configure the directive deliberately, as shown in the next section.
The installed build lacks the gzip module
Run:
nginx -V 2>&1
The build information can reveal whether the HTTP gzip module was disabled with --without-http_gzip_module. The module requires zlib. If it is absent, configuration syntax for gzip cannot provide runtime compression; install a package or build that includes the module, then retest.
Rank #4
Configure compression for reverse-proxied responses
The official administration example uses:
server {
gzip on;
gzip_types text/plain application/xml;
gzip_proxied no-cache no-store private expired auth;
gzip_min_length 1000;
}
gzip_proxied parameters describe conditions under which a proxied response may be compressed. For example, the listed policy permits compression when cache-control indicates no-cache, no-store, or private, when the response is expired, or when authorization is involved. The correct choice depends on how your proxy and cache are designed; copying the list without checking those semantics can create inconsistent cache behavior.
For a proxied failure, capture Via, Cache-Control, Expires, Last-Modified, and ETag along with Content-Type and Content-Encoding. Those headers show whether NGINX recognized an upstream response and which cache conditions influenced the decision. If an intermediary rewrites or strips Vary, fix that cache layer as well as the NGINX setting.
Runtime gzip versus precompressed .gz files
Runtime gzip and gzip_static solve different operational problems:
| Approach | How it works | Main cost | Requirements and trade-offs |
|---|---|---|---|
| Runtime gzip | gzip on; compresses eligible responses as they are sent. |
CPU work on request paths and potentially variable output timing. | Uses the normal gzip module and zlib; simple for dynamic or changing content. |
| Precompressed delivery | gzip_static on; looks for a matching file ending in .gz and serves it to a gzip-capable client. |
Build or deployment storage and generation time instead of per-request compression. | Requires the optional static module and a correctly generated, deployed .gz alongside the original. |
How gzip_static behaves
gzip_static does not perform on-the-fly compression. It merely uses a file compressed beforehand by a compatible tool. If the client does not support gzip, or the matching .gz file is absent or unsupported, NGINX sends the uncompressed original.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →The module is not built by default. A build must include --with-http_gzip_static_module. Check with nginx -V before adding the directive. Generate files during your asset build or deployment, for example with the system gzip command, and deploy the original and compressed versions together. Keeping their modification times aligned is recommended by the module documentation so that freshness checks remain coherent.
Precompression is attractive for large, immutable bundles because output is reproducible and request-time CPU use is removed. Runtime gzip is usually simpler for responses generated at request time. In either model, the MIME type and client negotiation still have to be correct.
Best Value
Verify the active configuration and negotiated headers
Inspect every included file
sudo nginx -T
This prints the fully expanded configuration, including files pulled in by include. Search it for the affected server name, the asset location, mime.types, default_type, gzip_types, and gzip_proxied. This often exposes a duplicate virtual host or later override that is invisible when looking at one file in isolation.
Test the response directly
curl -sS -D - -o /dev/null -H 'Accept-Encoding: gzip' https://example.com/assets/app.js
A successful negotiated response should show a JavaScript MIME type and Content-Encoding: gzip. When gzip_vary on; is active, it should also show Vary: Accept-Encoding. Test a CSS file, a JSON response, and an SVG or WebAssembly asset separately; one correct result does not prove every location uses the same mappings.
Compare with a request that does not advertise gzip
curl -sS -D - -o /dev/null https://example.com/assets/app.js
The second request should normally lack Content-Encoding: gzip. This confirms that NGINX is negotiating rather than blindly labeling every response as compressed. If both requests have the same result, inspect the request path, the client header, and any intermediary cache.
Performance and security boundaries
Do not spend CPU on formats that are already compressed
JPEG, PNG, MP4, ZIP, and similar binary formats generally contain their own compression. Adding them to gzip_types often increases CPU use with little or no size reduction. Keep the list focused on text and other formats for which testing demonstrates a benefit.
Account for runtime overhead
Runtime compression reduces transmitted bytes but adds processing work at request time. The useful balance depends on response size, traffic, CPU capacity, and whether the content is dynamic. Precompress immutable assets when build complexity and storage are acceptable; use runtime gzip where content cannot conveniently be generated ahead of time.
Consider BREACH exposure
The NGINX gzip documentation warns that compressed responses sent over SSL/TLS can be vulnerable to BREACH-style attacks. Treat pages that combine secrets with attacker-controlled input differently from ordinary static assets. Review whether sensitive responses should be compressed, and apply the decision consistently across the application and proxy layers.
Recommended Free Tools
Production checklist
- The active
httpblock includes the intended MIME registry. gzip on;is enabled in the scope serving the asset.- The response’s actual
Content-Typeappears ingzip_types. - No narrower
types,default_type, orgzip off;override changes that location. - The test request sends
Accept-Encoding: gzip. - The response is at least as large as the configured
gzip_min_length. - Proxy responses have a deliberate
gzip_proxiedpolicy based on their cache headers. nginx -tpasses before reload, andnginx -Tconfirms the expanded configuration.nginx -Vconfirms the runtime gzip module; use the separate static-module check before enablinggzip_static.- Verification checks
Content-Type,Content-Encoding, and, when enabled,Vary: Accept-Encoding.
Choosing the final setup
For most NGINX sites, start with the shared configuration shown above, correct the MIME registry, and verify real responses with curl. Use runtime gzip for dynamic output and for the simplest deployment. Use gzip_static for generated, cacheable assets when your NGINX build includes the optional module and your deployment process can keep original and .gz files synchronized. In both cases, correctness begins with the MIME type NGINX actually sends, not the extension visible in the URL.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

