title: Nginx disallowing execution of PHP in uploads directory with Magento
body: <p>I'm having difficulties getting nginx to stop execution of PHP in an uploads directory on a magento install.  I've tried many combinations of directives that should've sent a 503 or similar when *.php is matched in that directory, but still I'm able execute PHP in there.  Of-course the code solution is to prevent .php files from being uploaded but I don't understand how to prevent the execution from an nginx perspective.</p>
  
  <pre><code>map $http_x_ssl_offloaded $fastcgi_https {
    default off;
    on      on;
  }
  
  
  server {
      listen       80;
      server_name  store.xxxx.com;
      root         /var/www/store.xxxx.com;
  
      #charset koi8-r;
  
  
      #access_log  /var/log/nginx/store.xxxx.com-access.log  main;
      access_log  /var/log/nginx/store.xxxx.com-access.log;
  error_log   /var/log/nginx/store.xxxx.com-error.log;
  
  
  gzip on;
  gzip_disable msie6;
  gzip_static on;
  gzip_comp_level 9;
  gzip_proxied any;
  gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
  
  
   location / {
      index index.html index.php;
      try_files $uri $uri @handler;
      expires 30d; ## Assume all files are cachable
  }
  
  ## Location for media to prevent execution of php
  location ^~ /media/              {}
  
  ## These locations would be hidden by .htaccess normally
  location ^~ /app/                { deny all; }
  location ^~ /includes/           { deny all; }
  location ^~ /lib/                { deny all; }
  location ^~ /media/downloadable/ { deny all; }
  location ^~ /pkginfo/            { deny all; }
  location ^~ /report/config.xml   { deny all; }
  location ^~ /var/                { deny all; }
  
  location /var/export/ { ## Allow admins only to view export folder
      auth_basic           "Restricted"; ## Message shown in login window
      auth_basic_user_file htpasswd; ## See /etc/nginx/htpassword
      autoindex            on;
  }
  
  location  /. { ## Disable .htaccess and other hidden files
      return 404;
  }
  
  location @handler { ## Magento uses a common front handler
      rewrite / /index.php;
  }
  
  location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
      rewrite ^(.*.php)/ $1 last;
  }
  
  # Pass all PHP scripts to the PHP-FPM
  location ~ [^/]\.php(/|$) {
  
      fastcgi_split_path_info ^(.+?\.php)(/.*)$;
      if (!-f $document_root$fastcgi_script_name) {
              return 404;
      }
  
      expires        off; ## Do not cache dynamic content
      fastcgi_pass   127.0.0.1:9000;
      include        fastcgi_params;
  
      fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
      fastcgi_param  MAGE_RUN_CODE en_us;
      fastcgi_param  MAGE_RUN_TYPE store;
      fastcgi_param  SSL_OFFLOADED $fastcgi_https;
      fastcgi_param  HTTPS $fastcgi_https;
  
      fastcgi_read_timeout 6000;
  }
  
  location /api {
      rewrite ^/api/rest /api.php?type=rest last;
      rewrite ^/api/v2_soap /api.php?type=v2_soap last;
      rewrite ^/api/soap /api.php?type=soap last;
  }
  
  location /nginx_status {
          stub_status on;
          access_log   off;
          allow 127.0.0.1;
          deny all;
  }
  
  # deny running scripts inside writable directories
  location ~* /(images|cache|media|logs|tmp)/.*\.(php|pl|py|jsp|asp|sh|cgi)$ {
          return 403;
          error_page 403 /403_error.html;
  }
  
  # caching of files
  location ~* \.(ico|pdf|flv)$ {
          expires 1y;
  }
  
  location ~* \.(js|css|png|jpg|jpeg|gif|swf|xml|txt)$ {
          expires 14d;
  }
  
  # redirect server error pages to the static page /40x.html
  #
  error_page  404              /404.html;
  location = /40x.html {
  }
  
  # redirect server error pages to the static page /50x.html
  #
  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
  }
  
  # deny access to .htaccess files, if Apache's document root
  # concurs with nginx's one
  #
  location ~ /\.ht {
      deny  all;
  }
  }
  </code></pre>