Back to site

Nginx static cache

Configure Nginx static file caching and cache headers on a HolyCloud VPS to speed up your sites.

Nginx static cache

On a HolyCloud Linux VPS serving sites with Nginx, optimizing static file caching (CSS, JS, images, fonts) reduces CPU load and improves load times. This guide combines expires / Cache-Control headers and an optional proxy cache zone.

Prerequisites

  • Nginx installed and a working site on the HolyCloud VPS
  • sudo access
  • HTTPS domain recommended (Certbot)

Step 1: browser cache headers (versioned assets)

Edit the virtual host:

sudo nano /etc/nginx/sites-available/example.com

Block for common static files:

location ~* \.(?:css|js|jpg|jpeg|gif|png|ico|svg|webp|woff2?|ttf|eot)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
    access_log off;
    try_files $uri =404;
}

For assets without a hash in the filename (stale cache risk), use a shorter duration:

expires 7d;
add_header Cache-Control "public";

Test and reload:

sudo nginx -t
sudo systemctl reload nginx

Check headers:

curl -I https://www.example.com/assets/style.css

Look for Cache-Control and Expires.

Step 2: gzip / gzip_static

Compression on Nginx:

gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;

If you pre-generate .gz at build time:

gzip_static on;

Step 3: proxy cache zone (reverse proxy)

Useful when Nginx on the HolyCloud VPS proxies to an app (Node, PHP-FPM HTTP upstream, another port).

Create directories:

sudo mkdir -p /var/cache/nginx/proxy
sudo chown www-data:www-data /var/cache/nginx/proxy

In /etc/nginx/nginx.conf, http block:

proxy_cache_path /var/cache/nginx/proxy
    levels=1:2
    keys_zone=STATIC:10m
    max_size=500m
    inactive=7d
    use_temp_path=off;

In the server block:

location /static/ {
    proxy_pass http://127.0.0.1:3000;
    proxy_cache STATIC;
    proxy_cache_valid 200 7d;
    proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
    add_header X-Cache-Status $upstream_cache_status;
}

Step 4: open_file_cache (local files)

Reduces system calls for high-traffic sites on the same VPS:

open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;

Place these directives in the http block of nginx.conf.

Step 5: security and dynamic HTML

Do not set long cache on HTML/API:

location / {
    add_header Cache-Control "no-store, no-cache, must-revalidate";
    try_files $uri $uri/ /index.php?$query_string;
}

With PHP-FPM:

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.2-fpm.sock;
    add_header Cache-Control "no-store";
}

Step 6: purge and monitoring

Proxy cache size:

sudo du -sh /var/cache/nginx/proxy

Manual purge:

sudo rm -rf /var/cache/nginx/proxy/*
sudo systemctl reload nginx

Logs with cache status:

sudo tail -f /var/log/nginx/access.log | grep -i cache

On a resource-limited HolyCloud VPS, cap max_size (e.g. 200–500 MB) so disk does not fill up.

Verification

sudo nginx -t
curl -I https://www.example.com/favicon.ico
curl -I https://www.example.com/static/app.js

Need help?

  • Changes have no effect: browser cache — test in private browsing or purge the CDN if one sits in front of the VPS
  • Permanent X-Cache-Status: MISS: check proxy_cache_key, Set-Cookie headers that disable caching
  • HolyCloud support: nginx -T excerpt, tested URL, df -h (disk cache space)