Total Pageviews

Monday, 5 December 2011

Nginx

Nginx (pronounced "engine X") written by Igor Sysoev (Russia) in 2005, is a free, open-source, high-performance HTTP server and reverse proxy, as well as an IMAP/POP3 proxy server. According to the May 2010 Web Server Survey, Nginx now hosts nearly 6.55% of all domains worldwide, while lighttpd hosts about 0.91%. Nginx is now well known for its stability, rich feature set, simple configuration, and low resource consumption.

Contents

 [hide

Option A: Installation

The nginx package is now in the official repositories.
Or, you can compile and install the latest development version with the ABS.

Starting Service

To start the Nginx service, run:
# rc.d start nginx
The default served (i.e. the page served at http://127.0.0.1) page is:
/etc/nginx/html/index.html
(The nginx package does not install a default index.html file; you must create this file yourself, if you wish).
After creating a /etc/nginx/html/index.html webpage, you can use this URL: http://127.0.0.1 to test if Nginx is working.
To enable the Nginx service by default at start-up just add nginx to the DAEMONS array in /etc/rc.conf:
DAEMONS=(ntpd syslog-ng ... nginx)

Configuring

You can modify the configurations by editing the files in /etc/nginx/conf. (/etc/nginx/conf/nginx.conf being the main config file.)
More details can be found here: Nginx Configuration Examples.

PHP/Python Integration

FastCGI technology is introduced into Nginx to work with many external tools and servers, i.e.: PHP and Python. So, you cannot use PHP or Python service unless FastCGI server has been started.
PHP and Python can be run as FastCGI application and can process FastCGI requests from Nginx.
FastCGI is usually faster than implementations in e.g. Apache where PHP is loaded each time, with FastCGI the script is simply passed to the PHP daemon, and the appropriate value is returned and used by Nginx.

Step 1: Start the FastCGI server

There are two different ways to run FastCGI server. It is recommended to use a third party wrapper (the second method).
1st Method "New" (as of PHP 5.3.3)
PHP now contains a FastCGI server spawner that takes care of everything for you.
To get started, install php-fpm and then start the service:
# rc.d start php-fpm
Now, move to: Step 2.
Note: You can configure the number of servers in the pool and tweak other configuration options by editing the file /etc/php/php-fpm.conf. More details on php-fpm can be found on the php-fpm website.
1st Method "Old" (PHP's built-in)
Directly running PHP's built-in FastCGI server -- this method does not require any third party tools.
Arch Linux's php package in the official repositories has FastCGI support enabled already.
For example, install php and php-cgi, and then run:
$ php-cgi -b 127.0.0.1:9000 &
This command sets up the local machine as a FastCGI server using port 9000.
Note: Since NginX 0.7.62, the default internal $document_root is /etc/nginx/html which is moved outside the default NginX directory and symlinked to /usr/share/nginx/http in the Arch Linux package. For PHP to work with NginX 0.7.62 the open_basedir in /etc/php/php.ini has to contain the directory /etc/nginx/html:
open_basedir = /etc/nginx/html/:/srv/http/:/home/:/tmp/:/usr/share/pear/.
Below is a daemon script to be used in /etc/rc.conf to start PHP-cgi on boot. Save it as /etc/rc.d/fastcgi and add fastcgi to your DAEMONS array in /etc/rc.conf
#!/bin/bash
 
 . /etc/rc.conf
 . /etc/rc.d/functions
 
 case "$1" in
   start)
  stat_busy 'Starting Fastcgi Server'
  if /usr/bin/php-cgi -b 127.0.0.1:9000 &
  then
   add_daemon fastcgi
   stat_done
  else
   stat_fail fi
  fi
  ;;
   stop)
  stat_busy 'Stopping Fastcgi Server'
  [ -e /var/run/daemons/fastcgi ] && kill $(pidof php-cgi) &> /dev/null;
  if [ $? -gt 0 ]; then 
   stat_fail
  else
   rm_daemon fastcgi
   stat_done
  fi
  ;;
   restart)
  $0 stop
  $0 start
  ;;
   *)
  echo "Usage: $0 {start|stop|restart}"
 esac
2nd Method (third party wrapper)
This can be more comfortable than the first method because of increased flexibility.
There are currently three options for deploying PHP on Nginx:
  • fcgi
    • Includes cgi-fcgi
  • lighttpd
    • Includes spawn-fcgi
  • PHP-FPM (Recommended: see above)
To spawn a process, issue one of the following commands (matching the package you installed):
# cgi-fcgi -start -connect localhost:9000 /usr/bin/php-cgi
# spawn-fcgi -a 127.0.0.1 -p 9000 -C 9 -f /usr/bin/php-cgi
# php --fpm -b 127.0.0.1:
Note: You may need to edit /etc/php/php-fpm.conf at first. More details on php-fpm can be found at the php-fpm website.
Note: Sometimes, you may encounter some permission issue when running some third party software to start PHP as FastCGI-server. See Nginx#Troubleshooting.

Step 2: Edit /etc/nginx/conf/nginx.conf

Add index.php after index.htm in this line: (example below has index.php already added, you need to add it to your file manually)
location / {
      root    html;
      index   index.html index.htm index.php;
}
Then uncomment these lines and edit in the file to be as follows:
location ~ \.php$ {
      try_files $uri =404;
      root           html;
      fastcgi_pass   unix:/var/run/php-fpm/php-fpm.sock;
      fastcgi_index  index.php; 
      fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
      include        fastcgi_params;
 }
Note: If you are not using php-fpm, you may want to change the fastcgi_pass value to 127.0.0.1:9000, or whichever IP and port to which your server is configured to respond. Do not forget the semicolon at the end of the line.
Note: If you are planning to run applications that support file uploads (images, for example), be sure and include the try_files line in the above configuration, otherwise you may be exposed to a security risk by allowing arbitrary code execution. The short explanation for this behavior is that a properly crafted URI which ends in ".php", in combination with a malicious image file that actually contains valid PHP, can result in the image being processed as PHP. For more information on the specifics of this behavior, you may wish to review the information provided on Neal Poole's blog. If you are running FastCGI on another machine, this won't work and you should look at a better way to solve this.

Step 3: Restart Nginx

If Nginx has been working, run:
# rc.d restart nginx
Edit /srv/http/nginx/index.php,
<?php
  phpinfo();
?> 
Visit the URL: http://localhost/index.php with your browser, and you will find PHP has worked well with Nginx.

Ruby Integration (Ruby on Rails and Rack-based)

The Ruby on Rails wiki has tutorials on configuring Ruby for Nginx. It is not recommended to use FastCGI to make Nginx work with Ruby anymore, although very well possible. Nginx and Passenger are a great toolkit, and this setup is extremely easy to achieve on Archlinux. It should be noted, however, that there are other alternatives, including Mongrel, Thin and Unicorn.

Setting up Nginx and Passenger

Install the Nginx Passenger package from the AUR, and you are ready to go.
For further information on setting up Nginx with Ruby, read the Nginx part of this tutorial.
Note: With Passenger you are also able to run other Rack-based applications, including Sinatra. Note, however, that these require a config.ru file in the source directory.

phpMyAdmin Setup

See the following wiki article: PhpMyAdmin#NGINX_Configuration.

Security

  • Allow/deny visitors based on IP:
ngx_http_access_module.
  • HTTP authentication:
ngx_http_auth_basic_module.
  • HTTPS support:
ngx_http_ssl_module.

Option B: Ruby on Rails Oriented-Installation

See The Perfect Rails Setup.

Troubleshooting

Accessing local IP redirects to localhost

Solution from the Arch Linux forum.
Edit /etc/nginx/nginx.conf and locate the "server_name localhost" line without a # infront of it, and add below:
server_name_in_redirect off;
Default behavior is that nginx redirects any requests to the value given as server_name in the config.

Error: 403 (Permission error)

This is most likely a permission error. Are you sure whatever user configured in the Nginx configuration is able to read the correct files?
If the files are located within a home directory, (e.g. /home/arch/public/webapp) and you are sure the user running Nginx has the right permissions (you can temporarily chmod all the files to 777 in order to determine this), /home/arch might be chmod 750, simply chmod it to 751, and it should work.

Error: 404 (Pathinfo error)

In some framework(like thinkphp, cakephp) or CMS, they need the pathinfo function.
1. Edit the file /etc/php/php.ini, make sure
cgi.fix_pathinfo=1
2. Edit /etc/nginx/conf/nginx.conf, comment
location ~ \.php$ {
...
}
to
#location ~ \.php$ {
#...
#}
Then add the follows,
location ~ ^(.+\.php)(.*)$ {
  root   /srv/http/nginx;
  fastcgi_pass   unix:/var/run/php-fpm/php-fpm.sock;  
  #fastcgi_pass   127.0.0.1:9000; #Un-comment this and comment "fastcgi_pass   unix:/var/run/php-fpm/php-fpm.sock;" if you are not using php-fpm.
  fastcgi_index  index.php;
  set $document_root2 $document_root;
  if ($document_root2 ~ "^(.*\\\\).*?[\\\\|\/]\.\.\/(.*)$") { set $document_root2 $1$2; }
  if ($document_root2 ~ "^(.*\\\\).*?[\\\\|\/]\.\.\/(.*)$") { set $document_root2 $1$2; }
  if ($document_root2 ~ "^(.*\\\\).*?[\\\\|\/]\.\.\/(.*)$") { set $document_root2 $1$2; }
  if ($document_root2 ~ "^(.*\\\\).*?[\\\\|\/]\.\.\/(.*)$") { set $document_root2 $1$2; }
  if ($document_root2 ~ "^(.*\\\\).*?[\\\\|\/]\.\.\/(.*)$") { set $document_root2 $1$2; }
  fastcgi_split_path_info ^(.+\.php)(.*)$;
  fastcgi_param SCRIPT_FILENAME $document_root2$fastcgi_script_name;
  fastcgi_param PATH_INFO $fastcgi_path_info;
  fastcgi_param PATH_TRANSLATED $document_root2$fastcgi_path_info;
  include fastcgi_params;
  fastcgi_param  DOCUMENT_ROOT      $document_root2;
}

Error: The page you are looking for is temporarily unavailable. Please try again later.

This is because the FastCGI server has not been started.

Error: No input file specified

Most Likely you do not have the SCRIPT_FILENAME containing the full path to you scripts. If the configuration of nginx (fastcgi_param SCRIPT_FILENAME) is all right, this kind of error means php fail to load the requestd script. Usually it is simply a permissions issue, you can just run php-cgi as root
# spawn-fcgi -a 127.0.0.1 -p 9000 -f /usr/bin/php-cgi
or you should create some group and user to start the php-cgi. For example:
# groupadd www
# useradd -g www www
# chmod +w /srv/www/nginx/html
# chown -R www:www /srv/www/nginx/html
# spawn-fcgi -a 127.0.0.1 -p 9000 -u www -g www -f /usr/bin/php-cgi
Another occasion is that, wrong "root" argument in the "location ~ \.php$" section in nginx.conf, make sure the "root" points to the same directory as it in "location /" in the same server. Or you may just set root as global, do not define it in any location section.
Also keep in mind that your php script path was defined as /srv/www/nginx/html by default using the variable "open_basedir" in /etc/php/php.ini; you can change them if you need.

See Also

from https://wiki.archlinux.org/index.php/Nginx
----------------------------------------------------


Nginx is a fast and efficient web server. It can be configured to serve out files or be a reverse proxy depending on your application. What makes this web server different from Apache, Lighttpd or thttpd is the overall efficiency of the daemon, the number of configuration options and how easy it is to setup.
Nginx ("engine x") is a high-performance HTTP server and reverse proxy server. Nginx was written by Igor Sysoev for rambler.ru, Russia's second-most visited website, where it has been running in production for over two and a half years. Igor has released the source code under a BSD-like license. Although still in beta, Nginx is known for its stability, rich feature set, simple configuration, and low resource consumption. Nginx


The methodology behind our configuration - Trust No One

In the following example we are going to setup a simple web server to serve our static web pages to explain the basics. The daemon will load a few mime include files, compress outgoing data in real time and set the expires header to reduce bandwidth of client cached traffic. Full logging is on, in the default Apache format with the addition of compressed file size and the amount of time the server took to fulfill the request. Finally, we are going to set up restriction filters by ip to limit access to the "/secure" directory structure where you might put more sensitive non-public data.
The security mindset of the configuration is very paranoid. There are a significant amount of bots, scanners and broken clients that will abuse your site if given the opportunity. These clients will waste your bandwidth and system resources. As a response, we will not trust any client to access our server without first making sure that all of the request parameters are met. This means that the remote client must be asking for our site by the proper host name and must request any support files, like pictures and css, with the referrer headers properly set. Any deviation from these rules will lead to Nginx dropping the client's connection with a return code 444. Even though Nginx does not have a module like mod_security we can still make our own access rules. Note that even though these rules are strict, normal web traffic and bots like Google can access the site without issue.
Our goal is to setup a fast serving and CPU/disk efficient web server, but most importantly a _very secure_ web server. This configuration will work for the latest version of Nginx as well as the development versions. For the purpose of this example we built the latest development version of Nginx from source.
Below you will find a few different example nginx.conf configuration files in scrollable windows. The formats are available to make it easier for you to review the code. They are all fully working configuration files with the exception of setting up a few variables for your environment like listen port or ip.
You are welcome to copy and paste the following working examples. Before using the configuration file take a look it and then scroll down this page to the section titled, "Explaining the directives in nginx.conf".


Option 1: Nginx webserver to serve static files

This is a basic webserver running on port 80 (http) serving out web pages. Though we have added quite a few security checks, this is as basic a server as you can get. On an AMD64 2GHz machine this config will easily serve out thousands of pages a minute.
#######################################################
###  Calomel.org  /etc/nginx.conf  BEGIN
#######################################################
#
worker_processes  4;

events {
    worker_connections  1024;
}

http {
 ## MIME types
  types {
    application/xml xml;
    image/gif       gif;
    image/jpeg      jpg;
    image/png       png;
    image/bmp       bmp;
    image/x-icon    ico;
    text/css        css;
    text/html      html;
    text/plain      bob;
    text/plain      txt;
   }
  default_type       application/octet-stream;

 ## Size Limits
  client_body_buffer_size   8k;
  client_header_buffer_size 1k;
  client_max_body_size      1k;
  large_client_header_buffers 1 1k;

 ## Timeouts 
  client_body_timeout   60;
  client_header_timeout 60;
  keepalive_timeout     60 60;
  send_timeout          60;

 ## General Options
  charset                  utf-8;
  ignore_invalid_headers   on;
  limit_zone gulag $binary_remote_addr 1m;
  max_ranges                1;
  recursive_error_pages    on;
  sendfile                off;
  server_name_in_redirect off;
  server_tokens           off;
  source_charset          utf-8;

 ## TCP options  
  tcp_nodelay off;
  tcp_nopush  on;

 ## Compression
  gzip              on;
  gzip_static       on;
  gzip_buffers      16 8k;
  gzip_comp_level   1;
  gzip_http_version 1.0;
  gzip_min_length   0;
  gzip_types        text/plain text/html text/css image/x-icon image/bmp;
  gzip_vary         on;

 ## Log Format
  log_format  main  '$remote_addr $host $remote_user [$time_local] "$request"
                     $status $body_bytes_sent "$http_referer" "$http_user_agent" $ssl_cipher $request_time';

 ## Deny access to any host other than (www.)mydomain.com
    server {
         server_name  _;  #default
         return 444;
     }

 ## Server (www.)mydomain.com
  server {
      add_header  Cache-Control public;
      access_log  /var/log/nginx/access.log main buffer=32k;
      error_log   /var/log/nginx/error.log info;
      expires     31d;
      limit_conn  gulag 5;
      listen      127.0.0.1:8080 rcvbuf=64k backlog=128;
      root        /htdocs;
      server_name mydomain.com www.mydomain;

     ## Only allow GET and HEAD request methods
      if ($request_method !~ ^(GET|HEAD)$ ) {
         return 444;
      }

     ## Deny illegal Host headers
      if ($host !~* ^(mydomain.com|www.mydomain.com)$ ) {
        return 444;
      }

     ## Deny certain User-Agents (case insensitive)
     ## The ~* makes it case insensitive as opposed to just a ~
     if ($http_user_agent ~* (Baiduspider|Jullo) ) {
        return 444;
     }

     ## Deny certain Referers (case insensitive)
     ## The ~* makes it case insensitive as opposed to just a ~
     if ($http_referer ~* (babes|click|diamond|forsale|girl|jewelry|love|nudit|organic|poker|porn|poweroversoftware|sex|teen|video|webcam|zippo) ) {
        return 444;
     }

     ## Redirect from www to non-www
      if ($host = 'www.mydomain.com' ) {
        rewrite  ^/(.*)$  http://mydomain.com/$1  permanent;
      }

     ## Stop Image and Document Hijacking
      location ~* (\.jpg|\.png|\.css)$ {
        if ($http_referer !~ ^(http://mydomain.com) ) {
          return 444;
        }
      }

     ## Restricted Access directory
      location ^~ /secure/ {
            allow 127.0.0.1/32;
            allow 10.10.10.0/24;
            deny all;
            auth_basic "RESTRICTED ACCESS";
            auth_basic_user_file /var/www/htdocs/secure/access_list;
        }

     ## Only allow these full URI paths relative to document root. If you only want
     ## to reference the filename use $request_filename instead of $request_uri
      location / {
        if ($request_uri ~* (^\/|\.html|\.jpg|\.org|\.png|\.css|favicon\.ico|robots\.txt)$ ) {
          break;
        }
        return 444;
      }

     ## Serve an empty 1x1 gif _OR_ an error 204 (No Content) for favicon.ico
      location = /favicon.ico {
       #empty_gif;
        return 204;
      }

      ## System Maintenance (Service Unavailable) 
      if (-f $document_root/system_maintenance.html ) {
        error_page 503 /system_maintenance.html;
        return 503;
      }

     ## All other errors get the generic error page
      error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 495 496 497
                 500 501 502 503 504 505 506 507 /error_page.html;
      location  /error_page.html {
          internal;
      }
  }
}
#
#######################################################
###  Calomel.org  /etc/nginx.conf  END
#######################################################




Do you dislike malicious ip addresses scanning your web server and causing excessive errors? Take a look at our Web Server Abuse Detection perl script to keep track of the abusers and block them in real time.




Option 2: Nginx serving only SSL and redirecting http to https

This example configuration is for a webserver that serves out SSL (https) traffic only. We will redirect all clients that try to goto port 80 (http) to port 443 (https) with a permanent 301 redirect. This type of redirect works for Google bot and other search bots too. We will also stop illegal linking and document hijacking. On a AMD64 2GHz machine this config can serve out thousands of fully encrypted https sessions per minute without a problem.
If you need help with setting up a SSL certificate with a certificate authority like GoDaddy check out the section below titled, "How to setup a GoDaddy Turbo SSL Certificate for Nginx". If you want to learn more about SSL in general then check out our Guide to Webserver SSL Certificates.
#######################################################
###  Calomel.org  /etc/nginx.conf  BEGIN
#######################################################
worker_processes  4;

events {
    worker_connections  1024;
}

http {
 ## MIME types
  types {
    application/xml xml;
    image/jpeg      jpg;
    image/png       png;
    image/x-icon    ico;
    text/css        css;
    text/html      html;
    text/plain      bob;
    text/plain      txt;
  }
  default_type       application/octet-stream;

 ## Size Limits
  client_body_buffer_size      16k;
  client_header_buffer_size     1k;
  client_max_body_size          1k;
  large_client_header_buffers 1 1k;

 ## Global SSL options
  ssl_ciphers ECDHE-RSA-AES256-SHA:AES256-SHA:CAMELLIA256-SHA:DES-CBC3-SHA;
 #ssl_engine aesni;
  ssl_prefer_server_ciphers on;
  ssl_protocols TLSv1;
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 5m;

 ## Timeouts 
  client_body_timeout      60;
  client_header_timeout    60;
  keepalive_timeout     60 60;
  send_timeout             60;

 ## General Options
  charset                  utf-8;
  ignore_invalid_headers   on;
  keepalive_requests       10;
  max_ranges                1;
  recursive_error_pages    on;
  server_tokens           off;
  server_name_in_redirect off;
  sendfile                off;
  source_charset          utf-8;

 ## TCP options  
  tcp_nopush  off;
  tcp_nodelay on;

 ## Compression
  gzip                 on;
  gzip_static          on;
  gzip_buffers      16 8k;
  gzip_http_version   1.0;
  gzip_comp_level       1;
  gzip_min_length     100;
  gzip_types        text/plain text/html text/css image/x-icon image/gif;
  gzip_vary            on;

 ## Log Format
  log_format  main  '$remote_addr $host $remote_user [$time_local] "$request"
                     $status $body_bytes_sent "$http_referer" "$http_user_agent" $ssl_cipher $request_time';

 ## Redirect http to https
  server {
      add_header Cache-Control "public, must-revalidate";
      access_log  /var/log/nginx/access.log main;
      error_log   /var/log/nginx/error.log info;
      expires     90d;
      listen      127.0.0.1:80;
      root        /var/empty;
      server_name example.com www.example.com;

      location / {
        if ($host ~* ^(example\.com|www\.example\.com)$ ) {
          rewrite  ^/(.*)$  https://example.com/$1  permanent;
        }
        return 444;
      }
  }

## https .:. "default blank SSL server, SNI required"
   (look below for the tutorial titled, "default blank SSL server")
 #server {
 #    add_header Cache-Control "public, must-revalidate";
 #    add_header Strict-Transport-Security "max-age=7776000; includeSubdomains";
 #    expires     90d;
 #    listen      127.0.0.1:443 default;
 #    return      444;
 #    root        /var/empty;
 #    server_name _;

 #   ## SSL Certs (specific to this blank certificate)
 #    ssl                 on;
 #    ssl_certificate     ssl_keys/default_blank.crt;
 #    ssl_certificate_key ssl_keys/default_blank.key;
 #    return              403;
 #   }

 ## https .:. (www.)example.com ONLY
  server {
      access_log  /var/log/nginx/access.log main;
      add_header  Cache-Control "public, must-revalidate";
      error_log   /var/log/nginx/error.log info;
      expires     90d;
      index       index.html;
      listen      127.0.0.1:443;
      root        /var/www/htdocs;
      server_name  example.com www.example.com;

     ## SSL Certs (specific to this URL)
      ssl on;
      ssl_certificate /ssl_keys/mydomain.com_ssl.crt;
      ssl_certificate_key /ssl_keys/mydomain_ssl.key;
      ssl_ecdh_curve secp521r1;

     ## Strict Transport Security (ForceHTTPS)
      add_header Strict-Transport-Security "max-age=2592000; includeSubdomains";

     ## Only allow GET and HEAD request methods
      if ($request_method !~ ^(GET|HEAD)$ ) {
         return 444;
      }

     ## Deny illegal Host headers
      if ($host !~* ^(example.com|www.example.com)$ ) {
        return 444;
      }

     ## Deny certain User-Agents (case insensitive)
    # if ($http_user_agent ~* (Baiduspider|webalta|Wget|WordPress|youdao) ) {
    #   return 444;
    # }

     ## Deny certain Referers (case insensitive)
      if ($http_referer ~* (\.us$|dating|diamond|forsale|girl|jewelry|nudit|organic|poker|porn|poweroversoftware|sex|teen|webcam|zippo|zongdo) ) {
        return 444;
      }

     ## Only allow these full URI paths relative to document root. If you only want
     ## to reference the filename use $request_filename instead of $request_uri
      if ($request_uri !~* (^\/|\.html|\.gif|\.jpg|\.png|example\.css|robots\.txt|favicon\.ico)$ ) {
        return 444;
      }

     ## Redirect from www to non-www
      if ($host = 'www.example.com' ) {
        rewrite  ^/(.*)$  https://example.com/$1  permanent;
      }

     ## Stop Image and Document Hijacking
      location ~* (\.jpg|\.gif|\.png|example\.css)$ {
        if ($http_referer !~ ^(https://example.com) ) {
          return 444;
        }
      }

     ## Restricted Access directory
      location ^~ /secure/ {
            allow 127.0.0.1/32;
            allow 10.10.10.0/24;
            deny all;
            auth_basic "RESTRICTED ACCESS";
            auth_basic_user_file /var/www/htdocs/secure/access_list;
        }

     ## All other errors get the generic error page
      error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 495 496 497
                 500 501 502 503 504 505 506 507 /error_page.html;
      location  /example_error_page.html {
          internal;
      }
  }
}
#######################################################
###  Calomel.org  /etc/nginx.conf  END
#######################################################




Option 3: Nginx reverse proxy to a few back end web servers

A reverse proxy is a type of proxy server that retrieves resources on behalf of a client from one or more servers. These resources are then returned to the client as though it originated from the reverse proxy itself. Reverse proxies are a reat way to reduce the load on any one machine as well as help secure the web cluster from external influences. Some advantages for using a reverse proxy (source wikipedia) are:
  • Reverse proxies can hide the existence and characteristics of the origin server(s).
  • Application firewall features can protect against common web-based attacks. Without a reverse proxy, removing malware or initiating takedowns, for example, can become difficult.
  • A reverse proxy can distribute the load from incoming requests to several servers, with each server serving its own application area. In the case of reverse proxying in the neighborhood of web servers, the reverse proxy may have to rewrite the URL in each incoming request in order to match the relevant internal location of the requested resource.
  • A reverse proxy can reduce load on its origin servers by caching static content, as well as dynamic content. Proxy caches of this sort can often satisfy a considerable amount of website requests, greatly reducing the load on the origin server(s). Another term for this is web accelerator. This technique is also used for the Wikipedia servers. A reverse proxy can optimize content by compressing it in order to speed up loading times.
  • In a technique known as "spoon feeding",[2] a dynamically generated page can be produced all at once and served to the reverse-proxy, which can then return it to the client a little bit at a time. The program that generates the page is not forced to remain open and tying up server resources during the possibly extended time the client requires to complete the transfer.
  • Reverse proxies can be used whenever multiple web servers must be accessible via a single public IP address. The web servers listen on different ports in the same machine, with the same local IP address or, possibly, on different machines and different local IP addresses altogether. The reverse proxy analyses each incoming call and delivers it to the right server within the local area network.
This config is for a reverse proxy server in front of a few back end web servers. The client will connect to the proxy and depending on the hostname and path the request the proxy will forward the request to the proper backend server.
You may also want to think about switching from Apache's reverse proxy configuration (if you currently use it) due to the amount of serious vulnerabilities that have come up. By using different operating systems and software throughout your organization you can better protect yourself from a single vulnerability taking out the entire company.
In the example we have also added the ability to cache data on the proxy so requests do not have to go all the way to the back end servers. Commonly ask for data is quickly served from the proxy reducing the load of your infrastructure. We have also added client request rate limiting. This is a very good idea to limit bad clients from abusing your web servers. You can also configure Nginx to compress http calls back to the client in real time, thus saving bandwidth.
#######################################################
###  Calomel.org  /etc/nginx.conf  BEGIN
#######################################################
worker_processes  4;

events {
    worker_connections  1024;
}

http {
 ## MIME types
  types {
    application/xml xml;
    image/jpeg      jpg;
    image/png       png;
    image/x-icon    ico;
    text/css        css;
    text/html      html;
    text/plain      txt;
  }
  default_type       application/octet-stream;

 ## Timeouts 
  client_body_timeout     20;
  client_header_timeout   20;
  keepalive_timeout      20 20;
  send_timeout            20;

 ## General Options
  charset                 utf-8;
  ignore_invalid_headers     on;
  keepalive_requests        100;
  max_ranges                  0;
  recursive_error_pages      on;
  server_tokens             off;
  server_name_in_redirect   off;
  sendfile                  off;
  source_charset          utf-8;

 ## TCP options  
  tcp_nopush  off;
  tcp_nodelay on;

 ## Proxy settings
  proxy_max_temp_file_size    0;
  proxy_connect_timeout      90;
  proxy_send_timeout         90;
  proxy_read_timeout         90;
  proxy_buffer_size          4k;
  proxy_buffers              4 32k;
  proxy_busy_buffers_size    64k;
  proxy_temp_file_write_size 64k;
  proxy_intercept_errors     on;

  proxy_cache_path /disk01/web_cache levels=1:2 keys_zone=webcache:10m inactive=1d max_size=2000m;
  proxy_temp_path /disk01/web_cache/tmp;
  proxy_cache_min_uses 5;

 ## Limit requests per second. Her we limit requests to 250 requests per minute.
   limit_req_zone  $binary_remote_addr  zone=one:10m   rate=250r/m;

 ## Compression (if you want real time compression you can enable it here. Make
 ## sure your system is quite fast as compression could add a noticeable delay in
 ## sending data to the client.
 #gzip                off;
 #gzip_static          on;
 #gzip_buffers      16 8k;
 #gzip_http_version   1.0;
 #gzip_comp_level       6;
 #gzip_min_length     100;
 #gzip_types        text/plain text/html text/css image/x-icon image/gif;
 #gzip_vary            on;

 ## Log Format
  log_format main  '$remote_addr $host $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';
  log_format cache '$time_local $upstream_cache_status Cache-Control: $upstream_http_cache_control Expires: $upstream_http_expires "$request" ($status) "$http_user_agent"';

 ## back end web servers with "hot fail over". You can add as many back end
 ## servers as you like here. If you add the "backup" directive the server will
 ## only be used if the other servers are down. In this example we have two main
 ## web servers (100 and 150) being load balanced and (1.200) as the hot spare
 ## backup.
  upstream backend_web_servers {
      server 192.168.1.100:80;        
      server 192.168.1.150:80;        
      server 192.168.2.200:80 backup; 
      }

 ## http .:. clients without a host header get an error page. This will handle
 ## scanners looking for servers on an ip address and broken clients.
  server {
     add_header Cache-Control "public, must-revalidate";
     access_log  /var/log/nginx/access.log main;
     error_log   /var/log/nginx/error.log info;
     expires     30d;
     listen      192.168.1.50:80;
     server_name _;

   ## All other errors get the generic error page
      error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 495 496 497
                 500 501 502 503 504 505 506 507 /error_page.html;
      location  /error_page_generic.html {
      internal;
      }
  }

 ## This is our first hostname, example.com. Any client with a host header
 ## containing any string in this server{} block's server_name directive will be
 ## served from here.
 
 ## http .:. example.com 
  server {
     add_header Cache-Control "public, must-revalidate";
     access_log  /var/log/nginx/access.log main;
     access_log  /var/log/nginx/cache.log cache;
     error_log   /var/log/nginx/error.log info;
     expires     1h;
     listen      192.168.1.50:80;
     limit_req   zone=one  burst=1000 nodelay;
     server_name example.com www.example.com internal_lan_name.domain.lan;

    proxy_redirect     off;
    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

    proxy_cache webcache;
    proxy_cache_key $scheme$host$request_uri;
    proxy_cache_valid  200 301 302 304 60m;

   # Only allow GET, HEAD and POST request methods
    if ($request_method !~ ^(GET|HEAD|POST)$ ) {
        return 403;
    }

    ## Remember the paths are first match. If the forum string was not first
    ## then all request would goto the "default docs" webserver completely bypassing
    ## the forum server.

    # user forum
    location /forum/ {
        proxy_pass http://192.168.1.201/forum/;
    }

    # default htdocs
    location / {
        ## redirect host going to www to non-www hostname
        if ($host ~* ^(www\.example\.com)$ ) {
          rewrite  ^/(.*)$  http://example.com/$1 permanent;
        }
        proxy_pass http://backend_web_servers;
    }

   ## All other errors get the generic error page
      error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 495 496 497
                 500 501 502 503 504 505 506 507 /error_page.html;
      location  /error_page_example_com.html {
      internal;
      }

  }

 ## This next section is here to show you that nginx can proxy a completely
 ## different domain name out of the same nginx daemon. On the back end servers,
 ## someotherdomain.com is served from a different apache virtual host.

 ## http .:. someotherdomain.com
  server {
     add_header Cache-Control "public, must-revalidate";
     access_log  /var/log/nginx/access.log main;
     access_log  /var/log/nginx/cache.log cache;
     error_log   /var/log/nginx/error.log info;
     expires     1h;
     listen      192.168.1.50:80;
     limit_req   zone=one  burst=100 nodelay;
     server_name someotherdomain.com www.someotherdomain.com some_internal_lan_name.domain.lan;

    proxy_redirect     off;
    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

    proxy_cache webcache;
    proxy_cache_key $scheme$host$request_uri;
    proxy_cache_valid  200 301 302 304 60m;

    ## Only allow GET, HEAD and POST request methods
    if ($request_method !~ ^(GET|HEAD|POST)$ ) {
         return 403;
    }

    # snv server
    location /svn/ {
       proxy_pass http://192.168.1.60:8000/svn/;
    }

    # git server
    location /git/ {
       proxy_pass http://192.168.1.70:8000/git/;
    }

    # forum redirect -- for example, perhaps we do not host that
    # data anymore and want to redirect users to the new location.
    location /forum/ {
        rewrite  ^/(.*)$  http://new_loaction.somedomain.com/forum/ permanent;
    }

    # default htdocs
    location / {
        proxy_pass http://backend_web_servers;
    }

   ## All other errors get the generic error page
      error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 495 496 497
                 500 501 502 503 504 505 506 507 /error_page_3.html;
      location  /error_page_someotherdomain_com.html {
      internal;
      }
   }

}
#
#######################################################
###  Calomel.org  /etc/nginx.conf  END
#######################################################


Building the Nginx Reverse Proxy example

To make it easy we have included the source build line we used to make the reverse proxy above. It just removes all of the unneeded nginx modules and leaves only those which are needed for the proxy, caching and client rate limit restrictions.
make clean; ./configure --without-http_autoindex_module \
--without-http_browser_module --without-http_fastcgi_module \
--without-http_geo_module --without-http_empty_gif_module \
--without-http_map_module --without-http_memcached_module \
--without-http_ssi_module --without-http_userid_module \
--without-mail_pop3_module --without-mail_imap_module \
--without-mail_smtp_module --without-http_split_clients_module \
--without-http_uwsgi_module --without-http_scgi_module \
--without-http_referer_module --without-http-cache \
--without-http_upstream_ip_hash_module \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log && make && make install




For more information about OpenBSD's Pf firewall, CARP and HFSC quality of service options check out our PF Config (pf.conf), PF CARP and PF quality of service HFSC "how to's".


Building nginx from source

To get started, you need to first install nginx on your machine. The source code is available from the nginx home page and practically every distribution has pre-made packages if you prefer those. The install is very easy and it will not take you much time.
We highly recommend you build Nginx from source. This way you can modify the code if you need to and make sure you apply the latest patches when they come out.
You need to make sure that the package for PCRE is installed. Use the command "pkg_add -i pcre" to install from your chosen PKG_PATH repository. BTW, you may want to also look at the Perl script pkg_find for OpenBSD package management.
OPTIONAL: Change the Server: string of your host
The Server: string is the header which is sent back to the client to tell them what type of http server you are running and possibly what version. This string is used by places like Alexia and Netcraft to collect statistics about how many and of what type of web server are live on the Internet. To support the author and statistics for Nginx we recommend keeping this string as is. But, for security you may not want people to know what you are running and you can change this in the source code. Edit the source file src/http/ngx_http_header_filter_module.c at look at lines 48 and 49. You can change the String to anything you want.
## vi src/http/ngx_http_header_filter_module.c (lines 48 and 49)
static char ngx_http_server_string[] = "Server: MyDomain.com" CRLF;
static char ngx_http_server_full_string[] = "Server: MyDomain.com" CRLF;
OPTIONAL: annonomize you server string in the auto generated error pages
When nginx sends an error back to the client it can auto generate the error page. This error page has the error code at the top, a single horizontal line and then the string "nginx" and possibly the version number. If you want to you can take out the server string in the error page by editing the source code in the file src/http/ngx_http_special_response.c on lines 21 and 28. The following line would make the nginx generated error pages show your domain name for example.
## vi src/http/ngx_http_special_response.c (lines 21 and 28)
"<center>http://mydomain.org</center>" CRLF

## You can also change all of the built in error
## messages with just a carriage return.
static char ngx_http_error_301_page[] = CRLF;
static char ngx_http_error_302_page[] = CRLF;
static char ngx_http_error_400_page[] = CRLF;
static char ngx_http_error_401_page[] = CRLF;
static char ngx_http_error_402_page[] = CRLF;
static char ngx_http_error_403_page[] = CRLF;
static char ngx_http_error_404_page[] = CRLF;
static char ngx_http_error_405_page[] = CRLF;
static char ngx_http_error_406_page[] = CRLF;
static char ngx_http_error_408_page[] = CRLF;
static char ngx_http_error_409_page[] = CRLF;
static char ngx_http_error_410_page[] = CRLF;
static char ngx_http_error_411_page[] = CRLF;
static char ngx_http_error_412_page[] = CRLF;
static char ngx_http_error_413_page[] = CRLF;
static char ngx_http_error_414_page[] = CRLF;
static char ngx_http_error_415_page[] = CRLF;
static char ngx_http_error_416_page[] = CRLF;
static char ngx_http_error_495_page[] = CRLF;
static char ngx_http_error_496_page[] = CRLF;
static char ngx_http_error_497_page[] = CRLF;
static char ngx_http_error_500_page[] = CRLF;
static char ngx_http_error_501_page[] = CRLF;
static char ngx_http_error_502_page[] = CRLF;
static char ngx_http_error_503_page[] = CRLF;
static char ngx_http_error_504_page[] = CRLF;
static char ngx_http_error_507_page[] = CRLF;
This same file contains all of the default HTML error pages Nginx will send to the client if there is an error. Look for the functions that start with the line static char ngx_http_error_ and make any changes you find necessary. Note that the HTML text is only shown to the user and that all errors sent by Nginx will have the proper error code in the HTML headers. This means you can put anything you want into the HTML code.
OPTIONAL: change any of the default error codes
Normally you DO NOT want to change any of the standard error codes specified by RFC. But, in case you really need to you can edit the file src/http/ngx_http_request.h and look for the variables starting with NGX_HTTP_REQUEST. For example, if we wanted to change the default error code for REQUEST_URI_TOO_LARGE from 414 to 999 we could:
vi src/http/ngx_http_request.h (line 83)
OLD LINE:  #define NGX_HTTP_REQUEST_URI_TOO_LARGE     414
NEW LINE:  #define NGX_HTTP_REQUEST_URI_TOO_LARGE     999
Compiling the code
Building nginx for the AMD64 architecture on OpenBSD (running as user/group "nginx")
For the purpose of this example, Nginx was built with the following arguments. Make sure to check if you need to use one of the modules that we omit during the build. We use the methodology, "if you do not need it then do not build it in." Our example nginx.conf (option 1 and 2) works fine with the following:
make clean

./configure --with-cpu-opt=amd64 --with-http_ssl_module --with-http_gzip_static_module /
 --without-http_autoindex_module --without-http_browser_module --without-http_fastcgi_module /
 --without-http_geo_module --without-http_empty_gif_module --without-http_map_module /
 --without-http_proxy_module --without-http_memcached_module --without-http_ssi_module /
 --without-http_userid_module --prefix=/usr/local/nginx --sbin-path=/usr/local/sbin/nginx /
 --conf-path=/etc/nginx.conf --pid-path=/var/run/nginx.pid --http-log-path=/var/log/nginx/access.log /
 --error-log-path=/var/log/nginx/error.log --user=nginx --group=nginx

make && make install
Once Nginx is built and installed in place it is time to take a look at the config file.




Explaining the directives in nginx.conf

Now we need to edit the config file for your environment. Lets take a look at each of the directives that need attention.
pid /var/run/nginx.pid :   This is the location of the process id file that holds the pid number of the master Nginx process. If you wanted to re-read the nginx.conf file without restarting the daemon you could cat this file and send a HUP like so, "kill -HUP `cat /var/run/nginx.pid` .
user nginx nginx :   Is the user and group the child processes will run as. You may need to make this user and group if you install Nginx from source. Make sure this user is completely unprivileged or at least runs with the least privileges necessary to make the server work.
worker_processes 2 :   Is the number of worker processes to spawn. A worker is similar to a child process in Apache. Nginx has the ability to use more then one worker process for several reasons: use on (SMP) multiple processors machines, to decrease latency when workers are blocked by disk I/O, or to limit the number of connections per process when select() or poll() is used. The general rule of the thumb is to set the number of nginx workers to two(2) or the number of CPUs your server has; which ever is greater. But, on most servers you will find out that two(2) workers serve pages quickly and put less load on the server. The exception to this rule is if you use ssl and/or compress all of your content. If you use ssl and compression then we suggest testing your site with double the amount of workers. Our example nginx.conf has 2 workers so we would set it to 4.
For testing, we suggest using the Apache benchmark binary (ab) to stress your server and see how many connections your machine can handle. "ab" can be found in any Apache install. To calculate how many total concurrent connections nginx can support, multiply "worker_processes" times "worker_connections". Our example is setup to handle 2*1024=2048 total concurrent connections. Clients who attempt to connect after 2048 clients are already connected will be denied access. It is better to deny clients than overload the machine possibly causing a DOS.
worker_connections 1024 :   This is the amount of client connections a single child process will handle by themselves at any one time. (default: 1024) Note: Multiply worker_processes times worker_connections for the total amount of connections Nginx will handle. Our example is setup to handle 2*1024=2048 connection in total. Clients who connect after the max has been reached will be denied access.
MIME types :   This section allows nginx to identify files by extension. For example, if we serve out a .txt file then the mime type would be defined as text/plain.
include mime.types is the definition file nginx loads to identify all of the mime types. These directive simply allow our server to send the the proper file type and application type to the clients. Alternatively you can take out this line and instead define your own Mime types by using the following "type" directive".
types {...} Instead of using the "include mime.types" directive you can define your own mime types. This is especially useful option if you want to use the same mime types on many different systems or do not want to rely on a secondary definition file. You also have the option of defining a mime type for a non-standard extension. In our example we define the extension "bob" as a text/plain.
default_type application/octet-stream is the default type if a file extension has not already be defined in the mime.types file. This is useful if you serve out files with no extension or of a non standard extension. Either way, clients will be able to retrieve the file un-obstructed.
Size Limits :   These directive specify the buffer size limitations on the amount of data we will consider to be valid for a request. If the client sends to much data in one request, for example in a buffer overflow attack, then the request will be denied.
client_body_buffer_size 1k If the request body is more than the buffer, then the entire request body or some part is written in a temporary file.
client_header_buffer_size 1k is the limit on the size of all of the http headers the client can send to the server. For the overwhelming majority of requests a buffer size of 1K is sufficient. The only time you would need to increase this is if you have a custom header or a large cookie sent from the client.
client_max_body_size 1k is the maximum accepted body size of client request, indicated by the line "Content-Length" in the header of request. If size exceeds this value the client gets sent the error "Request Entity Too Large" (413). If you expect to receive files uploaded to your server through the POST request method you should increase this value.
large_client_header_buffers 1 1k is the limit of the URI request line which can not be larger than the buffer size multiplied by the amount of buffers. In our example we accept a buffer size of 1 kilobyte and there is only one(1) buffer. So, will not accept a URI which is larger than (1x1K=1K) 1 kilobyte of data. If the client sends a bigger request then Nginx will return an error "Request URI too large" (414). The longest header line of the request must also be less than the size of (1x1K=1K) 1 kilobyte, otherwise the client get the error "Bad request" (400). Limiting the client URI is important to keep a scanner or broken client from sending large requests and possibly cause a denial of service (DOS) or buffer overflow.
Timeouts :   These values specify the amount of time in seconds that Nginx will wait for the client to complete the specified action.
client_body_timeout 60 is the read timeout for the request body from client. If after this time the client sends nothing, nginx returns error "Request time out" (408).
client_header_timeout 60 is the timeout reading the title of the request of the client. If after this time the client send nothing, nginx returns error "Request time out" (408).
keepalive_timeout 60 60 the first value is for keep-alive connections with the client. The second parameter assigns the value "Keep-Alive: timeout=time" in the header of answer. Even though we used 60 seconds we really suggest you look at disabling keep-alives completely with "keepalive_timeout 0". With the speed of today's clients and their connections, keep-alives are really not needed for most sites. The other issue is every browser, and every version of each browser, has a different timeout the use for keep alives. Firewalls also have their own connection timeouts which may be shorter then the keep alives set on either the client or server. This means browsers, servers and firewalls all have to be in alignment so that keeps alives work. If not, the browser will try to request something over a connection which will never work which results in pausing and slowness for the user. Most of the time keep alives are not worth the hassle.
send_timeout 60 is response timeout to the client. Timeout is established not on the entire transfer of answer, but only between two operations of reading, if after this time client will accepts nothing, then nginx is shutting down the connection.


Want more speed? Make sure to also check out the Network Speed and Performance Guide. With a little time and understanding you could easily double your firewall's throughput.


General Options :  
ignore_invalid_headers on throws away non-standard headers in the client request. If you do not expect to receive any custom made headers then make sure to enable this option.
limit_zone gulag $binary_remote_addr 1m sets up a table we will call "gulag" which uses no more than 1 megabyte of ram to store session information keyed by remote ip address. This directive is used in conjunction with limit_conn gulag 5. The ngx_http_limit_zone_module only restricts the amount of connections from a single ip address which are currently being processed by the Nginx daemon. An error 503 will be returned to the client if request processing is being blocked at the socket level and new requests from same ip starts. limit_zone will _NOT_ help if your workload is CPU or disk bound. With several workers enabled an error 503 will be returned if two workers process requests from the same ip at the same time. But this is unlikely to happen with small requests.
This is _NOT_ a directive to limit the total number of open, "established" connections to the server per ip address!! You could use your iptables or PF firewall to limit the total amount of connections. The OpenBSD PF firewall (pf.conf) uses max-src-conn or max-src-states to limit the amount of established connections to your server.
You can increase the size of the "gulag" table from 1 megabyte if you need to. A zone size of 1M can handle 32000 sessions at a default size of 32 bytes/session. You can also change the name of the table we called "gulag" to any string you want. We thought this was a good name due to Nginx's country of origin combined with the purpose of this directive.
The HTTP 1.1 specification, circa 1999, recommends that browsers and servers limit parallel requests to the same hostname to two. Most browsers comply with the multi-threading recommendation of the specification, although downgrading to HTTP 1.0 boosts parallel downloads to four. So most web browsers are effectively throttled by this limit on parallel downloads if the objects in the web page they download are hosted on one hostname. We set this limit to 5 so browsers can open 4 connections with one slot left over as a buffer. Download accelerators can open many hundreds of connections to download a file so this directive will help to alleviate abuses.
recursive_error_pages on allows the use of the error_pages directive specified later in the config.
sendfile off enables the use of sendfile(). Sendfile relies on the OS to do actual IO, and this may not be a good idea if you are serving large files or if your OS is a little slow, like OpenBSD is. The OS will likely use something like 16k read requests and this will trash your disks with IOPS and seeks. Try either AIO or at least normal reading with big buffers and without sendfile. i.e. "sendfile off;" and "output_buffers 2 512k;" You need to be careful about using sendfile if the file being sent has any possibility of being modified ( especially truncated ) while the operation is in progress since some very odd things ( like the process crashing ) can happen on some platforms. You may just want to test your server with sendfile on and off to test.
server_name_in_redirect off turns off the server's ability to substitute the client supplied "Host" header with the virtual server variable "server_name" when a client is redirected.
server_tokens off turns off the nginx version numbers in the auto generated error pages. We do not want to display this information for security purposes.
TCP options :   These options say how we should use the TCP stack.
tcp_nodelay on TCP_NODELAY is for a specific purpose; to disable the Nagle buffering algorithm. It should only be set for applications that send frequent small bursts of information without getting an immediate response, where timely delivery of data is required (the canonical example is mouse movements).
tcp_nopush on If set, don't send out partial frames. All queued partial frames are sent when the option is cleared again. This is useful for pre-pending headers before calling sendfile(2), or for throughput optimization. As currently implemented, there is a 200 millisecond ceiling on the time for which output is corked by TCP_CORK. If this ceiling is reached, then queued data is automatically transmitted.
Compression :   These values tell nginx how to compress outgoing data. Remember that all files of the specified mime.type (gzip_types) are compressed in real time. On a P3 500MHz a 100KB HTML file takes 0.05 seconds (5 hundredths of a second) to gzip at level 9 compression (highest).
gzip on turn compression on.
gzip_static on; allows one to have pre-compressed .gz files served instead of compressing files on the fly. This is the most efficient method of serving compressed data. To use this option simply have a compressed copy of the same .html file in document root. For example, if we have the index.html file in place we will also have a pre-compressed index.html.gz file.
The following script will publish a compressed gzip file from a given html file. When you are done editing the html file execute this script to make a compressed copy ready for distribution. As soon as it is in place Nginx will serve it out. Also, make sure the date on the compressed .gz is always newer or equal to the original as Nginx will always serve out the most recent copy:
#!/bin/sh
#
## Calomel.org  publish_html2gz.sh
## usage: ./publish_html2gz.sh index.html
#
## Make a tmp copy of the original HTML file
cp $1 $1.tmp

## Remove the old gz if there is one
rm -rf $1.gz

## Compress the tmp HTML copy. Use the highest level 9
## compression and do not store dates or file names
## in the gzip header. BTW, if the compressed gz is
## larger then the original file a gzip will NOT be made.
gzip -9 -n $1.tmp -o $1.gz

## Clean up any tmp files
rm -rf $1.tmp

echo ""
echo "Verify files"
ls -al $1*

echo ""
echo "Compression statistics"
gzip -vl $1.gz
When Nginx sees the .gz file it will send this out to clients who accept compression instead of compressing the file in real time. Make sure you have built your nginx binary with the argument "--with-http_gzip_static_module". Execute "nginx -V" to see the compiled options.
gzip_buffers 16 8k allows 16 slots of 8k buffers used to respond to clients with a gzip'd response. This means the max size of our compressed responses can be no larger than 16*8= 128 kilobytes. By default Nginx limits compressed responses to 4*8k= 32 kilobytes. If you expect to return responses which compressed size is more than 32KB in size then increase the number of buffers (e.g. 16). The single buffer size of 8K can not be increased.
gzip_comp_level 1 compresses files to the lowest compression level. Level 1 is the fastest/lowest compression and level 9 is the slowest/best compression. During testing the time difference between level 1 and 9 was around 2 hundredths of a second per file on a P3 500MHz. Two(2) hundredths of a second is about the same amount of time the entire page should be rendered.
Which compression ratio is right for your server? As a test we took a standard 68.3 kilobyte HTML file and compressed it on a AMD64 1GHz machine using gzip levels 1, 6, and 9. Level 1 compressed the file 61.5%, but Level 9 took twice as long to compress the file to 67.1%. Level 1 has the best compression to time ratio. Realistically, even though the times are so short we still suggest using level 1, or at t level 6 compression to save overall bandwidth. Today's computers are fast enough that a user is unlikely to notice slightly more CPU usage compared to longer download times.
gzip     ratio  time      compressed  uncompressed
level 1  61.5%  0m0.009s  26320       68372
level 6  67.0%  0m0.016s  22560       68372
level 9  67.1%  0m0.018s  22525       68372
gzip_http_version 1.0 allows the server to send compressed data to HTTP/1.0 clients. HTTP/1.1 clients use the proper headers so they can always ask for compressed data.
gzip_min_length 0 this means that nginx should compress all files no matter what the size. The value is the size in bytes. You can always set this value to something higher if you do not wish to compress small files.
gzip_types text/plain text/html text/css image/bmp are the only files types to be compressed. For example, JPG's are already compressed so it would be useless for us to try to compress them again. TXT and BMP files on the other hand compress very well at an average of 250% smaller. Smaller files mean less bandwidth used and less time to transmit the same amount of data. This makes your site "feel" significantly faster.
gzip_vary on enables the response header "Vary: Accept-Encoding". This way clients know that our server has the ability to send out compressed data.
log_format main :   is the log format of the web logs. This format is assigned to the variable "main" and can be used later in the http section. This format is fully compatible with standard log analyzing tools like Awstats, Webalizer and custom tools like the Calomel.org Web Log Sentry. We also have added two(2) more fields at the end of each log line. "$request_time" logs how much time the server took to generate the content and "$gzip_ratio" shows what X-factor the file was compressed by. A value of 2.50 means the file was compressed 250%.
access_log and error_log :   are the locations you want the logs to be placed in. In the access_log directive you can also use the buffer command. This will buffer the access log activity into ram and once the limit has been reached Nginx will then write the logs. This can save I/O stress and bandwidth on your hard drive. You will want to remove "buffer=32k" while testing else you will not see any log output until at least 32 kilobytes of data are ready to be written to the access_log file. 32K of logs input is approximately 150 lines. The info directive on the error_log will increase the verbosity of the logs to include the reasons that clients were denied access.
expires 31d :   says we want our pages to be expired from the clients cache in 31 days. Time in the Expires header is obtained as the sum of the current system time added to the time assigned in this directive. In effect, we are saying that pages are to be expired 31 days after they were accessed by the client. You can also specify a time in hours using "h". In the Nginx v0.7.0 release you can use the format "expires modified +1d" to set the expires header based on the modified time of a file. The expire header tag will tell clients they should keep a copy of the object they already downloaded for the specified amount of time. This saves a significant amount of upload bandwidth for you. Instead of clients going from page to page downloading the same picture banner over and over again, they can keep a copy locally and just get the changes on your site. Imagine a client getting 5 pages from your site. Each page has a banner that is 15KB. With expires headers enabled that client will only download the banner once instead of 5 times (15KB compared to 75KB) saving your upload bandwidth and making your site "feel" quicker responding.
limit_conn gulag 5 :   limits remote clients to no more than 5 concurrently "open" connections per remote ip address being processed by Nginx. See the complimentary directive limit_zone gulag $binary_remote_addr 1m above for more information about defining the "gulag" table.
listen 127.0.0.1:8080 default rcvbuf=64K backlog=128 :   tells nginx to listen on localhost (127.0.0.1) port 8080. The directive rcvbuf=64K buffers incoming data (sysctl net.inet.tcp.sendspace). rcvbuf can be decreased to as little as 1K, possible decreasing the probability of overflow during a DDoS attack. The directive backlog (sysctl kern.somaxconn) are the max number of backlogged client requests Nginx will process. If you server is quite busy you will want to increase this value. We listen on 127.0.0.1:8080 in order to use the redirection rules in iptables or in OpenBSD's pf packet filter firewall. The argument "default" says that this server {...} function should handle any client request sent to this port no matter the hostname (not used in the example).
root /var/www/htdocs :   is the location of document root on your server. This is where nginx will look for all files to be served out to clients.
server_name mydomain.com www.mydomain :   means this server {...} block will only answer requests that have "mydomain.com" or "www.mydomain" host headers. By default the hostname of the machine is used. We are expecting the client to ask for the correct hostname with the Host header, if not, the default server block with "server_name _;" returns an error 444 to the client. BTW, the server_name_in_redirect and server_name directives work in conjunction with each other.
SSL Options (only enable if you use a SSL certificate)   If you are interested in setting up a SSL certificate for encrypted traffic on your site then we highly suggest reading our Guide to Webserver SSL Certificates. Once you understand the details of SSL certs then you must build Nginx from source and enable the argument "./configure --with-http_ssl_module".
ssl on; Enables the use of the ngx_http_ssl_module once it has been built into the Nginx binary.
ssl_certificate /ssl_keys/mydomain.com_ssl.crt; This file is the combined certificate which contains both of the "crt" files signed and sent to you by your certificate authority. See "How to setup a GoDaddy Turbo SSL Certificate on Nginx" below for details.
ssl_certificate_key /ssl_keys/mydomain_ssl.key; Specifies the location of the file with the secret key in PEM format for this server. This file is the public certificate secret key you made using the OpenSSL binary.
ssl_ciphers HIGH:!ADH:!MD5; says that our server will only accept SSL handshakes (pre-master) using AES 128/256 bit or 3DES 168 bit encryption at strong crypto cipher suites without anonymous DH. MD5 is also not accepted due to its know weaknesses. Both AES and 3DES are both enable for browser and BOT compatibility. The command "openssl ciphers -v 'HIGH:!ADH!MD5:@STRENGTH'" will show you all of the ciphers your version of OpenSSL supports in the HIGH level and not anonymous DH. Our Guide to Webserver SSL Certificates explains all of the details about ciphers and compatibility models.
ssl_prefer_server_ciphers on; just means that our server will use the ciphers specified in the "ssl_ciphers" directive over the ciphers preferred by remote clients. It is not a good security practice to ever trust remote clients.
ssl_protocols TLSv1; tells the server to only allow TLS version 1.0 or greater (TLSv1). It is highly recommended never to use SSL version 2 (SSLv2) or SSL version 3 (SSLv3) as they have vulnerabilities due to weak key strength. In order to be FIPS 140-2 compliant only TLSv1 (which stands for 1.0 or higher) can be used.
ssl_session_cache shared:SSL:1m; allows Nginx to cache the SSL session keys in its own cache structure instead of using OpenSSL slower, single threaded cache. This means Nginx can now take advantage of multiple worker_processes and separate the SSL jobs between them. The result is an impressive speed boost (2x or more) over the slower OpenSSL cache depending on your OS. The format of the line "shared:SSL:1m" is as follows: "shared" is the internal caching function, "SSL" is just an arbitrary name of this SSL cache (you can name it anything you want) and "1m"is the size of the cache (1 megabyte can hold around 4000 SSL cache sessions).
ssl_session_timeout 5m; is the cache session timeout between the client and the server set at 5 minutes or 300 seconds. When this time runs out the clients ssl session information is removed from the "ssl_session_cache". The reason this number was chosen is it also the default amount of time all client browsers will cache an ssl session. If you expect client to stay on your site longer and go to multiple pages you can always increase this default value. Depending on the client browser, they may or may not respect your ssl_session_timeout value if it larger than 5 minutes. 5 minutes seems to work perfectly fine for most sites.
ssl_ecdh_curve secp521r1; Elliptic curve Diffie-Hellman (ECDH) is a key agreement protocol that allows two parties, each having an elliptic curve public-private key pair, to establish a shared secret over an insecure channel. secp521r1 is a 521 bit Elliptic curve key and the strongest, most compatible and most widely supported key agreement protocol. For example, Here at Calomel.org, increased security is achieved with an initial 521 bit Elliptic curve Diffie-Hellman key agreement and SHA1 message authentication. Calomel.org prefers negotiating with a browser client using the Transport Layer Security (TLS) protocol and the Advanced Encryption Standard (AES) cipher at 256 bit encryption with the CBC block cipher mode. The end result of a 521 bit ECDHE handshake and a 256 bit AES key is a true 256 bit symmetric key size security model (ECDHE-RSA-AES256-SHA). Take a look at the NSA's paper titled, The Case for Elliptic Curve Cryptography for more details.




How to setup a GoDaddy Turbo SSL Certificate for Nginx
  • Goto your SSL Certificate Authority company of choice (GoDaddy Turbo SSL Certificates DV sell for little as $14 a year) and purchase it. You will be asked to upload a Certificate Signing Request (CSR) by GoDaddy. Use our Guide to Webserver SSL Certificates and look for the section titled, "How to request a SSL certificate from a Certificate Authority (CA)". The explains how to use the OpenSSL binary to generate the CSR.
  • When you provide GoDaddy with your CSR, you will be offered a link to download your signed certificates at the top of the SSL page. IMPORTANT NOTE: Make sure to choose the "APACHE" certificate type when asked what format to download in; else you will not receive any usable files.
  • When you receive the certificate file it will probably be compressed in ZIP format. In the zip file will be two files: one named with your domain like "mydomain.com.crt" and one called "gd_intermediate_bundle.crt". You will need to combine both of the files for Nginx to understand them.
  • THE ORDER IS IMPORTANT: make a new file called mydomain.com_ssl.crt. Put your certificate file first into the combined crt, for example "cat mydomain.com.crt > mydomain.com_ssl.crt". Then put the gd_intermediate_bundle.crt into the combined crt file, for example "cat gd_intermediate_bundle.crt >> mydomain.com_ssl.crt". Now the mydomain.com_ssl.crt is your Nginx "ssl_certificate" file.
  • Finally, make a directory outside of the web document tree and limit access to it to root and the Nginx web daemon only. In our example we will make a directory called /ssl_keys. Both your public "key" file generated by OpenSSL (ssl_certificate_key /ssl_keys/mydomain_ssl.key) and the combined certificate "crt" file (ssl_certificate /ssl_keys/mydomain.com_ssl.crt) are copied to /ssl_keys. It is a good idea to make both file read only by the Nginx daemon. Now you can test your SSL server.




Why setup a "default blank SSL server" ?

When a client browser asks for your server they should request the hostname you registered your SSL certificate for. In our example, we registered www.example.com and example.com. If a remote client asks for anything other than these they should not be allow to get to our site. The reason being that if they did not ask for our site by name then the SSL certificate is going to be invalid. The second reason is security. If you are not asking for our site they you should not be able to get to our site.
A "default blank SSL server" is the catch all for any client not specifically asking for our site by name.
In order to allow multiple SSL certificates to be served from a single IP address we need to use virtual hosting with Server Name Indication. This means that your nginx build must report that it is supporting TLS with SNI like this:
user@machine$  nginx -V
nginx version: nginx/0.8.45
TLS SNI support enabled
If your server supports SNI you are good to go. If not, you will probably need to upgrade your version of Nginx or possibly get a newer version of OpenSSL. The example above used Nginx v0.8.45 and OpenSSL v1.0.0a for example. Now you can setup a second server block in Nginx.conf.
The following code from our "SSL only webserver" example above will tell Nginx to serve out the blank, self-signed SSL certificate for any clients not using the hostname www.example.com or example.com. This includes any scanners looking at the ip address of the server or any bad clients using false "Host:" headers.
## https .:. default blank SSL server
  server {
      listen              127.0.0.1:443 default;
      server_name         _;
      ssl                 on;
      ssl_certificate     ssl_keys/default_blank.crt;
      ssl_certificate_key ssl_keys/default_blank.key;
      return              403;
     }
We need to generate the certificate "crt" and public "key" files for Nginx. The following commands will make a self-signed certificate and key file without a pass phrase. The ssl cert is blank will not give any information to anyone looking at it.
First we need to make a new key. This will be a 4096 bit key signed using AES at 256 bits. Put in any pass phrase you want because we are going to remove it in the next step.
openssl genrsa -aes256 4096 > default_blank.key
Next, this is a dummy key we really do not care about so this command will remove the pass phrase.
openssl rsa -in default_blank.key -out default_blank.key
Third, create a certificate signing request. The only question you need to answer if the first one for Country. Put any two(2) letters in like "US" and hit enter for the rest. Make sure to keep the "hostname" entry blank too.
openssl req -new -key default_blank.key -out default_blank.csr
self sign your own certificate.
openssl x509 -req -days 1460 -in default_blank.csr -signkey default_blank.key -out default_blank.crt
Finally, copy the default_blank.crt and default_blank.key into your "ssl keys" directory so Nginx can find them.

Testing the setup

Using openssl and the s_client directive we can query the server for the proper hostname and server name using SNI. For this example we will use our real hostname calomel.org. What you are looking for in the output is the "Certificate chain" information. The real SSL cert will show multiple entries for the CA like GoDaddy. The blank SSL cert will show zero certificates in the chain and no real information. The following line will properly access the server.
openssl s_client -servername calomel.org -connect calomel.org:443
The second test should be to test a failure. Here we connect to the proper hostname calomel.org on port 443, but we ask for the wrong hostname in the SSL certificate with the "-servername" directive.
openssl s_client -servername NotTheRightHost.com -connect calomel.org:443
NOTE: there are some clients that can not use SNI enabled servers. Very OLD browsers like IE5 and Firefox v1.0 are not compatible. Strangely, some modern versions of Wget are also not compatible, but Curl and Elinks are. Modern OS's and browsers do support SNI as well as search bots like Googlebot, MSN and Yahoo. As and added bonus we find that a lot of the spammer bots do not negotiate SNI very well.




IMPORTANT NOTE: Why are we using the error code "return 444" ?

In the following sections you will notice we are using the directive "return" with an error code 444, i.e "return 444". This is a custom error code understood by the Nginx daemon to mean, "Close the connection using a tcp reset with the client without sending any headers."
Nginx understands that if you want to send the client the 444 error code (only 400-417 and 500-505 are allowed by RFC) then Nginx should just close the connection to the client. Just dropping the connection and sending an empty TCP reset packet to the client will deny scanner information about the server and _may_ confuse them.
So what is the difference in using an error 404 compared to an 444? Lets take a look at the header results using the cURL command to a server sending a 404 error. FYI: cURL will be sending the HEAD request to the server. Notice the server sends back a set of headers with the error code and some information about the server.
user@machine: curl -I http://www.somedomain.com/
HTTP/1.1 404 Not Found
Server: Nginx
Date: Mon, 10 Jan 2020 20:10:30 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Keep-Alive: timeout=5
This is what cURL says about a Nginx server returning an error 444. The server sent nothing back to the client and closed the connection. The client did not get any useful information about the server. If you are paranoid about security or just do not want to provide and data to clients who cause errors, this is a good response for them.
user@machine: curl -I http://www.somedomain.com/
curl: (52) Empty reply from server
If you wish to change the return code to those found in the error_codes directive then your error page will be sent out instead. For example, instead of using code 444 you could send a 403 (Forbidden). For a full list of the error codes and their official definitions check out the w3.org Error Status Code Definitions.




Directive explanation and insight

Only requests to our Host are allowed :   This condition is to make sure that only clients who are asking for mydomain.com or www.mydomain.com are allowed access to our server. If a client is scanning web servers then they might ask for the ip address and this is NOT allowed by our rules.
Strict Transport Security add_header :   Strict Transport Security (STS or HSTS) is a proposed HTTPS response header that will require the user agent (such as a web browser) to access the website using secure connections only (such as HTTPS). The header specifies a period of time during which the user agent is not allowed to access the site insecurely. We use 2592000 seconds or 30 days.
When Strict-Transport-Security is active for a website, a complying user agent like Firefox, Internet Explorer, Opera or Chrome does the following: It automatically turns any insecure links to the website into secure links. (For instance, http://www.example.com/page/ will be modified to https://www.example.com/page/ before accessing the server.) Secondly, if the security of the connection cannot be ensured (e.g. the server's TLS certificate is self-signed), show an error message and do not allow the user to access the site despite the error. Strict-Transport-Security helps protect website users against some passive (eavesdropping) and active network attacks. A man-in-the-middle attacker will not be able to intercept any request to a website while the user's browser has Strict-Transport-Security active for that site. -Wikipedia (STS)
Only allow GET and HEAD request methods :   Request Method restrictions allow you to filter on GET, HEAD, POST, SEARCH, etc. We will be limiting access to our example server to GET and HEAD requests only as we do not allow uploads or any other options due to security concerns. All other request methods will get an error defined by "return 444".
Deny certain User-Agents :   You may want to list out some user-agents you do not want connecting to your server. They can be scanners, bots, spammers or any one else you find is abusing your server.
Deny certain Referers :   Referer spam is more of an annoyance than a problem. A web site or bot will connect to your server with the referer field referencing their web site. The idea is that if you publish your web logs or statistics then their hostname will show up on your page. When a search bot like Google comes by it will see the link from your site to theirs and give the spammers more PageRank credit. First, never make your weblogs public. Second, block access to referer spammers with these lines.
Redirect from www to non-www :   is if you prefer clients who connect to your site to instead use the non-www domain. For example, if a browser connects to www.mydomain.com they will be redirected to the URL mydomain.com with a code 301. If they then save your site location in a bookmark it will show up as the preferred non-www domain.
Stop Image and Document Hijacking :   Image hijacking is when someone makes a link to your site to one of your pictures or videos, but displays it on their site as their own content. The reason this is done is to send a browser to your server to use your bandwidth and make the content look like part of the hijacker's site. This is most common as people make links to pictures and add them to a public forum or blog listing. They get to use your picture in their content and not have to use their bandwidth or server to host the file. In order to keep your bandwidth usage low you should block access to images from those clients who are not referring the content from a page on your site. Note, this function can be used for any kind on content. Just add the file types to the list. If would like more ideas on lowering bandwidth usage check out our Saving Webserver Bandwidth (Tips).
Restricted Access directory :   This area is to limit access to a private or content sensitive directory. We will be limiting access to it by ip address (first check) and if that passes then ask for a password (second check). Both must match before access is granted.
access control list :   This is a way you can define a directory and only allow clients coming from the specified ips to have access. Use this function to allow internal LAN clients access to the status pages or employee contact information and deny other clients. In our example we will allow the clients coming from localhost (127.0.0.1/32) and internal LAN ips 10.10.10.0/24 to access the protected "secure" directory. BTW, if you use OpenBSD's pf packet filter firewall we highly suggest enabling "synproxy" in your pf.conf for all connections to your web server. Normally when a client initiates a TCP connection to a server, PF will pass the handshake packets between the two endpoints as they arrive. PF has the ability, however, to proxy the handshake. With the handshake proxied, PF itself will complete the handshake with the client, initiate a handshake with the server, and then pass packets between the two. The benefit of this process is that no packets are sent to the server before the client completes the handshake. This eliminates the threat of spoofed TCP SYN floods affecting the server because a spoofed client connection will be unable to complete the handshake.
password protected area :   If you are coming from an authorized ip address then we will ask for a username and password. If you have an area of the web site you only want authorized personnel to see then you should protect it. This set of directives will password protect the directory "/secure" and all files and directories under it. We will use the basic method which is the authors best choice to use especially for non-https sites. It will not send any of the passwords in clear text. Check "man htdigest" for details.
To make the "access_list" password file use the binary htdigest in the following form. Supply the "username" and "password" pair for access. Remember that our configuration file will look for this file at /var/www/htdocs/secure/access_list :
htpasswd -b -c access_list username password
Only allow these file types to document root :   We want to restrict access to our server to clients who are actually looking for data we serve out. For example, if a client is asking for a PHP file and we do not serve that type of file then we want to deny them access.
"(^\/|\.html|\.css|\.jpg|favicon\.ico|robots\.txt|\.png)$" matches the incoming request. If a request fails to match than this service will be skipped and the client will get an error. If all services fail to match Nginx returns a generic error (next section). The example URL string specifies the file types we expect a client to want to retrieve. The dollar sign ($) says that all the strings listed must be located at the end of the request URL. This line will allow:
  • ^\/ allows the root request http://mydomain.com/ to be accepted. / is expanded into /index.html by the web server
  • \.html HTML page files
  • \.css Cascading Style Sheets
  • \.jpg JPG pictures
  • favicon\.ico is the only .ico file
  • robots\.txt is the only text file
  • \.png PNG pictures
  • $ says that each of these strings have to be located at the end of the line
Serve an empty 1x1 gif _OR_ an error 204 (No Content) for favicon.ico :   Using either of these lines simply direct the Nginx daemon to serve out an empty 1x1 pixel (43 byte) favicon.ico file to the client or send back a return code 204, meaning "No content". When either option is in place you do not need a file called favicon.ico in your document root. This is perfect for anyone who sees the favicon.ico as useless and does not want to waste any bandwidth on it, but also do not want to see "file not found" errors in their logs. For more information make sure to read the section titled, "The Cursed favicon.ico" on our Webserver Optimization and Bandwidth Saving Tips page.
System Maintenance :   This function will look for the file /system_maintenance.html in the document root. If the file exists then _ALL_ client requests will be redirected to this file with an error code 503 (Service Unavailable). If the file does not exist then your pages will be served as normal. The purpose is so that you can work on your site and still keep the Nginx daemon up to show helpful information to your users. The system_maintenance.html file can contain something as simple as "Site Temporarily Down. Be back up soon." It is vitally important to send clients an error code 503 in order to notify them that the page they are looking for has NOT changed, but that the site is temporally down. Google for example understands this error and will return to index your page later. If you were to redirect Google to the /system_maintenance.html page and send them a code 200 for example, Google might replace the indexing information they have with this page. Your site would then have to be completely re-indexed once you got your site back up. Definitely not what you want to happen.
All other errors get the generic error page :   If the client fails the previous tests then they will receive our error_page.html. This error page will be sent out for all error codes listed (400-417, 500-505). Note the use of the internal directive? This means that an external client will not be able to access the /error_page.html file directly, only Nginx can serve this file to a client.




Starting the daemon

Make sure that the user and group Nginx is going to run as exists and can access the files in document root. Our example file will run the child daemons as the user "nginx" and the group "nginx".
Now that you have the config file installed in /etc/nginx.conf and configured you can start the daemon by hand with "/usr/local/sbin/nginx" or add the following into /etc/rc.local to start the Nginx daemon on boot.
#### Nginx start in /etc/rc.local
if [ -x /usr/local/sbin/nginx ]; then
   echo -n ' Nginx'; /usr/local/sbin/nginx
fi




In Conclusion

Nginx has many more options not covered in this how to. We highly suggest taking some time to read the Nginx English Wiki if you need more web functionality. If you are happy with the options we have started out with then at this point all that is left is finding some content to serve and setup your web tree.




Strip Unnecessary White space like spaces, tabs and new line characters

How much bandwidth can you expect to save by stripping out white space? On average , one could expect to save 2% of the total size of the HTML pages written by hand or previously unoptimized. If your average page size is 100 kilobytes you could save around 2 kilobytes every time they were served. If you served a hundred thousand pages per day you could reduce your bandwidth usage by 200 megabytes per day. Not a lot, but every bit makes a difference.
This is a simple perl script called "strip_whitespace.pl". It will read in any html file and output the stripped version. Use this script to make a published copy of your html docs while keeping the human readable versions in a private directory. BTW, we use this code with the pre-compression option in Nginx to serve out pre-stripped, pre-compressed files to save on bandwidth and CPU time.
#!/usr/bin/perl -w
#
## Calomel.org -- strip_whitespace.pl
#
## PURPOSE: This program will strip out all
##    whitespace from a HTML file except what is
##    between the pre and /pre and tags.
#
## DEPENDANCIES: p5-HTML-Parser which you can get by CPAN or
##    installing a package from your OS supporters.
#
## USAGE: ./strip_whitespace.pl < input.html > output.html
#

use HTML::Parser;
my $preserve = 0;

# Ignore any test between the /pre tags
sub process_tag
{
    my ($tag, $text) = @_;
    if ($tag eq 'pre') { $preserve = 1; }
    elsif ($tag eq '/pre') { $preserve = 0; }
    print $text;
}

# Replace all white space with a single space except what
# is between the pre tags. This includes all tabs (\t),
# returns (\r) and new line characters (\n).
sub process_default
{
    my ($text) = @_;
    $text =~ s/\s+/ /g unless $preserve;
    print $text;
}

undef $/;
$_ = <STDIN>;

my $p = HTML::Parser->new(
    start_h => [\&process_tag, 'tag,text'],
    end_h => [\&process_tag, 'tag,text'],
    default_h => [\&process_default, 'text']
);

$p->parse($_);

## EOL




Questions?

How do I rotate the logs in Nginx ?
There are two option regarding Nginx log rotation: you can use logrotate or you can write your own script. Using logrotate is good if you are on a Linux system and it is available. If you are running on OpenBSD or FreeBSD using the simple script method might be better. Let's look at both.
Logrotate: This is the config for the logrotate daemon. Just make a file called "/etc/logrotate.d/nginx" with the following in it. This will rotate the log files daily and keep 12 archived copies. The Nginx daemon will then be HUP'd and start writing to the new log files. Please make sure the kill line points to the location the nginx.pid is in on your machine.
user@machine:~# cat /etc/logrotate.d/nginx 
/var/log/nginx/*.log {
        daily
        missingok
        rotate 12
        compress
        delaycompress
        notifempty
        create 644 nobody root
        sharedscripts
        postrotate
                kill -USR1 `cat /usr/local/nginx/logs/nginx.pid` > /dev/null
        endscript
}

Script method log rotation: This is a simple script to move the files to another directory and date them. The script is run daily through cron.
## First make this script and make sure it is executable by the root user,
## "chmod 700 /root/nginx_logrotate.sh" and "chown root /root/nginx_logrotate.sh"

root@machine:~# cat /root/nginx_logrotate.sh 
#!/bin/bash
#
## Nginx log rotation

## move the logs
mv /var/log/nginx/access.log /log_archives/access.log_`date +%F`
mv /var/log/nginx/error.log /log_archives/error.log_`date +%F`
mv /var/log/nginx/cache.log /log_archives/cache.log_`date +%F`

## HUP nginx to start new log files
kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`

## clear out old log files after 90 days
find /log_archives/ -type f -mtime 90 -exec ls -la {} \;


## Second, add a cron job to execute the log rotation script every night at 23:59 (11:59pm)

root@machine:~# crontab -l
## nginx log rotation
59   23    *   *   *   /root/nginx_logrotate.sh
How can Nginx log to a central log server ?
One way to get Nginx to log to a central log server or loghost is to use rsyslog. The newest Linux distributions should already have rsyslog installed by default. Rsyslog will simply log any lines found in the access log to the central loghost facility. Once this config is setup just restart rsyslog and look in /var/log/syslog for the webserver logs.
## First, add this line to the /etc/rsyslog.conf . This will add support for log file reading. 
$ModLoad imfile

## Second, make a file called /etc/rsyslog.d/nginx.conf and put the following
## in it. This will tell rsyslog to look at the Nginx access log located at
## /var/log/nginx/access.log and log at the "info" level. This method is very
## efficient.

root@machine:~# cat /etc/rsyslog.d/nginx.conf 
$InputFileName /var/log/nginx/access.log
$InputFileTag nginx: 
$InputFileStateFile stat-nginx-access 
$InputFileSeverity info  
$InputRunFileMonitor 
How can I time the latency of multiple TCP and SSL handshakes ?
Curl is the tool of choice. Here we make two(2) connections to encrypted.google.com and time the responses from both the 3 way TCP handshake and the SSL negotiation of Google's 1024 bit rsa certificate key. We see that the first connection completes the 3 way TCP handshake in 32ms and the SSL handshake finishes 95ms after that. The second connection on the next line is all 0.00's because Google allows keepalive connections. So, the second request went over the same TCP connection as the first and thus saved us time. Keepalive's are quite useful when used correctly.
### bash shell
$ export URL=https://encrypted.google.com
$ curl -w "tcp: %{time_connect} ssl:%{time_appconnect} .. $URL\n" -sk -o /dev/null $URL -o /dev/null $URL
tcp: 0.032 ssl:0.095 .. https://encrypted.google.com
tcp: 0.000 ssl:0.000 .. https://encrypted.google.com
How can I best optimize Nginx for HTTPS connections ?
SSL negotiations consume a bit more CPU resources than a standard http connection. Understand that the amount of CPU used for HTTPS is not excessive, but the negotiation process does add a bit of delay (latency) to the initial connection process. On multi-processor systems you want to run several worker processes which are no less than the number of available CPU cores. By cores we mean real cores and not hyperthread Intel virtual cores.
The most CPU-intensive operation in HTTPS is the SSL handshake. There are a few ways to minimize the number of operations per client:
  • First, enable keepalive connections to send several requests via one connection.
  • Second, reuse SSL session parameters to avoid SSL handshakes for parallel and subsequent connections.
  • Third, decide how many clients will connect per second and figure out if your cipher and hardware can handle the load

Enable keepalivesEnable the "keepalive" directive to allow a remote client to send multiple queries per TCP connections. Take a look at our examples above concerning keepalive_requests and keepalive_timeout.
keepalive_requests    10;
keepalive_timeout     60 60;

Setting up SSL session cacheThe sessions stored in an SSL session cache are shared between workers and configured by the ssl_session_cache directive. One megabyte of the cache contains around four thousand (4000) sessions. The default cache timeout is 5 minutes and this can be increased by using the ssl_session_timeout directive. Here is a sample of the "Option 2" configuration from above. Just like in the example Nginx is optimized for a quad core system with 10M shared session cache:
worker_processes  4;

http {
  ## Global SSL options
  ssl_ciphers HIGH:!ADH:!MD5;
  ssl_prefer_server_ciphers on;
  ssl_protocols TLSv1;
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 5m;

  server {
   listen            443;
   server_name       example.com www.example.com;
   keepalive_timeout 60;

   ssl               on;
   ssl_certificate /ssl_keys/mydomain.com_ssl.crt;
   ssl_certificate_key /ssl_keys/mydomain_ssl.key; 
   ...

How many ssl clients and how fast can we encrypt data?You need to know how many SSL enable clients will be connecting to your servers per second and how fast you can encrypt the data flow. As we stated before the majority of time with SSL connections is taken up by the SSL handshake. The cipher you choose and the CPU in your machine are going to be the determining factors on how fast you negotiate with clients and how fast you encrypt data.
For these tests we will be using an Intel Quad core Xeon CPU L5630 @ 2.13GHz with 4gig of 1333MHz ram. The test OS is OpenBSD v5.0 (stable) and OpenSSL 1.0.0a. AES-NI (AES New Instructions) or the Advanced Encryption Standard (AES) Instruction Set can be enabled in our BIOS and is supported by our CPU. AES-NI is an extension to the x86 instruction set architecture for microprocessors from Intel and AMD with the purpose to improve the speed of applications performing encryption and decryption using the Advanced Encryption Standard (AES). The AES standard is comprised of three block ciphers, AES-128, AES-192 and AES-256, adopted from a larger collection originally published as Rijndael.
The first test will show us how fast our system can sign our ssl certificate during a handshake and how many ssl clients we can handshake with per second. A handshake is the action of the client and server opening up an encrypted connection between each other and negotiating with the site's SSL certificate. The common size of a SSL certificate is 1024, 2048 or 4096 bits. For example we sign calomel.org with a rsa 4096 bit key. So, when a client connects to our site they must negotiate with us with a rsa 4096 bit certificate.
The "sign" and "sign/s" are the values we want to examine. Make special note that the first results are for a single core and Nginx can work with multiple cores depending on your "worker_processes" directive. At rsa 4096, like what calomel.org is using, openssl specifies this machine can handshake with 44.9 clients per second per core and complete each certificate signing in 22ms (0.022). At rsa 2048 openssl can handle 300.1 SSL handshakes per second per core and sign in 0.3ms (0.003).
Note: AES-NI does NOT increase the speed of handshakes at all.
#### Intel Quad core Xeon CPU L5630 @ 2.13GHz
 user@machine: openssl speed rsa
                   sign    verify    sign/s verify/s
 rsa 4096 bits 0.022267s 0.000336s     44.9   2977.1 (1 core)
 rsa 2048 bits 0.003332s 0.000092s    300.1  10814.8 (1 core)
 rsa 1024 bits 0.000535s 0.000030s   1867.7  33674.9 (1 core)

 user@machine: openssl speed -multi 4 rsa
                   sign    verify    sign/s verify/s
 rsa 4096 bits 0.005498s 0.000084s    181.9  11922.5 (4 cores)
 rsa 2048 bits 0.000831s 0.000023s   1203.6  43244.5 (4 cores)
 rsa 1024 bits 0.000134s 0.000007s   7435.1 134482.8 (4 cores)
The second test shows how much block cipher data our system can encrypt in real time. This simulates a bulk data transfer like uploading or downloading a large file encrypted over SSL after the handshake is completed. We see that our machine and openssl can process over (145855.83k / 1024) 142 megabytes per second per core of AES 256bit, 8192 byte chunked encrypted data. This is where AES-NI can help the most. If we enable AES-NI we can almost quadruple the encryption / decryption speed as a single core can processes (402330.62k / 1024) 392 megabytes per second per core up from 142 megabytes per second per core. If we use all four(4) cores we could saturate a 10 gigabit link.
### single core AES 256bit encryption 
 user@machine:  openssl speed -engine aesni aes-256-cbc
 The 'numbers' are in 1000s of bytes per second processed.
 type          16 bytes      64 bytes     256 bytes    1024 bytes    8192 bytes
 aes-256 cbc   51537.86k     53793.62k    54669.65k    143895.81k    145855.83k (single core)
 aes-256-cbc  269689.64k    328777.67k   401489.65k    400522.80k    402330.62k (single core AES-NI on)

### four(4) cores AES 256bit encryption 
 user@machine:  openssl -multi 4 -engine aesni speed aes-256-cbc
 The 'numbers' are in 1000s of bytes per second processed.
 type          16 bytes      64 bytes     256 bytes    1024 bytes    8192 bytes
 evp          197800.42k    212958.32k   218247.91k    574456.18k    578834.20k (4 cores)
 evp         1078184.98k   1222598.23k  1574396.94k   1610181.83k   1609346.98k (4 cores AES-NI on)

SSL optimization conclusionsHow do I know if my machine supports AES-NI? The new range of Intel and AMD CPU's have support for AES-NI. You should see a section in your BIOS called "AES-NI" under the CPU processor options. You can also check to see if your OS supports AES-NI. We used OpenBSD v5.0 stable and this does. You can use the command "openssl engine -t" and it should report "(aesni) Intel AES-NI engine [available]". If you see "(no-aesni)" anywhere on the line then AES-NI is NOT supported for your hardware even though the engine is available. Again, you need to make sure you enable the AES-NI option in the BIOS if available before the OS can support the option. Be aware that in order for you to take advantage of AES-NI the hardware (Intel L5630 CPU), the BIOS, the OS (OpenBSD v5.0 stable) and the program (OpenSSL 1.0.0.a) you use must all support AES-NI instructions.
What if you need more speed than a single machine can offer? In most cases it is more cost effective to buy a weaker SSL certificate (1024 bit or 2048 bit compared to 4096 bit) than it is to buy SSL hardware. Looking at the results of the test above we see our machine can sign a 4096bit key 181.9 handshakes per second using all four(4) cores. What if you need to support 500 handshakes per second? You can buy more machines or you could just use a weaker rsa key if your business plan allows it. Our tests show this machine can support 1203.6 handshakes per second when using a rsa 2048 certificate key.
You can also take a look at some hardware SSL accelerator cards. They are beyond the scope of this article. What we have seen is hardware cards add too much overhead to the process to be truly viable and they normally do not help to speed up the handshake process. The hardware cards normally just speed up the AES block cipher encryption like AES-NI did. We prefer to add more machines to our cluster as this is the best price to performance option. If you have a few moderately powered front end SSL web proxies this will be a lot less expensive to run than one huge machine. Also, if one of the small front end goes down the others can take over. If the huge machine dies then you are offline. We prefer the smaller modular design.
Can Nginx support many HTTPS domains on a single ip address ?
Yes. A solution for running several HTTPS servers on a single IP address is TLSv1.1 Server Name Indication extension (SNI, RFC3546), which allows a browser to pass a requested server name during the SSL handshake and, therefore, the server will know which certificate it should use for the connection. Support is available in all modern browsers. Note: regardless of server SNI support, older browsers always get the certificate of default server and they complain if a server name does not match a certificate's server name. Theoretically, after this step you may redirect them to an other server, but it's too late from user point of view.
In order to use SNI in Nginx, SNI must be supported in both the OpenSSL library with which the Nginx binary has been built as well as the library to which it is being dynamically linked at run time. OpenSSL supports SNI since 0.9.8f version if it was built with config option --enable-tlsext. Since OpenSSL 0.8.9j this option is enabled by default. If nginx was built with SNI support, then nginx will show this when run with the -V switch:
$ nginx -V
   ...
 TLS SNI support enabled
   ...
However, if the SNI-enabled nginx is linked dynamically to an OpenSSL library without SNI support, nginx displays the warning:
nginx was built with SNI support, however, now it is linked
dynamically to an OpenSSL library which has no tlsext support,
therefore SNI is not available
When using SSL, where does Nginx get its entropy ?
Nginx uses OpenSSL's default entropy source. On Unix systems OpenSSL will try to use use /dev/urandom, /dev/random, /dev/srandom one after another. On FreeBSD /dev/urandom is symlink to /dev/random. On OpenBSD /dev/arandom is used. We highly advise using /dev/arandom On OpenBSD or FreeBSD if possible as it is extremely fast and uses high entropy. /dev/arandom uses the arc4random() method.
The arc4random() function provides a high quality 32-bit pseudo-random number very quickly. arc4random() seeds itself on a regular basis from the kernel strong random number subsystem described in random(4). On each call, an ARC4 generator is used to generate a new result. The arc4random() function uses the ARC4 cipher key stream generator, which uses 8*8 8-bit S-Boxes. The S-Boxes can be in about (2**1700) states.
The entropy source can be redefined by using the "SSLRandomSeed" directive and pointing to the new device. For example you can use the Simtec Electronics Entropy USB Key for high-quality random number generation.
For more detailed information about entropy check out our Entropy and random number generators page.
Is Nginx susceptible to the Slowloris DoS attack like Apache ?
It can be. Slowloris (slowloris.pl) holds connections open by sending partial HTTP requests. It continues to send subsequent headers at regular intervals to keep the sockets from closing. In this way webservers can be quickly tied up. In particular, servers that have threading enabled will tend to be more vulnerable, by virtue of the fact that they attempt to limit the amount of threading they'll allow.
Slowloris will wait for all the sockets to become available before it's successful at consuming them, so if it's a high traffic website, it may take a while for the site to free up it's sockets. So while you may be unable to see the website from your client, others may still be able to see it until all sockets are freed by them and consumed by Slowloris. This is because other users of the system must finish their requests before the sockets become available for Slowloris to consume.
Though it is difficult to be completely immune to this type of attack, Nginx is quite resilient. You can practice good web server security by doing the following:
  1. Limit the amount of connections and how fast those connections can be made from any ip address to your web server by use of your firewall. This can be done with PF (we have a "how to") or Iptables.
  2. Time out clients who take too long to perform any action.
  3. Drop clients immediately who send invalid data.
  4. Limit the amount or memory, cpu time and system resources the webserver can use. This is so the webserver can not take down the machine if the site is attacked.
The following Nginx directives will timeout clients who take too long to communicate their intentions to the server. The ignore_invalid_headers directive will drop any client trying to send invalid headers to the server. The explanations of each one is listed above on this page.
  • client_header_timeout 60;
  • client_body_timeout 60;
  • keepalive_timeout 60;
  • ignore_invalid_headers on;
  • send_timeout 60;
How do I setup log rotation for Nginx logs on OpenBSD?
Add the following two lines to the bottom of the /etc/newsyslog.conf file. This will rotate the logs if they are larger then 512KB and gzip the old file. We will keep a total of 4 log files.
root@machine# vi /etc/newsyslog.conf

# logfile                       owner:group  mode count size when flags
/var/log/nginx/access.log       root:wheel   644  4     512  *     Z     /var/run/nginx.pid
/var/log/nginx/error.log        root:wheel   644  4     512  *     Z     /var/run/nginx.pid
Is it possible to ask Nginx to look in Memcached, but if not found to look on the local file system before passing to the back end? Would this make things more efficient?
Yes, it's possible, but it would NOT be more efficient.
Sending the file from the local file system is most efficient way if kernel VM has cached that file: then sendfile() will be a zero-copy operation: you save memory and CPU time. Working with memcached or a back end server requires:
  • copy operations to the kernel by memcached or back end systems,
  • then copy operations from the kernel by nginx,
  • then copy operations to the kernel by nginx
If memcached or a back end server are on the same computer as nginx, then all these operations involve context switches between nginx and memcached or back end.
quoted from the author, Igor Sysoev
In what circumstances would Nginx take advantage of multiple CPUs or cores?
From my experience nginx needs more CPUs in 3 cases:
  • nginx does a lot of gzip'ing
  • nginx handles many SSL connections
  • the kernel processes a lot of TCP connections of around 3,000 requests/s.
For example, one could use a quad core for a PHP back end and a dual core for the nginx proxy to handle the connections and compressing the output.
paraphrased from the author, Igor Sysoev
I am interested in setting up a SSL encrypted server (https port 443). Can your help me?
Yes. Please check out our Guide to Webserver SSL Certificates. Setting up SSL through Nginx is quite easy. What is most important is understanding how SSL encryption works and what your expectations should be.
Do you have a listing of all of the nginx directives?
The nginx wiki site has all of the config directives listed on the Nginx Wiki Configuration File Options page.
Can you suggest a good web page optimization reporting site?
We highly suggest taking a look at PageTest - Web Page Optimization and Performance Test. It is free and will analyze a page and show graphs pertaining to your sites performance and speed of delivery.
How can I test to see if my server is actually compressing/gzip'ing served files?
Look at the logs and take a look at the end of each line. In the log format directive from our example above we defined the $gzip_ratio to show if a file is compressed. If you would rather use an external site for verification then check out WhatIsMyIp Gzip Test page. Put in the full URL in question and it will display the results. Finally, you can use the utility cURL, "curl -I --compressed http://localhost". This will show you the headers returned from the server. Look for a header "Content-Encoding: gzip".
I am looking for a simpler web server. Can your help me?
If you want a dead simple web server then check out the tHttpd "how to". It is a webserver that is ready to use by executing one line and it works really well too。
from https://calomel.org/nginx.html
----------------------------------------
 实战Nginx:取代Apache的高性能Web服务器

目录
第1部分 基础篇
第1章 Nginx简介
1.1 常用的Web服务器简介
1.2 Nginx简介
1.3 选择Nginx的理由
1.4 Nginx与Apache、Lighttpd的综合对比
第2章 Nginx服务器的安装与配置
2.1 安装Nginx服务器所需要的系统资源
2.2 Nginx的下载
2.3 Nginx的安装
2.4 Nginx的启动、停止、平滑重启
2.5 Nginx的平滑重启
2.6 Nginx的信号控制
2.7 Nginx的平滑升级
第2部分 进 阶 篇
第3章 Nginx的基本配置与优化
3.1 Nginx的完整配置示例
3.2 Nginx的虚拟主机配置
3.3 Nginx的日志文件配置与切割
3.4 Nginx的压缩输出配置
.3.5 Nginx的自动列目录配置
3.6 Nginx的浏览器本地缓存设置
第4章 Nginx与PHP(FastCGI)的安装、配置与优化
4.1 获取相关开源程序
4.2 安装PHP 5.2.10(FastCGI模式)
4.3 安装Nginx 0.8.15
4.4 配置开机自动启动Nginx + PHP
4.5 优化Linux内核参数
4.6 在不停止Nginx服务的情况下平滑变更Nginx配置
4.7 编写每天定时切割Nginx日志的脚本
第5章 Nginx与JSP、ASP.NET、Perl的安装与配置
5.1 Nginx与JSP(Tomcat)在Linux上的安装、配置
5.2 Nginx与ASP.NET(Mono+FastCGI)在Linux上的安装、配置
5.3 Nginx与Perl(FastCGI)在Linux上的安装、配置
第6章 Nginx HTTP负载均衡和反向代理的配置与优化
6.1 什么是负载均衡和反向代理
6.2 常见的Web负载均衡方法
6.3 Nginx负载均衡与反向代理的配置实例
6.4 Nginx负载均衡的HTTP Upstream 模块
6.5 Nginx负载均衡服务器的双机高可用
第7章 Nginx的Rewrite规则编写实例
7.1 什么是Nginx的Rewrite规则
7.2 Nginx Rewrite规则相关指令
7.3 PCRE正则表达式语法
7.4 Nginx的Rewrite规则编写实例
7.5 Nginx与Apache的Rewrite规则实例对比
第8章 Nginx模块开发
8.1 Nginx模块概述
8.2 Nginx模块编写实践
第9章 Nginx的Web缓存服务与新浪网的开源NCACHE模块
9.1 什么是Web缓存?
9.2 Nginx的Web缓存服务
9.3 新浪网开源软件项目——基于Nginx的NCache网页缓存系统
第3部分 实战篇
第10章 Nginx在国内知名网站中的应用案例
10.1 Nginx反向代理与负载均衡类网站应用案例
10.2 Nginx+PHP类网站应用案例
第11章 Nginx的非典型应用实例
11.1 用HTTPS(SSL)构建一个安全的Nginx Web服务器
11.2 采用Nginx搭建FLV视频服务器
11.3 Nginx+PHP+MySQL在小内存VPS服务器上的优化
11.4 采用Nginx搭建正向代理服务器
第4部分 模块篇
第12章 Nginx的核心模块
12.1 主模块指令
12.2 主模块变量
12.3 事件模块指令
第13章 Nginx的标准HTTP模块
13.1 HTTP的核心模块
13.2 HTTP Upstream模块
13.3 Http Access 模块
13.4 HTTP Auth Basic 模块
13.5 Http Autoindex 模块
13.6 Http Browser 模块
13.7 Http Charset 模块
13.8 Http Empty Gif模块
13.9 Http Fcgi 模块
13.10 geo 模块
13.11 Gzip 模块
13.12 Http Headers模块
13.13 Http Index模块
13.14 HTTP Referer模块
13.15 Http Limit Zone模块
13.16 Http Limit Req模块
13.17 Http Log模块
13.18 Http Map模块
13.19 Http Memcached模块
13.20 Http Proxy模块
第14章 Nginx的其他HTTP模块
14.1 Http Addition模块
14.2 Embedded Perl模块
14.3 Flv Stream模块
14.3 flv 指令
14.4 Http Gzip Static模块
14.5 Http Random Index模块
14.6 Http Geo IP模块
14.7 Http RealIp模块
14.8 Http SSL模块
14.9 Http Stub Status模块
14.10 Http Sub模块
14.11 Http Dav模块
14.12 Google Perftools模块
14.13 Http XSLT模块
14.14 Http Secure Link模块
14.15 Http Image Filter模块
第15章 Nginx的邮件模块
15.1 Nginx邮件核心模块
15.2 Nginx邮件认证模块
15.3 Nginx邮件代理模块
15.4 Nginx邮件SSL模块
15.5 Nginx邮件模块配置实例

from http://www.inginx.com/download/nginx-pdf-download.zip
--------------------------------------------------------------------------
 Nginx 常见应用技术指南

作者:NetSeek  http://www.linuxtone.org (IT运维专家网|集群架构|性能调优)

欢迎转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明.

首发时间: 2008-11-25     更新时间:2009-1-14

– NGINX 运行参数

nginx -s stop         快速关闭nginx,可能不保存相关信息,并迅速终止web服务。

nginx -s quit         平稳关闭nginx,保存相关信息,有安排的结束web服务。

nginx -s reload       因改变了nginx相关配置,需要重新加载配置而重载。

nginx -s reopen       重新打开日志文件。

nginx -t              不运行,而仅仅测试配置文件。

目 录

一、        Nginx 基础知识

二、        Nginx 安装及调试

三、        Nginx Rewrite

四、        Nginx Redirect

五、        Nginx 目录自动加斜线:

六、        Nginx Location

七、        Nginx expires

八、        Nginx 防盗链

九、        Nginx 访问控制

十、        Nginx日志处理

十一、     Nginx Cache

十二、      Nginx负载均衡

十三、       Nginx简单优化

十四、        如何构建高性能的LEMP环境

十五、        Nginx服务监控

十六、        常见问题与错误处理.

十七、        相关资源下载

【前言】:

编写此技术指南在于推广普及NGINX在国内的使用,更方便的帮助大家了解和掌握NGINX的一些使用技巧。本指南很多技 巧来自于网络和工作中或网络上朋友们问我的问题.在此对网络上愿意分享的朋友们表示感谢和致意!欢迎大家和我一起丰富本技术指南提出更好的建议!请朋友们 关注: http://www.linuxtone.org 技术分享社区! 互想学习共同进步!

一、 Nginx 基础知识

1、简介

Nginx (“engine x”) 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,它已经在该站点运行超过两年半了。Igor 将源代码以类BSD许可证的形式发布。尽管还是测试版,但是,Nginx 已经因为它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名了。

更多的请见官方wiki: http://wiki.codemongers.com/

2、 Nginx的优点

nginx做为HTTP服务器,有以下几项基本特性:

1)        处理静态文件,索引文件以及自动索引;打开文件描述符缓冲.

2)        无缓存的反向代理加速,简单的负载均衡和容错.

3)        FastCGI,简单的负载均衡和容错.

4)        模块化的结构。包括gzipping, byte ranges, chunked responses, 以及 SSI-filter等filter。如果由FastCGI或其它代理服务器处理单页中存在的多个SSI,则这项处理可以并行运行,而不需要相互等待。

5)        支持SSL 和 TLS SNI .

Nginx专为性能优化而开发,性能是其最重要的考量, 实现上非常注重效率 。它支持内核Poll模型,能经受高负载的考验, 有报告表明能支持高达 50,000 个并发连接数。

Nginx具有很高的稳定性。其它HTTP服务器,当遇到访问的峰值,或者有人恶意发起慢速连接时,也很可能会导致服务器物理内存耗尽频繁交换,失 去响 应,只能重启服务器。例如当前apache一旦上到200个以上进程,web响应速度就明显非常缓慢了。而Nginx采取了分阶段资源分配技术,使得它的 CPU与内存占用率非常低。nginx官方表示保持10,000个没有活动的连接,它只占2.5M内存,所以类似DOS这样的攻击对nginx来说基本上 是毫无用处的。就稳定性而言, nginx比lighthttpd更胜一筹。

Nginx支持热部署。它的启动特别容易, 并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。你还能够在不间断服务的情况下,对软件版本进行进行升级。

Nginx采用master-slave模型, 能够充分利用SMP的优势,且能够减少工作进程在磁盘I/O的阻塞延迟。当采用select()/poll()调用时,还可以限制每个进程的连接数。

Nginx代码质量非常高,代码很规范, 手法成熟, 模块扩展也很容易。特别值得一提的是强大的Upstream与Filter链。 Upstream为诸如reverse proxy, 与其他服务器通信模块的编写奠定了很好的基础。而Filter链最酷的部分就是各个filter不必等待前一个filter执行完毕。它可以把前一个 filter的输出做为当前filter的输入,这有点像Unix的管线。这意味着,一个模块可以开始压缩从后端服务器发送过来的请求,且可以在模块接收 完后端服务器的整个请求之前把压缩流转向客户端。

Nginx采用了一些os提供的最新特性如对sendfile (Linux 2.2+),accept-filter (FreeBSD 4.1+),TCP_DEFER_ACCEPT (Linux 2.4+) 的支持,从而大大提高了性能

二、 Nginx 安装及调试

1、Pcre 安装
   

./configure

make && make install

cd ../

2.        nginx 编译安装
   

#/usr/local/nginx/sbin/nginx -t

2008/12/16 09:08:35 [info] 28412#0: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok

2008/12/16 09:08:35 [info] 28412#0: the configuration file /usr/local/nginx/conf/nginx.conf was tested successfully

更详细的模块定制与安装请参照官方wiki.

3、Nginx 配置文件测试:
   

#/usr/local/nginx/sbin/nginx -t

2008/12/16 09:08:35 [info] 28412#0: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok

2008/12/16 09:08:35 [info] 28412#0: the configuration file /usr/local/nginx/conf/nginx.conf was tested successfully

3、Nginx 启动:
   

#/usr/local/nginx/sbin/nginx

4、Nginx 配置文件修改重新加载:
   

#kill -HUP `cat /usr/local/nginx/logs/nginx.pid

三、Nginx Rewrite

1.  Nginx Rewrite 基本标记(flags)

last – 基本上都用这个Flag。

※相当于Apache里的[L]标记,表示完成rewrite,不再匹配后面的规则

break – 中止Rewirte,不再继续匹配

redirect – 返回临时重定向的HTTP状态302

permanent – 返回永久重定向的HTTP状态301

※原有的url支持正则  重写的url不支持正则

2.  正则表达式匹配,其中:

    * ~         为区分大小写匹配

    * ~*       为不区分大小写匹配

    * !~和!~*   分别为区分大小写不匹配及不区分大小写不匹配

3. 文件及目录匹配,其中:

 * -f和!-f用来判断是否存在文件

    * -d和!-d用来判断是否存在目录

    * -e和!-e用来判断是否存在文件或目录

    * -x和!-x用来判断文件是否可执行

3.  Nginx 的一些可用的全局变量,可用做条件判断:

$args
$content_length
$content_type
$document_root
$document_uri
$host
$http_user_agent
$http_cookie
$limit_rate
$request_body_file
$request_method
$remote_addr
$remote_port
$remote_user
$request_filename
$request_uri
$query_string
$scheme
$server_protocol
$server_addr
$server_name
$server_port
$uri

四、 Nginx Redirect

将所有linuxtone.org与netseek.linuxtone.org域名全部自跳转到http://www.linuxtone.org

server



{



listen 80;



server_name linuxtone.org netseek.linuxtone.org;



index index.html index.php;



root /data/www/wwwroot;



if ($host !~ "^www\.linxtone\.org$") {



rewrite ^(.*) http://www.linuxtone.org$1 redirect;



}



........................



}

五、 Nginx 目录自动加斜线:
   

if (-d $request_filename){



rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;



}

六  Nginx Location

1.基本语法:[和上面rewrite正则匹配语法基本一致]

location [=|~|~*|^~] /uri/ { … }

* ~  为区分大小写匹配

    * ~* 为不区分大小写匹配

    * !~和!~*分别为区分大小写不匹配及不区分大小写不匹配

示例1:
   

location = / {



# matches the query / only.



# 只匹配 / 查询。



}

匹配任何查询,因为所有请求都已 / 开头。但是正则表达式规则和长的块规则将被优先和查询匹配

示例2:
   

location ^~ /images/ {



# matches any query beginning with /images/ and halts searching,



# so regular expressions will not be checked.



# 匹配任何已 /images/ 开头的任何查询并且停止搜索。任何正则表达式将不会被测试。

示例3:
   

location ~* \.(gif|jpg|jpeg)$ {



# matches any request ending in gif, jpg, or jpeg. However, all



# requests to the /images/ directory will be handled by



}

# 匹配任何已 gif、jpg 或 jpeg 结尾的请求。

七、 Nginx expires

1.根据文件类型expires
   

# Add expires header for static content



location ~* \.(js|css|jpg|jpeg|gif|png|swf)$ {



if (-f $request_filename) {



root /data/www/wwwroot/bbs;



expires      1d;



break;



}



}

2、根据判断某个目录
   

# serve static files



location ~ ^/(images|javascript|js|css|flash|media|static)/  {



root    /data/www/wwwroot/down;



expires 30d;



}

八、  Nginx 防盗链

1.        针对不同的文件类型   

#Preventing hot linking of images and other file types



location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)$ {



valid_referers none blocked server_names *.linuxtone.org linuxtone.org http://localhost baidu.com;



if ($invalid_referer) {



rewrite   ^/   ;



# return   403;



}



}

2.        针对不同的目录
   

location /img/ {



root /data/www/wwwroot/bbs/img/;



valid_referers none blocked server_names *.linuxtone.org http://localhost baidu.com;



if ($invalid_referer) {



rewrite  ^/  ;



#return   403;



}



}

3.        同实现防盗链和expires的方法
   

#Preventing hot linking of images and other file types



location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)$ {



valid_referers none blocked server_names *.linuxtone.org linuxtone.org http://localhost ;



if ($invalid_referer) {



rewrite   ^/   ;



}



access_log off;



root /data/www/wwwroot/bbs;



expires 1d;



break;



}

九、 Nginx 访问控制

1.        Nginx 身份证验证   

#cd /usr/local/nginx/conf



#mkdir htpasswd



/usr/local/apache2/bin/htpasswd -c /usr/local/nginx/conf/htpasswd/tongji linuxtone



#添加用户名为linuxtone



New password:   (此处输入你的密码)



Re-type new password:   (再次输入你的密码)



Adding password for user



http://count.linuxtone.org/tongji/data/index.html(目录存在/data/www/wwwroot/tongji/data/目录下)



将下段配置放到虚拟主机目录,当访问http://count.linuxtone/tongji/即提示要密验证:



location ~ ^/(tongji)/  {



root    /data/www/wwwroot/count;



auth_basic              "LT-COUNT-TongJi";



auth_basic_user_file  /usr/local/nginx/conf/htpasswd/tongji;



}

2.        Nginx 禁止访问某类型的文件.

如,Nginx下禁止访问*.txt文件,配置方法如下.   

location ~* \.(txt|doc)$ {



if (-f $request_filename) {



root /data/www/wwwroot/linuxtone/test;



#rewrite …..可以重定向到某个URL



break;



}



}

方法2:

location ~* \.(txt|doc)${



root /data/www/wwwroot/linuxtone/test;



deny all;



}

实例:

禁止访问某个目录
   

location ~ ^/(WEB-INF)/ {



deny all;



}

3.        使用ngx_http_access_module限制ip访问
   

location / {



deny    192.168.1.1;



allow   192.168.1.0/24;



allow   10.1.1.0/16;



deny    all;



}

详细参见wiki: http://wiki.codemongers.com/NginxHttpAccessModule#allow

4.        Nginx 下载限制并发和速率
   

limit_zone   linuxtone  $binary_remote_addr  10m;



server



{



listen       80;



server_name  down.linuxotne.org;



index index.html index.htm index.php;



root   /data/www/wwwroot/down;



#Zone limit



location / {



limit_conn   linuxtone  1;



limit_rate  20k;



}



..........



}

只允许客房端一个线程,每个线程20k.

【注】limit_zone   linuxtone  $binary_remote_addr  10m; 这个可以定义在主的

5.        Nginx 实现Apache一样目录列表
   

location  /  {



autoindex  on;



}

6.        上文件大小限制

主配置文件里加入如下,具体大小根据你自己的业务做调整。
   

client_max_body_size 10m;

十、        Nginx 日志处理

1.Nginx 日志切割
   

#contab -e



59 23 * * * /usr/local/sbin/logcron.sh /dev/null 2>&1



[root@count ~]# cat /usr/local/sbin/logcron.sh



#!/bin/bash



log_dir="/data/logs"



time=`date +%Y%m%d`



/bin/mv  ${log_dir}/access_linuxtone.org.log ${log_dir}/access_count.linuxtone.org.$time.log



kill -USR1 `cat  /var/run/nginx.pid`

更多的日志分析与处理就关注(同时欢迎你参加讨论):http://bbs.linuxtone.org/forum-8-1.html

2.利用AWSTATS分析NGINX日志

设置好Nginx日志格式,仍后利用awstats进行分析.

请参考: http://bbs.linuxtone.org/thread-56-1-1.html

3.        Nginx 如何不记录部分日志

日志太多,每天好几个G,少记录一些,下面的配置写到server{}段中就可以了
   

location ~ .*\.(js|jpg|JPG|jpeg|JPEG|css|bmp|gif|GIF)$



{



access_log off;



}

十一、Nginx Cache服务配置

如果需要将文件缓存到本地,则需要增加如下几个子参数:
   

proxy_store on;



proxy_store_access user:rw group:rw all:rw;



proxy_temp_path 缓存目录;

其中,

proxy_store on用来启用缓存到本地的功能,

proxy_temp_path用来指定缓存在哪个目录下,如:proxy_temp_path html;

在经过上一步配置之后,虽然文件被缓存到了本地磁盘上,但每次请求仍会向远端拉取文件,为了避免去远端拉取文件,必须修改
   

proxy_pass:



if ( !-e $request_filename) {



proxy_pass  http://mysvr;



}

即改成有条件地去执行proxy_pass,这个条件就是当请求的文件在本地的proxy_temp_path指定的目录下不存在时,再向后端拉取。

更多更高级的应用可以研究ncache,详细请参照http://bbs.linuxtone.org 里ncache相关的贴子.

十二、Nginx 负载均衡

1. Nginx 负载均衡基础知识

nginx的upstream目前支持4种方式的分配

1)、轮询(默认)

每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

2)、weight

指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。

2)、ip_hash

每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。

3)、fair(第三方)

按后端服务器的响应时间来分配请求,响应时间短的优先分配。

4)、url_hash(第三方)

2.        Nginx 负载均衡实例1
   

upstream bbs.linuxtone.org {#定义负载均衡设备的Ip及设备状态



server 127.0.0.1:9090 down;



server 127.0.0.1:8080 weight=2;



server 127.0.0.1:6060;



server 127.0.0.1:7070 backup;



}

在需要使用负载均衡的server中增加

proxy_pass http://bbs.linuxtone.org/ ;

每个设备的状态设置为:

a)        down 表示单前的server暂时不参与负载

b)        weight 默认为1.weight越大,负载的权重就越大。

c)        max_fails :允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误

d)        fail_timeout:max_fails次失败后,暂停的时间。

e)        backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。

nginx支持同时设置多组的负载均衡,用来给不用的server来使用。

client_body_in_file_only 设置为On 可以讲client post过来的数据记录到文件中用来做debug

client_body_temp_path 设置记录文件的目录 可以设置最多3层目录

location 对URL进行匹配.可以进行重定向或者进行新的代理 负载均衡

3.        Nginx 负载均衡实例 2

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效,也可以用作提高Squid缓存命中率.

简单的负载均等实例:
#vi nginx.conf  //nginx主配置文件核心配置



……….



#loadblance my.linuxtone.org



upstream  my.linuxtone.org  {



ip_hash;



server   127.0.0.1:8080;



server   192.168.169.136:8080;



server   219.101.75.138:8080;



server   192.168.169.117;



server   192.168.169.118;



server   192.168.169.119;



}



…………..



include          vhosts/linuxtone_lb.conf;



………



# vi proxy.conf



proxy_redirect off;



proxy_set_header Host $host;



proxy_set_header X-Real-IP $remote_addr;



proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;



client_max_body_size 50m;



client_body_buffer_size 256k;



proxy_connect_timeout 30;



proxy_send_timeout 30;



proxy_read_timeout 60;proxy_buffer_size 4k;



proxy_buffers 4 32k;



proxy_busy_buffers_size 64k;



proxy_temp_file_write_size 64k;



proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;



proxy_max_temp_file_size 128m;



proxy_store on;



proxy_store_access   user:rw  group:rw  all:r;



#nginx cache



#client_body_temp_path  /data/nginx_cache/client_body 1 2;



proxy_temp_path /data/nginx_cache/proxy_temp 1 2;
   

#vi  linuxtone_lb.conf



server



{



listen  80;



server_name my.linuxtone.org;



index index.php;



root /data/www/wwwroot/mylinuxtone;



if (-f $request_filename) {



break;



}



if (-f $request_filename/index.php) {



rewrite (.*) $1/index.php break;



}error_page 403 http://my.linuxtone.org/member.php?m=user&a=login;



location / {



if ( !-e $request_filename) {



proxy_pass http://my.linuxtone.org;



break;



}



include /usr/local/nginx/conf/proxy.conf;



}



}

十三、Nginx简单优化

1.        减小nginx编译后的文件大小 (Reduce file size of nginx)

默认的nginx编译选项里居然是用debug模式(-g)的(debug模式会插入很多跟踪和ASSERT之类),编译以后一个nginx有好几兆。去掉nginx的debug模式编译,编译以后只有几百K

在 auto/cc/gcc,最后几行有:
   

# debug



CFLAGS=”$CFLAGS -g”

注释掉或删掉这几行,重新编译即可。

2.        修改Nginx的header伪装服务器

1)        修改nginx.h
   

#vi nginx-0.7.30/src/core/nginx.h



#define NGINX_VERSION      "1.8"



#define NGINX_VER          "LTWS/" NGINX_VERSION#define NGINX_VAR          "NGINX"



#define NGX_OLDPID_EXT     ".oldbin"

2) 修改nginx_http_header_filter_module
   

#vi nginx-0.7.30/src/http/ngx_http_header_filter_module.c

将如下
static char ngx_http_server_string[] = "Server: nginx" CRLF;

修改为   

static char ngx_http_server_string[] = "Server: LTWS" CRLF;

a)        修改nginx_http_header_filter_module
   

#vi nginx-0.7.30/src/http/ngx_http_special_response.c

将如下:
   

static u_char ngx_http_error_full_tail[] =



"<hr><center>" NGINX_VER "</center>" CRLF



"</body>" CRLF



"</html>" CRLF
static u_char ngx_http_error_tail[] =



"<hr><center>nginx</center>" CRLF



"</body>" CRLF



"</html>" CRLF



;

修改为:
   

static u_char ngx_http_error_full_tail[] =



"<center> "NGINX_VER" </center>" CRLF



"<hr><center>http://www.linuxtone.org</center>" CRLF



"</body>" CRLF



"</html>" CRLF



;static u_char ngx_http_error_tail[] =



"<hr><center>LTWS</center>" CRLF



"</body>" CRLF



"</html>" CRLF



;

修改后重新编译一下环境,

404错误的时候显示效果图(如果没有指定错误页的话):

利用curl命令查看服务器header

3.为特定的CPU指定CPU类型编译优化.

默认nginx使用的GCC编译参数是-O

需要更加优化可以使用以下两个参数
   

--with-cc-opt='-O3'



--with-cpu-opt=opteron

使得编译针对特定CPU以及增加GCC的优化.

此方法仅对性能有所改善并不会有很大的性能提升,供朋友们参考.

CPUD类型确定:
   

#cat /proc/cpuinfo | grep "model name"

编译优化参数参考:http://en.gentoo-wiki.com/wiki/Safe_Cflags

4.Tcmalloc优化Nginx 性能
   

# wget http://download.savannah.gnu.org/releases/libunwind/libunwind-0.99-alpha.tar.gz



# tar zxvf libunwind-0.99-alpha.tar.gz



# cd libunwind-0.99-alpha/



# CFLAGS=-fPIC ./configure



# make CFLAGS=-fPIC



# make CFLAGS=-fPIC install



# wget http://google-perftools.googlecode.com/files/google-perftools-0.98.tar.gz



# tar zxvf google-perftools-0.98.tar.gz



# cd google-perftools-0.98/



# ./configure



# make && make install



# echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf



# ldconfig



# lsof -n | grep tcmalloc

编译nginx 加载google_perftools_module:
   

./configure --with-google_perftools_module

在主配置文件加入nginx.conf 添加:
   

google_perftools_profiles /path/to/profile;

5.内核参数优化

# vi /etc/sysctl.conf   #在末尾增加以下内容:
   

net.ipv4.tcp_fin_timeout = 30



net.ipv4.tcp_keepalive_time = 300



net.ipv4.tcp_syncookies = 1



net.ipv4.tcp_tw_reuse = 1



net.ipv4.tcp_tw_recycle = 1



net.ipv4.ip_local_port_range = 5000 65000

#使配置立即生效   

/sbin/sysctl -p

十四、如何构建高性的LEMP

请参见: http://www.linuxtone.org/lemp/lemp.pdf

1、提供完整的配置脚本下载:http://www.linuxtone.org/lemp/scripts.tar.gz

2、提供NGINX常见配置范例含(虚拟主机,防盗链,Rewrite,访问控制,负载均衡

Discuz相关程序静态化及等等),你只要稍稍修改即可线上应用。 3、将原版的xcache替换成EA,并提供相关简单调优脚本及配置文件。

更多的及更新资料请关注: http://www.linuxtone.org

十五、Nginx监控

1、RRDTOOL+Perl脚本画图监控

先安装好rrdtool ,关于rrdtool本文不作介绍,具体安装请参照linuxtone监控版块.
   

#cd /usr/local/sbnin



#wget http://blog.kovyrin.net/files/mrtg/rrd_nginx.pl.txt



#mv rrd_nginx.pl.txt rrd_nginx.pl



#chmod a+x rrd_nginx.pl



#vi rrd_nginx.pl   //配置脚本文件设置好路径



#!/usr/bin/perl



use RRDs;



use LWP::UserAgent;



# define location of rrdtool databases



my $rrd = '/data/www/wwwroot/nginx/rrd';



# define location of images



my $img = '/data/www/wwwroot/nginx/html';



# define your nginx stats URL



my $URL = "http://219.232.244.13/nginx_status";



…………

【注】根据自己具体的状况修改相应的路径.

#crontab ?e //加入如下

* * * * * /usr/local/sbin/rrd_nginx.pl

重启crond后,通过配置nginx虚拟主机指到/data/www/wwwroot/nginx/html目录,通过crond自动执行perl脚本会生成很多图片.

http://xxx/connections-day.png即可看到服务器状态图。

2、        官方Nginx-rrd 监控服务(多虚拟主机)(推荐)

网址:http://www.nginx.eu/nginx-rrd.html

此解决方案其实是基于上述监控方案的一个改进和增强,同样先安装好rrdtool这个画图工具和相应的perl模块再做如下操作
   

# yum install perl-HTML*



先建立好生成的库存和图片存放录



#mkdir -p /data/www/wwwroot/nginx/{rrd,html}#cd /usr/local/sbin



#wget http://www.nginx.eu/nginx-rrd/nginx-rrd-0.1.4.tgz



#tar zxvf nginx-rrd-0.1.4.tgz



#cd nginx-rrd-0.1.4



#cd etc/



#cp nginx-rrd.conf /etc



#cd etc/cron.d



#cp nginx-rrd.cron /etc/cron.d#cd /usr/local/src/nginx-rrd-0.1.4/html



# cp index.php /data/www/wwwroot/nginx/html/#cd /usr/local/src/nginx-rrd-0.1.4/usr/sbin



#cp * /usr/sbin/
   

#vi /etc/nginx-rrd.conf



#####################################################



#



# dir where rrd databases are stored



RRD_DIR="/data/www/wwwroot/nginx/rrd";



# dir where png images are presented



WWW_DIR="/data/www/wwwroot/nginx/html";



# process nice level



NICE_LEVEL="-19";



# bin dir



BIN_DIR="/usr/sbin";



# servers to test



# server_utl;server_name



SERVERS_URL="http://219.32.205.13/nginx_status;219.32.205.13  http://www.linuxtone.org/nginx_status;www.linuxtone.org""

//根据你的具体情况做调整.

SEVERS_URL 格式 http://domain1/nginx_status;domain1 http://domain2/nginx_status;domain2

这种格式监控多虚拟主机连接状态:

重点启crond服务,仍后通过http://219.32.205.13/nginx/html/ 即可访问。配置过程很简单!

3、        CACTI模板监控Nginx

利用Nginx_status状态来画图实现CACTI监控

nginx编译时允许http_stub_status_module
   

# vi /usr/local/nginx/conf/nginx.conf



location /nginx_status {



stub_status on;



access_log off;



allow 192.168.1.37;



deny all;



}


# kill -HUP `cat /usr/local/nginx/logs/nginx.pid`



# wget http://forums.cacti.net/download.php?id=12676



# tar xvfz cacti-nginx.tar.gz



# cp cacti-nginx/get_nginx_socket_status.pl /data/cacti/scripts/



# cp cacti-nginx/get_nginx_clients_status.pl /data/cacti/scripts/



# chmod 755 /data/cacti/scripts/get_nginx*

检测插件
   

#/data/cacti/scripts/get_nginx_clients_status.pl http://192.168.1.37/nginx_status

在cacti管理面板导入

cacti_graph_template_nginx_clients_stat.xml

cacti_graph_template_nginx_sockets_stat.xml

十六、常见问题与错误处理

1、400 bad request错误的原因和解决办法

配置nginx.conf相关设置如下.

client_header_buffer_size 16k;

large_client_header_buffers 4 64k;

根据具体情况调整,一般适当调整值就可以。

2、Nginx 502 Bad Gateway错误

proxy_next_upstream error timeout invalid_header http_500 http_503;

或者尝试设置:

large_client_header_buffers 4 32k;

3、Nginx出现的413 Request Entity Too Large错误

这个错误一般在上传文件的时候会出现,

编辑Nginx主配置文件Nginx.conf,找到http{}段,添加

client_max_body_size 10m ; //设置多大根据自己的需求作调整.

如果运行php的话这个大小client_max_body_size要和php.ini中的如下值的最大值一致或者稍大,这样就不会因为提交数据大小不一致出现的错误。

post_max_size = 10M

upload_max_filesize = 2M

4、解决504 Gateway Time-out(nginx)

遇到这个问题是在升级discuz论坛的时候遇到的

一般看来, 这种情况可能是由于nginx默认的fastcgi进程响应的缓冲区太小造成的, 这将导致fastcgi进程被挂起, 如果你的fastcgi服务对这个挂起处理的不好, 那么最后就极有可能导致504 Gateway Time-out

现在的网站, 尤其某些论坛有大量的回复和很多内容的, 一个页面甚至有几百K。

默认的fastcgi进程响应的缓冲区是8K, 我们可以设置大点

在nginx.conf里, 加入: fastcgi_buffers 8 128k

这表示设置fastcgi缓冲区为8×128k

当然如果您在进行某一项即时的操作, 可能需要nginx的超时参数调大点,例如设置成60秒:send_timeout 60;

只是调整了这两个参数, 结果就是没有再显示那个超时, 可以说效果不错, 但是也可能是由于其他的原因, 目前关于nginx的资料不是很多, 很多事情都需要长期的经验累计才有结果, 期待您的发现哈!

5、如何使用Nginx Proxy

朋友一台服务器运行tomcat 为8080端口,IP:192.168.1.2:8080,另一台机器IP:192.168.1.8. 朋友想通过访问http://192.168.1.8 即可访问tomcat服务.配置如下:

在192.168.1.8的nginx.conf上配置如下:

server {



listen 80;



server_name java.linuxtone.org



location / {



proxy_pass http://192.168.1.2:8080;



include /usr/local/nginx/conf/proxy.conf;



}



}

6、如何关闭Nginx的LOG

access_log /dev/null; error_log /dev/null;

十七、相关资源下载

1.nginx配置示例及脚本下载:

# wget http://www.linuxtone.org/lemp/scripts.tar.gz #此脚本范例定期更新