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: checkproxy_cache_key,Set-Cookieheaders that disable caching - HolyCloud support:
nginx -Texcerpt, tested URL,df -h(disk cache space)