This is the 3rd and final article about installing Magento on Nginx with PHP-FPM. Part 1 is here, and Part 2 is here.
This part explains how I set up my public web directories, and how I did the Nginx configuration files for a Magento site. One of the tricky things about switching to Nginx from Apache is that Nginx does not use .htaccess files or the usual Apache mod_rewrite rules for pretty/SEO URLs. You can replicate all of Magento’s mod_rewrite rules with Nginx’s own rewrite module, but it takes some getting used to and Magento doesn’t come with them pre-written (like the mod_rewrite rules in the .htaccess files).
Here are some of the resources I used:
- Slicehost: Nginx Virtual Hosts #1
- Slicehost: Nginx Virtual Hosts #2
- Magento Forum: NginX Web Server with Magento
- Magento Forum: Thread about Fooman Speedster (which I never go to work)
- Random MarkMail post (I needed Google Translate to help me out)
- varien.com.ua (Also needed Google Translate to help me out)
First we’ll set up the directory structure like we are used to with Apache:
# mkdir /usr/local/nginx/sites-available
# mkdir /usr/local/nginx/sites-enabled
# mkdir /var/www/example1.com/public
# mkdir /var/www/example1.com/log
# cp /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf-original
Then set up the base nginx conf file /usr/local/nginx/conf/nginx.conf:
user www-data;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
include /usr/local/nginx/sites-enabled/*;
}
Then set up the Nginx conf file for your website. I am using the default site in this example /usr/local/nginx/sites-available/default, but if you have multiple sites instead of default you would create files called site1.com, site2.com, etc.
This file is where all of the rewrite magic is. The url in this example is example1.com, which you should replace with your own. The document root is /var/www/example1.com/public which, again, you will need to change to match your own configuration.
# fastcgi nodes
upstream backend {
server unix:/tmp/fcgi.sock;
}
# redirect all non-www requests to www requests (it would be easy to reverse this)
server {
listen 80;
server_name example1.com;
rewrite ^/(.*) http://www.example1.com/$1 permanent;
}
server {
listen 80;
server_name www.example1.com;
# protection (we have no .htaccess)
location ~ (/(app/|includes/|lib/|/pkginfo/|var/|report/config.xml)|/\.svn/|/.hta.+) {
deny all;
}
# pass php files over to PHP-FPM via the socket
location ~ (\.php)$ {
fastcgi_index index.php;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
if (-e $request_filename) { # check if requested path exists
fastcgi_pass backend;
}
}
# the javascript compressor
location ^~ /js/index.php {
fastcgi_pass backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param SCRIPT_FILENAME /var/www/example1.com/public$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
access_log off;
expires 30d;
}
# special case for the error "report" pages
location /report/ {
fastcgi_index index.php;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_NAME /report/index.php;
fastcgi_param SCRIPT_FILENAME /var/www/example1.com/public/report/index.php;
if (!-f $request_filename) {
fastcgi_pass backend;
break;
}
}
# pass everything else over to PHP-FPM via the socket
location / {
root /var/www/example1.com/public/; # absolute path doc root
index index.php index.html index.htm;
# set expire headers
if ($request_uri ~* "\.(ico|css|js|gif|jpe?g|png)$") {
expires max;
}
# set fastcgi settings, not allowed in the "if" block
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param SCRIPT_NAME /index.php;
# rewrite - if file not found, pass it to the backend
if (!-f $request_filename) {
fastcgi_pass backend;
break;
}
error_page 404 index.php;
}
access_log /var/www/example1.com/log/access.log;
error_log /var/www/example1.com/log/error.log;
}
I am no expert with Nginx, but a lot of Google searching and trial and error gave me the file above, and it seems to work. I hope it is helpful, even if this exact code doesn’t work for you.
Finally, activate the site by creating a symbolic link to it and restarting the server:
# ln -s /usr/local/nginx/sites-available/default /usr/local/nginx/sites-enabled/default
# ln -s /usr/local/nginx/sites-enabled /etc/sites
# /etc/init.d/nginx restart
And that’s it! You should now have Magento running on Nginx! (After, of course, also installing mysql and a sendmail program, and probably an FTP server, and who knows what else :)
Now, how to make it actually go faster than Apache? There are many settings you can tweak. Look in fastcgi_params to change PHP-FPM settings, php.ini to change APC settings, my.cnf to change mysql settings, nginx.conf to adjust the number of worker processes and the keepalive timeouts… the list goes on. Good luck!