Freitag, 22. November 2013

Magento, Plesk, nginx and PHP-FPM

Since v11.5 Plesk has the ability to manage PHP websites without Apache by using the ability of nginx to run PHP directly via PHP-FPM, this is considered to be a faster way to run PHP scripts with generally lower memory footprint as nginx is really small.

Magento needs rewrite feature for internal SEO, while Apache has his mod_rewrite and the ability to use .htaccess files to configure its features, nginx doesn't offer such dynamic configuration, it's done statically so it doesn't have to search the path for .htaccess files and try to parse it, which happens on every webserver access and the price of slowing down the webservice while keeping the flexibility.

There are several tutorials across the web (e.g. nginx wiki) which show how to configure nginx, so Magento will run without .htaccess which are quite good but will not work with Plesk, which of course adds some own nginx configuration that collides with the nginx configuration in the tutorials.

The general problem is that Plesk defines its own "location /" and while you can work it around by using "location ~ (.*)" for the most important instruction "try_files $uri $uri/ @handler;" to run "location @handler { rewrite / /index.php; }", this will not work for urls with trailing slash which Magento generates for example for CMS sites, these will deliver 404 because Plesk adds following to every nginx config:
    location ~ /$ {
        index index.html index.cgi index.pl index.php index.xhtml index.htm index.shtml;
    }

The Plesk per-site nginx custom config is included inside the server scope, so a workaround using a combination of some ifs and rewrites is possible to circumvent this.

The following nginx config pasted into the Plesk custom nginx seems to do the magic properly:

## Taken from http://www.linux-magazin.de/Ausgaben/2012/01/Magento-Hosting/%28offset%29/4
# gzip compression
gzip on;
gzip_min_length 1100;
gzip_buffers 4 8k;
gzip_proxied any;
gzip_types text/plain text/css application/x-javascript text/javascript application/json;

############################################
## uncomment next line to enable light API calls processing
#rewrite ^/api/([a-z][0-9a-z_]+)/?$ /api.php?type=$1 break;

############################################
## rewrite API2 calls to api.php (by now it is REST only)
rewrite ^/api/rest /api.php?type=rest last;

############################################
## TRACE and TRACK HTTP methods disabled to prevent XSS attacks
if ($request_method ~ "^TRAC[EK]") {
 return 405;
}

############################################
## always send 404 on missing files in these folders
if ($uri !~ "^/(media|skin|js)/") {
 set $rewrite_to_index 1;
}

###########################################
## Deny access to release notes to prevent disclosure of the installed Magento version
if ($uri ~* "/RELEASE_NOTES.txt") {
 return 404;
}

# Don't rewrite if file exists
if (-e $request_filename) {
 set $rewrite_to_index 0;
}

############################################
## rewrite everything else to index.php
if ($rewrite_to_index = "1") {
 rewrite / /index.php;
}

############################################
## Prevent character encoding issues from server overrides
## If you still have problems, use the second line instead
charset off;
#charset utf-8;

############################################
## Add default Expires header
## http://developer.yahoo.com/performance/rules.html#expires
expires 365d;

##Taken from http://wiki.nginx.org/Magento
# Hide the system directories
location ~ ^/(app|includes|lib|media/downloadable|pkginfo|report/config.xml|var)/ {
 internal;
}

# Hide the hidden files
location /. {
 return 404;
}

Keine Kommentare:

Kommentar veröffentlichen