Master Nginx Static Site Performance: Caching, Gzip, CORS & Anti‑Hotlinking

This article consolidates practical solutions for configuring Nginx to serve high‑performance static websites, covering cache control, gzip compression, cross‑origin resource sharing, and anti‑hotlinking techniques, complete with code examples and detailed explanations of underlying principles.

Top Architect
Top Architect
Top Architect
Master Nginx Static Site Performance: Caching, Gzip, CORS & Anti‑Hotlinking

Overview

This blog summarizes common issues and solutions when configuring Nginx for high‑performance static sites, covering caching, Gzip compression, cross‑origin resource sharing, and anti‑hotlinking.

Nginx configuration for high‑performance static website

Cache

Proper cache settings let browsers reuse previously fetched resources, reducing latency and improving user experience.

Cache‑Control header values: no-cache for negative values, max-age=time for positive or zero values.

location ~* \.(jpg|jpeg|png|gif)$ {
    expires 30d;
}
# expires 30s;  # cache 30 seconds
# expires 30m;  # cache 30 minutes
# expires 2h;   # cache 2 hours
# expires 30d;  # cache 30 days

Principle Analysis

Principle and steps:

User requests a resource for the first time; no cache exists.

Server responds with 200 and includes caching headers.

Subsequent requests check the browser cache.

If no cached file, repeat step 2.

If cached, evaluate expiration via Expires.

If not expired, serve from local cache.

If expired, compare ETag and Last‑Modified.

If unchanged, server returns 304 and client uses cached file.

If changed, fetch fresh data and store according to cache‑control directives.

Cache Header Explanation

Browser cache involves two mechanisms: strong cache (Expires, Cache‑Control) and conditional cache (ETag, Last‑Modified).

Strong cache rules: Server sends Expires and Cache‑Control; Cache‑Control has higher priority.

Expires: HTTP/1.0 header; specifies absolute expiration time; superseded by Cache‑Control in HTTP/1.1.

Cache‑Control parameters: control max‑age, public/private, no‑store, etc.

location ~* \.(css|js)$ {
    expires 7d;
    add_header Cache-Control "public";
}

Alternative configuration:

location ~* \.(css|js)$ {
    expires 600;
    add_header Cache-control max-age=800;
}

Example response headers from a browser request:

HTTP/1.1 304 Not Modified
Server: nginx
Date: Sun, 11 Aug 2024 12:46:58 GMT
Last-Modified: Fri, 09 Aug 2024 10:03:08 GMT
ETag: "66b5e95c-2c7"
Expires: Mon, 12 Aug 2024 12:46:58 GMT
Cache-Control: max-age=86400
Cache-Control: public

Gzip Module

Enabling gzip compresses responses, reducing transferred data size and speeding up page loads.

location ~ .*(jpg|gif|png|js)$ {
    gzip on;
    gzip_http_version 1.1;
    gzip_comp_level 2; # compression level 1‑9
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif img/png;
}

CORS and Anti‑Hotlinking

These settings improve security by allowing only authorized origins and preventing other sites from hot‑linking static resources.

server {
    listen 80;
    server_name www.stark.com;

    location / {
        add_header 'Access-Control-Allow-Origin' 'http://stark1.com https://stark2.com';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'User-Agent,Keep-Alive,Content-Type';
        add_header 'Access-Control-Max-Age' 1728000;

        if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'User-Agent,Keep-Alive,Content-Type';
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Type' 'text/plain charset=UTF-8';
            add_header 'Content-Length' 0;
            return 204;
        }
    }
}

Anti‑hotlinking checks the Referer header; if invalid, the request is denied.

server {
    listen 80;
    server_name yourdomain.com;

    location / {
        root /path/to/your/files;
        valid_referers none blocked server_names *.yourdomain.com;
        if ($invalid_referer) {
            return 403;
        }
    }
}
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendcachingCORSNginxGzipanti-hotlinking
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.