ð Introduction
This comprehensive guide walks you through configuring NGINX as a high-performance web server for WordPress and PHP applications. You'll learn how to create server blocks, optimize FastCGI communication with PHP-FPM, and implement effective browser caching strategies.
- Creating and configuring NGINX server blocks
- Optimizing FastCGI parameters for PHP processing
- Implementing browser caching for static assets
- Troubleshooting common configuration errors
- Enabling and testing server configurations
ð Understanding NGINX Request Flow
HTTP Request Processing Flow
Sends HTTP Request
Receives Request
(HTML, CSS, JS, Images)
from Filesystem
(.php scripts)
Passes to PHP-FPM
Executes PHP Code
via FastCGI
Back to Client
- Static Assets: NGINX serves directly from the filesystem without processing
- PHP Files: Handed off to PHP-FPM via the FastCGI protocol
- PHP-FPM: The application server that executes PHP code and generates responses
- FastCGI: The communication protocol between NGINX and PHP-FPM
ð Creating NGINX Server Blocks
Server blocks (similar to Apache's virtual hosts) define how NGINX handles requests for different
domains. Each server block is configured in a separate file in the
/etc/nginx/sites-available/ directory.
Step 1: Create the Server Block File
Step 2: Progressive Server Block Configuration
Basic Server Block (Empty)
server {
}
Add Listening Port
server {
listen 80;
}
Tells NGINX to listen on port 80 (HTTP)
Add Server Name
server {
listen 80;
server_name example.com www.example.com;
}
Specifies which domain names this server block responds to
Add Document Root
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/public_html;
}
Defines where NGINX should look for website files
Add Index File
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/public_html;
index index.php;
}
Specifies which file to serve when a directory is requested
Add Location Block for URL Routing
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/public_html;
index index.php;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
}
Handles WordPress permalink structure and URL routing
Add PHP Processing
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/public_html;
index index.php;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
}
Configures how PHP files are processed via FastCGI
Complete Server Block with Logging
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/public_html;
index index.php;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
access_log /var/log/nginx/access_example.com.log combined buffer=256k flush=60m;
error_log /var/log/nginx/error_example.com.log;
}
- Typing domain name incorrectly
- Wrong document root path
- Missing semicolons at the end of directives
- Incorrect spacing or extra spaces
- Not matching opening and closing braces
⥠Browser Caching Configuration
Browser caching allows visitors' browsers to store static assets locally, reducing server load and improving page load times on subsequent visits. The first visit downloads assets from the server, but subsequent visits serve them from the browser's cache.
Browser Caching Flow
Browser â Server â Downloads Assets â Stores in Cache
Browser â Checks Cache â Serves from Cache (Fast!)
Create Browser Caching Configuration
Complete Browser Caching Configuration
# Images, Videos, Documents (365 days)
location ~* \.(webp|3gp|gif|jpg|jpeg|png|ico|wmv|avi|asf|asx|mpg|mpeg|mp4|pls|mp3|mid|wav|swf|flv|exe|zip|tar|rar|gz|tgz|bz2|uha|7z|doc|docx|xls|xlsx|pdf|iso)$ {
expires 365d;
add_header Cache-Control "public, no-transform";
access_log off;
}
# JavaScript files (30 days)
location ~* \.(js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
access_log off;
}
# CSS files (30 days)
location ~* \.(css)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
access_log off;
}
# Fonts (30 days)
location ~* \.(eot|svg|ttf|woff|woff2)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
access_log off;
}
Cache Control Headers Explained
| Directive | Purpose | Example |
|---|---|---|
expires |
How long to cache the resource | 365d = 365 days, 30d = 30 days |
public |
Resource can be cached by any cache (browser, CDN, proxy) | Allows intermediate caches to store the resource |
no-transform |
Prevents proxies from modifying the resource | Stops image compression by intermediate proxies |
access_log off |
Don't log requests for these assets | Reduces log file size and I/O operations |
- Reduced server load (fewer requests to process)
- Faster page load times for returning visitors
- Lower bandwidth usage
- Improved user experience
âïļ FastCGI Optimization
FastCGI optimization configures how NGINX communicates with PHP-FPM. Proper configuration of timeouts, buffers, and temporary files ensures better performance and stability when processing PHP requests.
ðŠķ Lightweight Configuration
Best For: Static sites, brochure sites, blogs where caching handles most of the load
Key Features:
- Conservative buffer sizes (128KB total)
- Standard timeouts (30-60s)
- Minimal memory footprint
- Suitable for low-traffic sites
ðŠ Heavy Duty Configuration
Best For: WooCommerce, LMS (Learning Management Systems), dynamic membership sites
Key Features:
- Expanded buffer sizes (256KB total)
- Extended timeouts (60-180s)
- Handles large checkout pages
- Prevents timeouts during bulk operations
Create FastCGI Optimization File
Lightweight Configuration
# LIGHTWEIGHT CONFIGURATION
# Best for static/brochure sites where caching handles the load.
# Timeouts (Standard)
fastcgi_connect_timeout 30s;
fastcgi_send_timeout 60s;
fastcgi_read_timeout 60s;
# Buffers (Conservative)
# 32k is plenty for standard headers
fastcgi_buffer_size 32k;
# 8 buffers at 16k = 128KB total body size in RAM
# This is enough for most standard pages
fastcgi_buffers 8 16k;
# Flow Control
fastcgi_busy_buffers_size 64k;
# Error Handling
fastcgi_intercept_errors on;
fastcgi_ignore_client_abort on;
fastcgi_keep_conn on;
Heavy Duty Configuration
# HEAVY DUTY CONFIGURATION
# Best for WooCommerce, LMS, or dynamic membership sites.
# Timeouts (Extended)
# Increased to 180s to prevent timeouts during bulk edits or checkout processing
fastcgi_connect_timeout 60s;
fastcgi_send_timeout 180s;
fastcgi_read_timeout 180s;
# Buffers (Expanded)
# Increased to 64k to handle heavy cookies and long headers common in WooCommerce
fastcgi_buffer_size 64k;
# 16 buffers at 16k = 256KB total body size in RAM
# This helps keep larger checkout pages in memory rather than writing to disk
fastcgi_buffers 16 16k;
# Flow Control
fastcgi_busy_buffers_size 128k;
# Error Handling
fastcgi_intercept_errors on;
fastcgi_ignore_client_abort on;
fastcgi_keep_conn on;
FastCGI Directives Explained
| Directive | Purpose | Impact |
|---|---|---|
fastcgi_connect_timeout |
Timeout for establishing connection with PHP-FPM | If exceeded, NGINX returns an error |
fastcgi_send_timeout |
Timeout for sending request to PHP-FPM | Prevents hanging on stuck requests |
fastcgi_read_timeout |
Timeout for reading response from PHP-FPM | Critical for long-running PHP scripts |
fastcgi_buffer_size |
Buffer for reading response headers | Must accommodate all HTTP headers |
fastcgi_buffers |
Number and size of buffers for response body | Determines how much data stays in RAM |
fastcgi_busy_buffers_size |
Maximum size of buffers being processed | Controls memory usage during active processing |
fastcgi_intercept_errors |
Handle PHP-FPM errors as HTTP errors | Allows custom error pages |
fastcgi_ignore_client_abort |
Continue processing even if client disconnects | Ensures operations complete |
fastcgi_keep_conn |
Keep connections alive to PHP-FPM | Improves performance by reusing connections |
ð Integrating Optimization Files
After creating the browser caching and FastCGI optimization files, you need to include them in your server block configuration.
Step 1: Verify File Paths
The readlink -f command displays the absolute path, helping you verify the correct
location.
Step 2: Edit Server Block
Step 3: Add Include Directives
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com/public_html;
index index.php;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
include /etc/nginx/includes/fastcgi_optimize.conf;
}
include /etc/nginx/includes/browser_caching.conf;
access_log /var/log/nginx/access_example.com.log combined buffer=256k flush=60m;
error_log /var/log/nginx/error_example.com.log;
}
- FastCGI Optimization: Inside the
location ~ \.php$block, afterfastcgi_pass - Browser Caching: At the server level, after PHP location block
â Enabling the Server Block
NGINX uses a sites-available/sites-enabled pattern. Configuration files are created in
sites-available, and symbolic links are created in sites-enabled to
activate them.
Sites Structure
sites-available/
Actual configuration files
- default
- example.com.conf
- mysite.com.conf
sites-enabled/
Symbolic links to active configs
- default â ../sites-available/default
- example.com.conf â ../sites-available/example.com.conf
Enable Your Server Block
1. Check Current Status
This shows files in both directories
2. Create Symbolic Link
Creates a link from sites-enabled to your configuration in sites-available
3. Verify the Link
The -l flag shows detailed listing including symbolic links
4. Test NGINX Configuration
Tests the syntax of all NGINX configuration files
nginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful
5. Reload NGINX
Reloads NGINX configuration without dropping connections
- Reload: Gracefully applies new configuration without dropping existing connections
- Restart: Stops and starts NGINX, briefly interrupting service
ð§ Troubleshooting Common Issues
403 Forbidden Error
Solution: This is normal before installing WordPress. NGINX returns 403 when the directory is empty and directory listing is disabled (default behavior).
Verify with curl:
Shows HTTP response headers. You should see HTTP/1.1 403 Forbidden before content is
added.
Syntax Test Failures
Example Error:
nginx: [emerg] open() "/etc/nginx/include/fastcgi_optimize.conf" failed (2: No such file or directory) in /etc/nginx/sites-available/example.com.conf:16
- First line: The problematic file/path
- Second line: The file where the error occurs
- Line number: Exact location of the error
Open File with Line Numbers:
The -l flag displays line numbers in nano
Common Configuration Errors
| Error | Cause | Solution |
|---|---|---|
| No such file or directory | Typo in path or filename | Verify path with ls or readlink -f |
| Unexpected "}" | Missing semicolon | Check all directives end with semicolon |
| Unknown directive | Typo in directive name | Double-check spelling against documentation |
| Conflicting server name | Duplicate domain in another config | Each domain should only appear once |
Debugging Workflow
sudo nginx -t
sudo systemctl reload nginx
- Domain name spelling (server_name)
- Document root path accuracy (root)
- Semicolons at end of directives
- Matching opening and closing braces
- Include file paths
- PHP-FPM socket path
ð Quick Command Reference
| Command | Alias | Purpose |
|---|---|---|
sudo nginx -t |
ngt | Test NGINX configuration syntax |
sudo systemctl reload nginx |
ngr | Reload NGINX configuration |
sudo systemctl restart nginx |
- | Restart NGINX service |
sudo systemctl status nginx |
- | Check NGINX service status |
ls -l sites-* |
- | View sites-available and sites-enabled |
readlink -f [file] |
- | Display absolute path of file |
curl -I [domain] |
- | View HTTP response headers |
nano -l [file] |
- | Edit file with line numbers |
Nano Editor Shortcuts
| Shortcut | Action |
|---|---|
Ctrl + O |
Save file (WriteOut) |
Ctrl + X |
Exit nano |
Ctrl + K |
Cut current line |
Ctrl + U |
Paste cut text |
Shift + Alt + $ |
Toggle soft wrap (view long lines) |
âĻ Best Practices & Tips
Configuration Management
- Keep configurations organized in separate files
- Use include files for reusable directives
- Always test syntax before reloading
- Comment your configurations for future reference
- Back up working configurations before major changes
Performance Optimization
- Choose the appropriate FastCGI configuration for your site type
- Implement aggressive caching for static assets
- Use buffered logging to reduce I/O operations
- Monitor access logs to identify performance bottlenecks
- Consider using HTTPS with HTTP/2 for better performance
Security Considerations
- Never expose NGINX version in error pages
- Limit file upload sizes appropriately
- Implement rate limiting for sensitive endpoints
- Use restrictive file permissions on configuration files
- Regularly update NGINX and PHP-FPM
ð Next Steps
After completing this configuration, you're ready to install WordPress. The server block is configured to handle PHP processing, browser caching is optimized, and FastCGI communication with PHP-FPM is properly tuned.
What Happens Next:
- Install WordPress in your document root (
/var/www/example.com/public_html) - The 403 error will disappear once WordPress files are in place
- NGINX will serve your WordPress site using the optimized configuration
- Static assets will be cached in visitors' browsers
- PHP requests will be efficiently processed via FastCGI
You've Successfully Configured:
- â NGINX server block for your domain
- â PHP processing via PHP-FPM
- â Browser caching for static assets
- â FastCGI optimization for PHP communication
- â Access and error logging
- â WordPress permalink support