Recent release of Nginx 1.0.0 triggered me to refresh my knowledge about its configuration options. There were quite some additions since I looked in the docs for the last time. New variables and directives let me to simplify my configuration for Symfony projects (both 1.x and 2).
Warning: Configurations published on the Internet usually suffer from the vulnerability which allows to run a non-PHP file as a PHP. More about the problem here: "Setting up PHP-FastCGI and nginx? Don’t trust the tutorials: check your configuration!". For Nginx+PHP installation read "Setting up a PHP development environment with Nginx on Ubuntu 11.04".
Configuration
The convention says we should put virtual host configurations into /etc/nginx/sites-available/ directory and then link to them in /etc/nginx/sites-enabled/.
Rules below define development virtual hosts. We'll put them into /etc/nginx/sites-available/dev file.
server {
listen 80 default;
server_name *.dev;
root /var/www/$host/current/web;
access_log /var/log/nginx/$host-access.log;
error_log /var/log/nginx/dev-error.log error;
index app.php index.html index.htm;
try_files $uri $uri/ @rewrite;
location @rewrite {
rewrite ^/(.*)$ /app.php/$1;
}
location ~ \.php {
# try_files $uri =404;
fastcgi_index app.php;
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location ~ /\.ht {
deny all;
}
}
Don't forget about the symbolic link (/etc/nginx/sites-enabled/dev).
More about the configuration
listen 80 default;
Nginx listens on the port 80 by default. What's important in this line is the second parameter - "default". It makes that Nginx treats given host as a default one.
server_name *.dev;
Our dynamic virtual host will accept every .dev domain (kuba.dev, myproject.dev etc).
Alternatively we could simply list one ore more domains (i.e. server_name zalas.eu). In such case we'd probably define every domain in a separate server {} section.
root /var/www/$host/current/web;
Root directory will be defined dynamically based on the $host variable (/var/www/kuba.dev/current/web for kuba.dev domain).
access_log /var/log/nginx/$host-access.log;
error_log /var/log/nginx/dev-error.log error;
Every domain will have its own access log. Unfortunately we cannot use $host variable with error logs. Therefore all the errors will be logged into the same file.
index app.php index.html index.htm;
Index files are checked every time URL points to the directory. Nginx will try them one by one until it finds an existing one.
app.php is a default controller in Symfony2. For symfony 1.x it's usually index.php.
try_files $uri $uri/ @rewrite;
It's a really elegant solution for readable URLs as it lets us to avoid evil if statements.
During the request Nginx will check for an existence of a file first. If the file doesn't exist it will look for a directory. If both checks fail it will rewrite the request to the named location.
location @rewrite {
rewrite ^/(.*)$ /app.php/$1;
}
This named location is reached only if user wasn't requesting an existing file or directory. We want to rewrite such a request to the default controller.
location ~ \.php {
fastcgi_index app.php;
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
All the PHP requests will be routed to the fastcgi deamon (running locally on port 9000).
Appart from including default fastcgi parameters we make sure that PATH_INFO and SCRIPT_FILENAME variables are set properly. fastcgi_split_path_info says how to split the controller file from the path.
location ~ /\.ht {
deny all;
}
This will forbid access to apache's .htaccess files. These are only simple text files for Nginx and we don't want them to be accessible via the browser.