NGINX URL Rewrite: Remove index.php from /index.php/path/ to /path/ with Permanent Redirect


4 views

When working with PHP frameworks like DooPHP, we often need to handle clean URLs by removing the index.php segment. The goal is to transform URLs like:

http://example.com/index.php/something/more/

into cleaner versions:

http://example.com/something/more/

The existing configuration has several components we need to consider:

if (!-e $request_filename){
    rewrite /.* /index.php;
}

This currently rewrites all non-existent files to index.php, but doesn't handle the reverse operation we need.

To properly remove index.php, we need to add these rules to your server block:

server {
    # ... existing configuration ...
    
    # Remove index.php with permanent redirect
    location ~ ^/index\.php/(.*)$ {
        return 301 /$1;
    }

    # Existing PHP handler
    location ~ \.php$ {
        # ... existing PHP configuration ...
    }
}

Here's how your complete server block should look with the improvements:

server {
    listen 80;
    server_name vip.example.com;
    return 301 https://vip.example.com$request_uri;
}

server {
    listen 443;
    server_name vip.example.com;
    root /sites/vip.example.com;

    # Error pages
    error_page 404 /404.html;
    error_page 403 /403.html;
    error_page 401 /401.html;

    # SSL configuration
    ssl on;
    ssl_certificate /etc/nginx/config/server.csr;
    ssl_certificate_key /etc/nginx/config/server.sky;

    # Remove index.php permanently
    location ~ ^/index\.php/(.*)$ {
        return 301 /$1;
    }

    # Main location block
    location / {
        auth_basic "example Team Access";
        auth_basic_user_file config/htpasswd;
        index index.php;

        try_files $uri $uri/ /index.php?$args;
    }

    # PHP handler
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_param PATH_INFO $fastcgi_script_name;
    }
}

After making these changes:

  1. Test your configuration with nginx -t
  2. Reload NGINX with service nginx reload
  3. Verify by accessing https://vip.example.com/index.php/test/path - it should redirect to https://vip.example.com/test/path

The configuration now includes several improvements:

  • Changed the HTTP to HTTPS redirect to use return 301 instead of rewrite for better performance
  • Simplified the error page paths
  • Added try_files directive for better handling of clean URLs
  • Fixed the root directory specification

Many PHP frameworks like DooPHP generate URLs containing index.php in the path (e.g., http://example.com/index.php/something/more/). This creates ugly URLs that aren't SEO-friendly. We want clean URLs like http://example.com/something/more/.

Here's how to implement clean URLs in NGINX with proper rewrite rules:

server {
    listen 80;
    server_name example.com;
    
    # Redirect HTTP to HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    root /var/www/example.com;
    index index.php;
    
    # Remove index.php from URLs
    location / {
        try_files $uri $uri/ @rewrite;
    }
    
    location @rewrite {
        rewrite ^/index.php/(.*)$ /$1 permanent;
        rewrite ^/(.*)$ /index.php/$1 last;
    }
    
    # PHP processing
    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/run/php/php-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
    
    # Error pages
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
}

The configuration uses two key rewrite rules:

  1. rewrite ^/index.php/(.*)$ /$1 permanent; - Redirects any URL containing index.php to its clean version (301 permanent redirect)
  2. rewrite ^/(.*)$ /index.php/$1 last; - Internally rewrites clean URLs to the index.php handler

After making changes:

sudo nginx -t
sudo systemctl reload nginx

Test with curl to verify redirects:

curl -I http://example.com/index.php/something/more/
  • Ensure your PHP framework is configured to handle clean URLs
  • Check file permissions on your web root directory
  • Verify PHP-FPM is running if you get 502 errors
  • Clear your browser cache when testing redirects

For more complex scenarios, you might need additional rules:

# Handle direct requests to index.php
location = /index.php {
    return 301 $scheme://$host/;
}

# Prevent direct access to other PHP files
location ~ /(app|config|core)/.*\.php$ {
    deny all;
}