How to Properly Rewrite Base URL to Subdirectory in Nginx Without Redirect Loops


3 views

When dealing with WordPress installations, we often encounter plugins that set cookies at the root URL (http://www.example.com), preventing proper caching. The requirement is to internally rewrite (not redirect) all root requests to a specific subdirectory (/something/else) while avoiding two common pitfalls:

  1. Missing rewrite rules that don't actually trigger
  2. Accidental redirect loops that crash browsers

The initial attempt using:

location / {
    rewrite ^ /something/else break;
}

This performs an internal rewrite but doesn't solve the cookie issue because the browser still sees the original URL.

The second attempt:

location / {
    rewrite ^ http://www.example.com/something/else break;
}

Creates a redirect loop because Nginx keeps reprocessing the rewritten URL through the same location block.

Here's the proper configuration that handles both the rewrite and prevents loops:

server {
    listen 80;
    server_name www.example.com;
    
    # Handle root specifically
    location = / {
        return 301 /something/else;
    }
    
    # Standard WordPress handling
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    
    # Additional WordPress-specific locations...
}

For cases where you need to preserve query strings:

location = / {
    if ($args ~* "^(.*)$") {
        return 301 /something/else?$1;
    }
    return 301 /something/else;
}

To handle both www and non-www versions:

server {
    listen 80;
    server_name example.com;
    return 301 $scheme://www.example.com/something/else$request_uri;
}

Always verify your rewrites with:

nginx -t
curl -I http://localhost/

Look for HTTP/1.1 301 Moved Permanently in the response headers.


When dealing with WordPress plugins that set cookies on the root URL, we often need to redirect http://www.example.com to a specific path like http://www.example.com/something/else. The challenge is implementing this without causing infinite redirect loops or performance issues.

The initial attempt using:

location / {
    rewrite ^ /something/else break;
}

doesn't perform an actual HTTP redirect - it's an internal rewrite. The second attempt:

location / {
    rewrite ^ http://www.example.com/something/else break;
}

creates a loop because Nginx keeps reprocessing the rewritten URL.

Here are three working approaches:

1. Using Return 301

The cleanest solution for permanent redirects:

location = / {
    return 301 /something/else;
}

2. Exact Root URL Matching

For more control over what gets redirected:

location = / {
    rewrite ^ /something/else permanent;
}

3. Conditional Redirect

When you need additional logic:

location / {
    if ($request_uri = /) {
        return 301 /something/else;
    }
    # Other location directives...
}

Always test redirect rules with:

nginx -t
service nginx reload

Monitor server performance after implementation to ensure no unexpected loops or excessive requests occur.

When troubleshooting:

  1. Check Nginx error logs: tail -f /var/log/nginx/error.log
  2. Test with curl: curl -v http://example.com
  3. Verify cookie behavior with browser dev tools

Here's a complete server block example:

server {
    listen 80;
    server_name www.example.com;
    
    location = / {
        return 301 /something/else;
    }
    
    location /something/else {
        # Your normal configuration here
        try_files $uri $uri/ /index.php?$args;
    }
    
    # Other locations...
}