NGINX Configuration Guide: WordPress Uploads CDN Integration
Overview
This technical documentation outlines the implementation of an NGINX configuration designed to intelligently route WordPress media requests between local storage and a Content Delivery Network (CDN). The configuration implements a fallback mechanism where requests first attempt to serve files from the local filesystem before redirecting to the CDN.
Architecture
Components
-
Local WordPress Installation
- Contains the standard WordPress file structure
- Houses the
/wp-content/uploads/
directory for media storage - Serves as the primary point of contact for web requests
-
Content Delivery Network (CDN)
- Secondary storage location for media assets
- Provides distributed content delivery
- Reduces load on origin server
- Improves global access speeds
-
NGINX Server
- Handles incoming requests
- Implements routing logic
- Manages fallback mechanisms
- Performs URL rewrites as needed
Configuration Implementation
Base Configuration
# Define CDN endpoint
set $production cdn.example.com/example-subdirectory;
# Named location for production CDN redirects
location @prod_uploads {
rewrite "^(.*)/wp-content/uploads/(.*)$" "https://$production/wp-content/uploads/$2" break;
}
# Primary location block for uploads directory
location ~ "^/wp-content/uploads/(.*)$" {
try_files $uri @prod_uploads;
}
Configuration Breakdown
1. CDN Variable Declaration
set $production cdn.example.com/example-subdirectory;
- Defines a variable storing the CDN domain
- Allows easy modification of CDN endpoint
- Supports subdirectory paths if required
- Should be updated to match your CDN provider’s endpoint
2. Named Location Block
location @prod_uploads {
rewrite "^(.*)/wp-content/uploads/(.*)$" "https://$production/wp-content/uploads/$2" break;
}
- Creates a named location for handling CDN redirects
- Uses regular expression capture groups for path manipulation
- Maintains original file path structure on CDN
break
directive prevents further rewrite rule processing
3. Primary Location Block
location ~ "^/wp-content/uploads/(.*)$" {
try_files $uri @prod_uploads;
}
- Matches requests to uploads directory using regex
- Implements
try_files
directive for fallback logic - Attempts local file serving before CDN redirect
- Maintains transparent operation for end users
Implementation Considerations
Security
-
SSL/TLS Configuration
- Ensure proper SSL certificate setup
- Configure secure cipher suites
- Enable HTTP/2 for improved performance
ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off;
-
Access Controls
- Consider implementing rate limiting
- Add IP-based restrictions if needed
limit_req_zone $binary_remote_addr zone=uploads:10m rate=10r/s; location ~ "^/wp-content/uploads/(.*)$" { limit_req zone=uploads burst=20 nodelay; try_files $uri @prod_uploads; }
Performance Optimization
-
Caching Headers
location ~ "^/wp-content/uploads/(.*)$" { expires 7d; add_header Cache-Control "public, no-transform"; try_files $uri @prod_uploads; }
-
Compression Settings
gzip on; gzip_types image/svg+xml application/x-font-ttf image/x-icon; gzip_vary on;
Monitoring and Logging
Access Logging
log_format cdn_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'cdn=$upstream_http_x_cdn_status';
access_log /var/log/nginx/cdn_access.log cdn_log;
Error Handling
location @prod_uploads {
error_log /var/log/nginx/cdn_error.log notice;
rewrite "^(.*)/wp-content/uploads/(.*)$" "https://$production/wp-content/uploads/$2" break;
}
Testing and Validation
Configuration Testing
-
Syntax validation:
nginx -t
-
Request flow testing:
curl -I https://example.com/wp-content/uploads/2024/01/test.jpg
-
CDN fallback verification:
curl -v https://example.com/wp-content/uploads/non-existent.jpg
Troubleshooting
Common Issues
-
404 Errors on CDN
- Verify CDN endpoint configuration
- Check rewrite rule syntax
- Ensure proper path preservation
-
Mixed Content Warnings
- Confirm SSL configuration
- Verify HTTPS in rewrite rules
- Check WordPress site URL settings
-
Performance Issues
- Monitor NGINX error logs
- Verify CDN response times
- Check local filesystem performance
Debug Configuration
location ~ "^/wp-content/uploads/(.*)$" {
error_log /var/log/nginx/debug.log debug;
add_header X-Debug-Path $request_filename;
try_files $uri @prod_uploads;
}
Server Block Explanation
The server block listening on port 8080 is essentially a backend server that handles PHP processing. Here’s why it exists and how it works:
- The main server (listening on port 443) acts as a reverse proxy and forwards PHP requests to this backend server. This is evident from the line in the main server block:
proxy_pass http://127.0.0.1:8080;
- The port 8080 server block has several important functions:
listen 8080;
listen [::]:8080; # IPv6 support
server_name hhf.technology;
Its main responsibilities are:
- PHP Processing:
location ~ \.php$ {
fastcgi_pass 127.0.0.1:{{php_fpm_port}}; # Forwards PHP requests to PHP-FPM
include fastcgi_params; # Includes necessary FastCGI parameters
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# ... other FastCGI configurations
}
- WordPress-specific handling:
try_files $uri $uri/ /index.php?$args; # WordPress pretty URLs
index index.php index.html; # Default files to serve
This setup provides several benefits:
- Separation of concerns: Static content is handled by the main server, while PHP processing is isolated
- Better security: PHP processor isn’t directly exposed to the internet
- Performance: It allows for different optimization settings for static and dynamic content