It doesn’t matter whether it’s capitalized or not (the author doesn’t capitalize it), NginX is still pronounced “engine-x”. Some people like to display it as “NginX” to emphasize the pronunciation (including me), but it really doesn’t matter. Anyway… When I started doing my installation of everything on the new server, I already had resources and references available. In fact, this installation started by following the instructions at the Tutorials Pundit‘s article titled “How to: Install NginX on Ubuntu 10.04 64bit via apt-get” and I can’t add to it – it’s perfect. I suggest you go there and follow those instructions before returning here to continue with the configuration.
Configuring nginx
After I installed NginX, I was surprised that I now had the latest version. Not wanting to waste time, I got right into the NginX configuration file, /etc/nginx/nginx.conf, and started changing what needed to be changed.
This is my configuration. I’ll try to explain some of the changes I made by adding comments below the entire section:
user www-data;
worker_processes 8;
worker_rlimit_nofile 262144;
pid /var/run/nginx.pid;
events {
worker_connections 2048;
# multi_accept on;
use epoll;
}
http {
index index.php index.htm index.html;
client_max_body_size 20m;
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
#gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript
text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
worker processes 8; – I changed this from 4 to 8. The server has 16 cores, so that means it has 4 quad-core processors. I read somewhere that anything more than 4 isn’t necessary, but I wanted to spread the processes out as much as possible. I tried 16 and it locked up. 8 worked, so I left it at that. I seem to remember that only two cores are being used by most operating systems right now (and that may change again now that 6-core processors are available).
worker_rlimit_nofile 262544; – This is added. The NginX default is 1024 and it’s wrong. 1024 is the number of files that can be opened, which you can check from the shell with # ulimit -n. To find out the maximum file descriptors available, use # more /proc/sys/fs/file-max. This number is important because it has to match the number in the PHP-FPM configuration when you install that.
worker_connections 768; – I changed this from 768 to 2048. 768 is probably perfect for a 512 megabyte VPS, but mine is 2 gigabytes. By multiplying 8 worker processes by 2048 worker_connections, I know that nginx can handle up to 16384 maximum clients. If you consider how many HTTP requests come from a single web browser page load, you can appreciate a number this high.
use epoll; – This is added. Various documents about NginX indicate epoll is better than the default, so that’s what I’m using.
index index.php index.htm index.html; – This is added. The nginx Pitfalls page describes why the index directive should be within the “http” stanza instead of a location block (which a lot of people seem to do).
client_max_body_size 20m; – This is added. It needs to match the upload_max_filesize in PHP and I always set that to 20M. The NginX default is only 1 megabyte.
Gzip Settings – I removed the comment marking (“#”) from every line except gzip_http_version 1.1;. If I’m not mistaken, SSL still uses http version 1.0. I also completely removed the mail stanza since I’ll be using a combination of Courier and Postfix for my domain e-mail.
The next step is to add the server stanzas to the first domain in the /etc/nginx/sites-available. Before doing that however, the default domain needs to be copied to a backup file and then altered. This is what my default domain looks like:
server {
listen 80 default_server;
server_name _;
return 444;
}
That listen line is only necessary for the default domain and doesn’t need to be repeated anywhere else. Basically, what this does is it drops any connection trying to connect to the server by using just the IP address, a very common server log spamming technique.
Here is the configuration file for this domain:
server {
server_name untwistedvortex.com;
rewrite ^ $scheme://www.untwistedvortex.com$request_uri? permanent;
}
server {
server_name www.untwistedvortex.com;
root /home/untwistedvortexcom/httpdocs;
access_log /home/untwistedvortexcom/log/access.log;
error_log /home/untwistedvortexcom/log/error.log;
set $bad_poster "";
if ($request_method = POST) {
set $bad_poster "${bad_poster}P";
}
if ($request_uri = /wp-comments-post.php) {
set $bad_poster "${bad_poster}F";
}
if ($http_referer !~ ^(www.untwistedvortex.com) ) {
set $bad_poster "${bad_poster}R";
}
if ($http_user_agent = "") {
set $bad_poster "${bad_poster}U";
}
if ($bad_poster = PFRU) {
return 444;
}
location / {
try_files $uri $uri/ /index.php;
} location ~ /\.ht {
deny all;
}
location ~* \.(jpg|jpeg|png|gif|swf|flv|mp4|mov|avi|wmv|m4v|mkv|ico|js|css|txt)$ {
access_log off;
expires 7d;
}
location ~ ^.+\.php {
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_ignore_client_abort on;
fastcgi_read_timeout 180;
}
}
The first server stanza redirects to the second server stanza when someone tries to access the domain without the “www” in front of it. For domains that don’t use the “www”, you simply switch the server names and work from there.
The “set bad poster” routines are a replacement for the WordPress anti-comment spam conditional routines for wp-comments-post in an Apache .htaccess file and prevents spammers from bypassing a comments form. The http_referer line needs to contain the correct domain name.
The access and error logs are pointed to the domain user name directories I created when I used adduser to add it to the system. You don’t have to do that if you don’t want and especially if you’re only running one domain.
The location block with try_files replaces the .htaccess WordPress permalinks block. It works, trust me.
The location block with deny all in it just prevents access to .htpasswd since there’s no .htaccess file used with NginX.
The location block with file extensions tells NginX to serve those files immediately as static files.
I can’t really explain the location block with the fastcgi routines, other than that is what communicates with the PHP-FPM service. You’ll see some of the same numbers when you get to that part of the installation process. You may have to increase fastcgi_read_timeout 180; if you’re using WordPress (I don’t know about other applications), especially to prevent timeouts caused by using WP-Cron. I increased mine to 360 and that worked for me. Your mileage may vary.
One last file needed to be edited: /etc/nginx/fastcgi_params
The $request_filename; in this line:
fastcgi_param SCRIPT_FILENAME $request_filename;
It needed to be changed to $document_root$fastcgi_script_name;.
Coming Up
The next article in this series will be on Installing and Configuring PHP and PHP-FPM on Ubuntu 10.04 64-bit LTS.
Great post, and lots of useful information on your site.
I’ve spent hours troubleshooting why a few location directives stopped working for me after a recent upgrade to nginx 1.0.1 – just to find the changed fastcgi_params file from previous versions.
I see in your guide you’ve changed it back to the ‘old’ ways. Can you explain why it works?
I can confirm that line difference is what caused my problems, but I’m not sure why it was changed in the first place.
Well, old ways or new ways, what works, works. The fastcgi_params file is part of the upgrade you did and it overwrites anything you already had. That’s why upgrades have to be checked completely.
The first question that came to my mind was “Why choose the fourth most popular web server instead of the ‘most’ popular?”. But instead of just asking you that I decided to do a little research.
This site had a few snippets that I think best summed up what I was seeing alluded to on other sites. How do you like these:
- “Apache is like Microsoft Word, it has a million options but you only need six. Nginx does those six things, and it does five of them 50 times faster than Apache.”
- “Apache is a process-based server, while nginx is an event-based web server.”
- “Nginx and Lighttpd are probably the two best-known asynchronous servers and Apache is undoubtedly the best known process-based server. The main advantage of the asynchronous approach is scalability.”
I also read somewhere; can’t find it now, that the place nginx really shines is Virtual Hosting.
I decided to use nginx instead of Apache because of memory stability. Apache uses twice as much memory to do the same job. That in itself is a good enough reason for me.