Detailed How to Configure Nginx Expire Headers
Meta Description: Boost your WordPress site’s SEO with Nginx expire headers. Learn to configure caching for faster load times and better Core Web Vitals in this step-by-step guide.
Want to boost your WordPress site’s SEO? Configuring Nginx expire headers is a powerful way to improve page load times, a key factor in Google’s Core Web Vitals. By caching static assets like images, CSS, and JavaScript, you reduce server requests, enhance user experience, and improve metrics like Largest Contentful Paint (LCP). This guide shows you how to set up expire headers for your WordPress site running on Nginx with PHP.
Why Nginx Expire Headers Improve SEO
Expire headers tell browsers to cache static files, reducing load times and server strain. Here’s why they matter for your site:
- Faster Page Loads: Caching reduces LCP, boosting SEO rankings.
- Lower Server Load: Fewer requests free up resources for dynamic WordPress content.
- Better User Experience: Faster pages lower bounce rates, signaling engagement to search engines.
- Mobile Optimization: Cached assets reduce data usage, improving mobile performance.
[note type=”success” title=”Guide is tested on:” icon=”fa-check-circle”]
- PHP 8.3
- Nginx Certbot SSL enabled
- Ubuntu Server 24.04
[/note]
Prerequisites
Before you start, ensure you have:
- A WordPress site at [inline_code type=”warning”]/var/www/html/wordpress[/inline_code] on server.
- Nginx server with [inline_code type=”warning”]root access[/inline_code] to edit configuration files.
- PHP 8.3 with PHP-FPM configured.
- Certbot for SSL (already set up).
- A backup of your Nginx configuration.
Step-by-Step Guide to Configure Nginx Expire Headers
Follow these steps to add expire headers to your Nginx configuration safely, optimized for SEO and WordPress.
✅ Step 1: Backup Your Nginx Configuration
Protect your live server by backing up your configuration:
sudo cp /etc/nginx/sites-available/your_domain.com /etc/nginx/sites-available/your_domain.com.bak
✅ Step 2: Edit the Nginx Configuration File
Open your site’s configuration file (likely [inline_code type=”warning”]/etc/nginx/sites-available/your_domain.com[/inline_code]):
sudo nano /etc/nginx/sites-available/your_domain.com
Replace its contents with this SEO-optimized configuration:
# HTTPS Server Block
server {
listen 443 ssl; # Managed by Certbot
listen [::]:443 ssl ipv6only=on; # Managed by Certbot
server_name your_domain.com www.your_domain.com;
root /var/www/html/wordpress;
index index.php index.html index.htm;
client_max_body_size 64M;
# SSL Configuration (Managed by Certbot)
ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem; # Managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem; # Managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # Managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # Managed by Certbot
# WordPress Rewrite Rules
location / {
try_files $uri $uri/ /index.php?$args;
}
# Expire Headers for Static Assets (SEO-focused)
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg|eot|pdf|webp)$ {
expires 90d; # Cache for 90 days
add_header Cache-Control “public, must-revalidate”; # Supports WordPress ?ver= query strings
add_header Vary “Accept-Encoding”; # Supports Gzip
access_log off; # Reduce server load
}
# PHP Processing
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Deny Access to Sensitive Files
location ~* /(wp-config\.php|readme\.html|license\.txt|xmlrpc\.php|\.ht) {
deny all;
}
# Gzip Compression for Performance
gzip on;
gzip_types text/css application/javascript image/svg+xml application/font-woff2;
gzip_min_length 256;
gzip_vary on;
# Security Headers for SEO and Protection
add_header X-Content-Type-Options “nosniff”;
add_header X-Frame-Options “DENY”;
add_header X-XSS-Protection “1; mode=block”;
}
# HTTP to HTTPS Redirect
server {
listen 80;
listen [::]:80;
server_name your_domain.com www.your_domain.com;
return 301 https://$host$request_uri; # Redirect all HTTP to HTTPS
}
Key Settings:
- [inline_code type=”warning”]expires 90d:[/inline_code] Caches static files for 90 days, balancing SEO and WordPress updates.
- [inline_code type=”warning”]Cache-Control: public, must-revalidate[/inline_code]: Ensures compatibility with WordPress’s [inline_code type=”warning”]?ver=[/inline_code] query strings.
- [inline_code type=”warning”]gzip[/inline_code]: Compresses files for faster loading.
- [inline_code type=”warning”]access_log off[/inline_code]: Reduces server load for static assets.
- Security headers enhance trust signals for SEO.
✅ Step 3: Test the Configuration
Verify syntax to avoid errors:
sudo nginx -t
Expected output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf text is successful
If [inline_code type=”error”]errors[/inline_code] occur, check for typos or incorrect paths (e.g., [inline_code type=”warning”]/var/run/php/php8.3-fpm.sock[/inline_code]).
✅ Step 4: Apply Changes Safely
Reload Nginx without downtime:
sudo systemctl reload nginx
If [inline_code type=”error”]issues arise[/inline_code], revert to the backup:
sudo cp /etc/nginx/sites-available/your_domain.com.bak /etc/nginx/sites-available/your_domain.com
sudo systemctl reload nginx
✅ Step 5: Verify Expire Headers
Test a static asset:
curl -I https://your_domain.com/wp-content/uploads/sample.jpg
Expected output:
HTTP/1.1 200 OK
Server: nginx/1.24/0 (Ubuntu)
Date: Tue, 05 Aug 2025 03:43:32 GMT
Content-Type: image/png
Content-Length: 995
Last-Modified: Thu, 31 Jul 2025 03:43:32 GMT
Connectiong: keep-alive
ETag: “688aee23-3d3
Expires: Mon, 03 Nov 2025 03:43:32 GMT
Cache-Control: max-age=7776000
Cache-Control: public, must-revalidate
Vary: Accept-Encoding
Accept-Ranges: bytes
Check headers in browser DevTools (Network tab) for [inline_code type=”success”].jpg[/inline_code], [inline_code type=”success”].css[/inline_code], [inline_code type=”success”].js[/inline_code], etc.
✅ Step 6: Test WordPress Functionality
- Visit [inline_code type=”warning”]https://your_domain.com[/inline_code], sample posts, and [inline_code type=”warning”]/wp-admin[/inline_code].
- Ensure updated CSS/JS files (with [inline_code type=”warning”]?ver=[/inline_code]) load correctly.
- Confirm no 502/404 errors.
Additional SEO Tips for your_domain.com
- Shorter Expirations for CSS/JS: If you update themes/plugins often, use: Bash
location ~* \.(css|js)$ { expires 30d; add_header Cache-Control “public, must-revalidate”; }
- Caching Plugins: Pair with WP Rocket or W3 Total Cache for dynamic caching.
- CDN: Use Cloudflare with “Respect Existing Headers” for global caching.
- WebP Images: The [inline_code type=”warning”]location[/inline_code] block includes [inline_code type=”warning”].webp[/inline_code] for modern formats. Use plugins like ShortPixel for conversion.
Troubleshooting
- 502 Errors: Verify [inline_code type=”warning”]fastcgi_pass unix:/var/run/php/php8.3-fpm.sock[/inline_code] matches your PHP-FPM socket.
- Stale Assets: [inline_code type=”warning”]must-revalidate[/inline_code] ensures [inline_code type=”warning”]?ver=[/inline_code] query strings work.
- Logs: Check [inline_code type=”warning”]/var/log/nginx/error.log[/inline_code] or [inline_code type=”warning”]/var/log/php8.3-fpm.log[/inline_code].
- Rank Math Conflicts: Ensure caching plugins don’t override Nginx headers.
Conclusion
Configuring Nginx expire headers on your_domain.com is a simple yet effective way to enhance WordPress SEO. By caching static assets, you’ll improve load times, Core Web Vitals, and user experience. Combined with Rank Math SEO, this setup can skyrocket your rankings.
Have questions or success stories? Share in the comments below!