Nginx and PHP-FPM 403 Forbidden

Chris asked:

I’m using Nginx with PHP-FPM. The requested page is displayed, but firebug shows that the paths to the CSS, JS, and images are returning 403 Forbidden error which breaks the styling.

Taking a look at the logs:

013/03/09 21:15:43 [error] 1012#0: *17 FastCGI sent in stderr: "Access to the script '/var/www/my_server/extras/extras/go/_common/imgs/WebLogo2-trans.png' has been denied (see security.limit_extensions)" while reading response header from upstream, client:, server:, request: "GET /extras/extras/go/_common/imgs/WebLogo2-trans.png HTTP/1.1", upstream: "fastcgi://unix:/var/tmp/php-fpm.sock:", host: "", referrer: ""

However, I tried setting security.limit_extensions = .php .css .js .jpg just to see what happens, but the mimetype is interpreted is text/html and doesn’t load.

I’ve tried chmod 777 every file and directory, but no luck.

Here is the Nginx server block: and relevent location block. The location block is included from another file which is not reflected in the server block:

     location /extras/ {
            access_log /var/log/nginx/my_server/extras.log debug_phpfpm;
            include         /etc/nginx/fastcgi_params;
            root            /var/www/my_server/extras;
            fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
            autoindex       on;
            fastcgi_pass    unix:/var/tmp/php-fpm.sock;
            fastcgi_index   index.php;

            expires max;


My /etc/nginx/fastcgi_params;

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;

The output of /usr/sbin/php5-fpm -version:

PHP 5.3.10-1ubuntu3.5 (fpm-fcgi) (built: Jan 18 2013 23:44:08)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies
with XCache v1.3.2, Copyright (c) 2005-2011, by mOo

Nginx 1.2.6 is compiled from source for extra modules.

My answer:

I’m going to presume you’ve given enough information and not left out anything important in the nginx configuration information you chose not to share.

With that caveat in mind…

It appears that you are passing everything under /extras/ to PHP, including requests for static data. This is rightly being denied, as it means a malicious PHP script uploaded with a .jpg extension (for instance) will not be executed as PHP.

To resolve this issue, you need to pass only requests for PHP scripts under /extras/ to PHP.

location ~ /extras/.*.php$ {

If you need to handle static files under that directory specially, then you can make a location block for them. (You probably should do this, since you seem to be passing everything else to Django…)

location /extras/ { }

Another issue you have which is probably causing you grief is that your server block does not have a valid root defined. This is one of the most common nginx misconfigurations. It should be something like:

root /var/www/my_server;

(Which also means you should not define redundant roots in every single location.)

View the full question and answer on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.