NGINX WordPress permalink 404 errors occur when your server can't process pretty URLs, typically due to missing or incorrect rewrite rules in your NGINX configuration. Unlike Apache's .htaccess files, NGINX requires explicit server-level configuration to handle WordPress permalinks.
Why NGINX WordPress Permalinks Return 404 Errors
NGINX handles URL rewriting differently than Apache, which causes permalink problems for WordPress sites. Apache automatically processes .htaccess files in each directory, while NGINX requires explicit configuration in server blocks.
WordPress generates permalink structures like /post-name/ or /category/post-name/, but these URLs don't correspond to actual files on your server. Without proper rewrite rules, NGINX returns 404 errors because it can't find physical files matching these URLs.
According to W3Techs, NGINX powers 33.6% of all websites (2024), but WordPress permalink issues remain one of the most common configuration problems. The root cause is always the same: NGINX doesn't know how to route pretty URLs to WordPress's index.php file.
How to Diagnose NGINX Permalink 404 Issues
Start by identifying whether the problem affects all permalinks or specific patterns. Test these URL types on your site:
- Posts:
/sample-post/ - Pages:
/about/ - Categories:
/category/news/ - Archives:
/2024/01/ - Admin:
/wp-admin/(should work)
If only the admin works while all pretty URLs return 404s, you have a complete rewrite rule failure. Partial failures indicate location block conflicts or incomplete configuration.
Check your current NGINX configuration:
sudo nginx -T | grep -A 20 "server_name yourdomain.com"
Look for try_files directives and location blocks. Missing or incorrect try_files configuration is the primary culprit in 95% of permalink issues.
Common diagnostic signs include:
| Symptom | Likely Cause |
|---|---|
| All pretty URLs 404 | Missing try_files directive |
| Admin works, posts don't | WordPress location block missing |
| Some permalinks work randomly | Location block priority conflict |
| URLs work without trailing slash | try_files missing $uri/ pattern |
The Complete NGINX WordPress Configuration Fix
The standard WordPress NGINX configuration requires specific location blocks and rewrite rules. Here's the complete server block configuration that resolves permalink 404s:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
root /var/www/yourdomain.com/public_html;
index index.php index.html index.htm;
# Main WordPress location block
location / {
try_files $uri $uri/ /index.php?$args;
}
# Handle PHP files
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# WordPress admin and includes
location ~* ^/(wp-admin|wp-includes)/ {
try_files $uri $uri/ /index.php?$args;
}
# Block access to sensitive files
location ~* /(?:uploads|files)/.*\.php$ {
deny all;
}
# Static file caching
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
The critical line is try_files $uri $uri/ /index.php?$args; in the main location block. This directive tells NGINX:
- First, try to serve the exact URI as a file (
$uri) - If not found, try it as a directory (
$uri/) - Finally, pass the request to WordPress (
/index.php?$args)
For managed WordPress hosting environments, this configuration is automatically optimized and maintained, eliminating the need for manual server management.
Advanced NGINX WordPress Rewrite Rules
Complex WordPress sites often need additional rewrite rules beyond the basic configuration. Here are advanced patterns for common scenarios:
Multisite Network Configuration
WordPress multisite requires specific handling for subdirectory installations:
# Multisite subdirectory support
location ~ ^(/[^/]+/)?files/(.+) {
try_files /wp-content/blogs.dir/$1$2 /wp-includes/ms-files.php?file=$2;
}
# Main multisite location
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ ^/[_0-9a-zA-Z-]+(/wp-.*) {
try_files $uri $uri/ /index.php?$args;
}
Custom Post Type Permalinks
Sites using custom post types with specific permalink structures need targeted rewrite rules:
# Custom post type: portfolio
location ~ ^/portfolio/([^/]+)/?$ {
try_files $uri $uri/ /index.php?portfolio=$1&$args;
}
# Custom taxonomy: project-type
location ~ ^/project-type/([^/]+)/?$ {
try_files $uri $uri/ /index.php?project_type=$1&$args;
}
REST API and AJAX Handling
WordPress REST API and AJAX requests require specific location handling:
# WordPress REST API
location ~ ^/wp-json/ {
try_files $uri $uri/ /index.php?$args;
}
# Admin AJAX requests
location = /wp-admin/admin-ajax.php {
try_files $uri /index.php?$args;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
}
According to Kinsta's 2024 performance study, proper NGINX configuration can improve WordPress response times by up to 200% compared to poorly configured setups.
Common NGINX WordPress Misconfigurations
Several configuration mistakes consistently cause permalink problems. Understanding these patterns helps prevent recurring issues.
Location Block Priority Problems
NGINX processes location blocks in specific order, and incorrect priority can override WordPress rules:
# WRONG - Too specific location blocks first
location /wp-content/ {
# This overrides WordPress handling
}
location / {
try_files $uri $uri/ /index.php?$args;
}
# CORRECT - General WordPress rule first
location / {
try_files $uri $uri/ /index.php?$args;
}
location /wp-content/ {
# Static file handling
}
Missing Query String Preservation
Failing to preserve query strings breaks WordPress functionality:
# WRONG - Loses query parameters
try_files $uri $uri/ /index.php;
# CORRECT - Preserves query strings
try_files $uri $uri/ /index.php?$args;
Incorrect PHP Handler Configuration
PHP processing problems often masquerade as permalink issues:
# WRONG - Missing SCRIPT_FILENAME
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
include fastcgi_params;
}
# CORRECT - Proper PHP handling
location ~ \.php$ {
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
include fastcgi_params;
}
For agencies managing multiple client sites, these configuration complexities are why many choose managed hosting solutions that handle server optimization automatically.
Testing and Validating Your NGINX WordPress Configuration
After implementing configuration changes, systematic testing ensures your permalink fix works correctly across all WordPress features.
Configuration Syntax Testing
Always validate NGINX configuration before reloading:
# Test configuration syntax
sudo nginx -t
# If successful, reload NGINX
sudo systemctl reload nginx
Never skip syntax testing. Invalid configuration can bring down your entire server.
Comprehensive Permalink Testing
Test these URL patterns to verify complete functionality:
# Basic post permalinks
curl -I https://yourdomain.com/sample-post/
# Category archives
curl -I https://yourdomain.com/category/news/
# Date archives
curl -I https://yourdomain.com/2024/01/
# WordPress admin
curl -I https://yourdomain.com/wp-admin/
# REST API endpoints
curl -I https://yourdomain.com/wp-json/wp/v2/posts
Each request should return HTTP 200 status codes, not 404 errors.
WordPress Permalink Structure Testing
Navigate to WordPress Admin → Settings → Permalinks and test different permalink structures:
| Structure | URL Pattern | NGINX Requirement |
|---|---|---|
| Plain | /?p=123 | Basic PHP handling |
| Day and name | /2024/01/01/post-name/ | Full try_files configuration |
| Month and name | /2024/01/post-name/ | Full try_files configuration |
| Numeric | /archives/123 | Full try_files configuration |
| Post name | /post-name/ | Full try_files configuration |
| Custom | /blog/%postname%/ | Custom rewrite rules |
Switch between structures to ensure your NGINX configuration handles all patterns correctly. This process is automatically managed with WordPress maintenance plans that include server optimization.
Performance Optimization for NGINX WordPress Sites
Beyond fixing 404 errors, optimize your NGINX WordPress configuration for maximum performance. These enhancements build on the basic permalink fix.
FastCGI Caching Configuration
Implement server-level caching to reduce WordPress processing overhead:
# FastCGI cache configuration
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=wordpress:100m max_size=1g inactive=60m use_temp_path=off;
server {
# Cache configuration
set $skip_cache 0;
# Skip cache for admin, logged-in users, and POST requests
if ($request_method = POST) { set $skip_cache 1; }
if ($query_string != "") { set $skip_cache 1; }
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") { set $skip_cache 1; }
if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") { set $skip_cache 1; }
location ~ \.php$ {
fastcgi_cache wordpress;
fastcgi_cache_valid 200 301 302 60m;
fastcgi_cache_use_stale error timeout invalid_header http_500 http_503;
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
# Standard PHP processing
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
}
}
Gzip Compression and Static File Optimization
Reduce bandwidth and improve load times:
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
# Static file handling with aggressive caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|pdf|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
Security Enhancements
Block common WordPress attack vectors while maintaining permalink functionality:
# Block XML-RPC attacks
location = /xmlrpc.php {
deny all;
access_log off;
}
# Prevent PHP execution in uploads
location ~* /(?:uploads|files)/.*\.php$ {
deny all;
}
# Block sensitive WordPress files
location ~* /(?:wp-config\.php|wp-config-sample\.php|readme\.html|license\.txt)$ {
deny all;
}
According to Sucuri's 2024 Website Security Report, properly configured NGINX servers experience 67% fewer successful attacks compared to default configurations.
Troubleshooting Persistent Permalink Issues
When standard configuration fixes don't resolve NGINX permalink problems, systematic troubleshooting identifies underlying issues.
Debug NGINX Processing
Enable detailed logging to understand how NGINX processes WordPress URLs:
# Temporary debug logging
error_log /var/log/nginx/debug.log debug;
access_log /var/log/nginx/access.log combined;
# Add to location block for specific debugging
location / {
try_files $uri $uri/ /index.php?$args;
error_log /var/log/nginx/wordpress_debug.log debug;
}
Monitor logs while testing problematic URLs:
tail -f /var/log/nginx/wordpress_debug.log
WordPress-Specific Debugging
Enable WordPress debug logging to identify theme or plugin conflicts:
// Add to wp-config.php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
Check /wp-content/debug.log for WordPress-level errors that might interfere with permalink processing.
DNS and SSL Certificate Issues
Sometimes permalink problems stem from domain configuration rather than NGINX:
# Check DNS resolution
dig yourdomain.com
# Verify SSL certificate
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com
SSL certificate problems can cause browsers to display connection errors that appear as 404s.
For complex WordPress installations with custom requirements, professional WordPress hosting solutions provide expert configuration management and 24/7 troubleshooting support.
Automated NGINX WordPress Management
Manual NGINX configuration management becomes complex as your WordPress portfolio grows. Modern hosting platforms provide automated solutions that eliminate configuration headaches.
Configuration Management Tools
Use configuration management for consistent NGINX setups across multiple sites:
# Ansible playbook example
- name: Configure NGINX for WordPress
template:
src: wordpress-nginx.conf.j2
dest: /etc/nginx/sites-available/{{ domain }}
notify: reload nginx
- name: Enable site
file:
src: /etc/nginx/sites-available/{{ domain }}
dest: /etc/nginx/sites-enabled/{{ domain }}
state: link
Monitoring and Alerting
Implement monitoring to catch permalink issues before they impact users:
# Basic permalink monitoring script
#!/bin/bash
response=$(curl -s -o /dev/null -w "%{http_code}" https://yourdomain.com/sample-post/)
if [ $response -ne 200 ]; then
echo "Permalink 404 detected: $response" | mail -s
Topics

DevOps & Security Lead
12+ years DevOps, Linux & cloud infrastructure certified
Marcus leads infrastructure and security at TopSyde, managing the server fleet and AI monitoring systems that keep client sites fast and protected. Former sysadmin turned WordPress hosting specialist.



