# NGINX Configuration Guide: Server Blocks, FastCGI Optimization & Browser Caching NGINX Configuration Guide

🚀 NGINX Server Configuration Guide

Complete Guide to Server Blocks, FastCGI Optimization & Browser Caching

📋 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.

ðŸŽŊ What You'll Learn:
  • 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

1. Client Browser
Sends HTTP Request
↓
2. NGINX Web Server
Receives Request
↓
Request Type Decision:
Static File
(HTML, CSS, JS, Images)
↓
NGINX Serves Directly
from Filesystem
PHP File
(.php scripts)
↓
3. FastCGI Protocol
Passes to PHP-FPM
↓
4. PHP-FPM Processes
Executes PHP Code
↓
5. Returns Response
via FastCGI
↓
6. NGINX Sends Response
Back to Client
🔑 Key Points:
  • 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

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

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;
}
⚠ïļ Common Mistakes to Avoid:
  • 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

First Visit:
Browser → Server → Downloads Assets → Stores in Cache
Subsequent Visits:
Browser → Checks Cache → Serves from Cache (Fast!)

Create Browser Caching Configuration

cd /etc/nginx/includes/
sudo nano browser_caching.conf

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
✅ Benefits of Browser Caching:
  • 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.

📊 December 2025 Update: Two configuration profiles are now available based on your application requirements.

ðŸŠķ 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

cd /etc/nginx/includes/
sudo nano fastcgi_optimize.conf

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

readlink -f /etc/nginx/includes/browser_caching.conf
readlink -f /etc/nginx/includes/fastcgi_optimize.conf

The readlink -f command displays the absolute path, helping you verify the correct location.

Step 2: Edit Server Block

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

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;
}
📍 Include Placement:
  • FastCGI Optimization: Inside the location ~ \.php$ block, after fastcgi_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

cd /etc/nginx/
ls sites-*

This shows files in both directories

2. Create Symbolic Link

sudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/example.com.conf

Creates a link from sites-enabled to your configuration in sites-available

3. Verify the Link

ls -l sites-*

The -l flag shows detailed listing including symbolic links

4. Test NGINX Configuration

sudo nginx -t

Tests the syntax of all NGINX configuration files

Expected Output:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

5. Reload NGINX

sudo systemctl reload nginx

Reloads NGINX configuration without dropping connections

🔄 Reload vs Restart:
  • Reload: Gracefully applies new configuration without dropping existing connections
  • Restart: Stops and starts NGINX, briefly interrupting service

🔧 Troubleshooting Common Issues

403 Forbidden Error

Cause: Empty document root directory
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:

curl -I example.com

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
🔍 How to Read Error Messages:
  1. First line: The problematic file/path
  2. Second line: The file where the error occurs
  3. Line number: Exact location of the error

Open File with Line Numbers:

sudo nano -l example.com.conf

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

1. Make configuration changes
↓
2. Test syntax: sudo nginx -t
↓
3a. If successful: sudo systemctl reload nginx
3b. If failed: Read error message → Fix issue → Test again
⚠ïļ Critical Points to Check:
  • 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:

  1. Install WordPress in your document root (/var/www/example.com/public_html)
  2. The 403 error will disappear once WordPress files are in place
  3. NGINX will serve your WordPress site using the optimized configuration
  4. Static assets will be cached in visitors' browsers
  5. 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