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


19 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;
}