Troubleshooting Nginx Alias Configuration for phpMyAdmin Access


2 views

When configuring Nginx to serve phpMyAdmin from a custom directory using alias, a common pitfall emerges where static files (CSS, JS, images) return 404 errors while PHP files process correctly through FastCGI. This occurs because Nginx's location matching behavior differs from what many administrators expect.

The configuration shown has two competing location blocks:

location ~ ^/phpmyadmin/(.+\\.php)$ {
    # PHP processing configuration
}

location /phpmyadmin {
    alias /home/phpmyadmin/;
}

The regex location (~) takes precedence over the prefix location, which means all requests matching the PHP pattern will bypass the alias directive completely.

Here's the corrected approach that ensures both PHP processing and static file serving work correctly:

location /phpmyadmin/ {
    alias /home/phpmyadmin/;
    
    location ~ \\.php$ {
        include fcgi.conf;
        fastcgi_pass unix:/tmp/php-cgi.sock;
        fastcgi_param SCRIPT_FILENAME $request_filename;
    }
}
  • Always include the trailing slash in both the location and alias paths
  • Nested location blocks maintain proper context for both static and PHP files
  • $request_filename preserves the correct path resolution

To verify your configuration:

nginx -t
systemctl reload nginx
curl -I http://yourserver/phpmyadmin/index.php
curl -I http://yourserver/phpmyadmin/js/config.js
  1. Mixing root and alias directives in the same context
  2. Forgetting trailing slashes in path specifications
  3. Using $document_root instead of $request_filename
  4. Improper permission settings on the target directory

For high-traffic installations, consider this optimized version:

location ^~ /phpmyadmin/ {
    alias /home/phpmyadmin/;
    
    location ~* \\.php$ {
        fastcgi_split_path_info ^(/phpmyadmin)(/.+?\\.php)(.*)$;
        include fastcgi_params;
        fastcgi_pass unix:/tmp/php-cgi.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$2;
    }
}

When configuring Nginx to serve phpMyAdmin from a custom directory using alias, many administrators encounter a frustrating scenario: PHP files process correctly via FastCGI, but static resources (CSS, JS, images) return 404 errors because Nginx keeps looking in the default document root rather than the specified alias path.

The original configuration contains two location blocks:

location ~ ^/phpmyadmin/(.+\\.php)$ {
    include fcgi.conf;
    fastcgi_index index.php;
    fastcgi_pass  unix:/tmp/php-cgi.sock;
    fastcgi_param SCRIPT_FILENAME /home$fastcgi_script_name;
}

location /phpmyadmin {
    alias /home/phpmyadmin/;
}

The issue stems from Nginx's location matching priority. The regex location (~) takes precedence over prefix locations, causing all requests to first match the PHP handler. For non-PHP files, this creates a silent fallback to the document root.

Solution 1: Exact location matching

location = /phpmyadmin {
    alias /home/phpmyadmin;
    try_files $uri $uri/ /phpmyadmin/index.php;
}

location ^~ /phpmyadmin/ {
    alias /home/phpmyadmin/;
    try_files $uri $uri/ @phpmyadmin;
}

location @phpmyadmin {
    rewrite ^/phpmyadmin/(.*)$ /phpmyadmin/index.php?route=/$1 last;
}

Solution 2: Directory index handling

location /phpmyadmin/ {
    alias /home/phpmyadmin/;
    index index.php;
    
    location ~ \\.php$ {
        if (!-f $request_filename) { return 404; }
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $request_filename;
        fastcgi_pass unix:/tmp/php-cgi.sock;
    }
}
  • Always end alias paths with / when the location block ends with /
  • Use $request_filename instead of constructing paths manually
  • Consider adding try_files to handle missing files gracefully
  • Test configurations with nginx -t before reloading

Access log analysis: Add this to your server block:

log_format alias_debug '$remote_addr - $remote_user [$time_local] '
                      '"$request" $status $body_bytes_sent '
                      '"$http_referer" "$http_user_agent" '
                      'alias: "$alias" filename: "$request_filename"';

Strace verification:

strace -e openat -p $(pgrep -f "nginx: worker")