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


22 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...
}