All notes
Nginx

Walk through

Command line


# -t: Test.
# -c: Config.
nginx -t -c pathology.conf

# Check the config first:
/etc/init.d/nginx configtest
# Then restart:
nginx restart
# Start
nginx

nginx -s reload
# -s signal      Send signal to the master process.
# 	stop    SIGTERM - fast shutdown
# 	quit    SIGQUIT - graceful shutdown
# 	reopen  SIGUSR1 - reopening the log files
# 	reload  SIGHUP - reloading the configuration file

# 1628 is the main process ID.
kill -s QUIT 1628

Master and worker processes

nginx has one master process and several worker processes. The main purpose of the master process is to read and evaluate configuration, and maintain worker processes.

The process ID of the nginx master process is written, by default, to the nginx.pid in the directory /usr/local/nginx/logs or /var/run.

Once the master process receives the signal to reload configuration, it checks the syntax validity of the new configuration file and tries to apply the configuration provided in it.

Old worker processes, receiving a command to shut down, stop accepting new connections and continue to service current requests until all such requests are serviced. After that, the old worker processes exit.

Configuration

nginx consists of modules which are controlled by directives specified in the configuration file.

Directives are divided into:

Directives placed in the configuration file outside of any contexts are considered to be in the main context.

The events and http directives reside in the main context, server in http, and location in server.


# Main context

events {
}

http {
  server {
    location {
    }
  }
}

The rest of a line after the # sign is considered a comment.

Example configuration


location /some/path/ {
    proxy_pass http://www.example.com/link/;
}

location / {
    root /var/www/html;
    index index.php;
}
location ~ \.php {
    proxy_pass http://127.0.0.1:8000;
}

location /share/ {
    alias html/share/;
    autoindex on;
}

HTTP server

How nginx processes a request

nginxDoc.

Name-based virtual servers


# "server_name" could point to multiple names.
server {
    listen      80;
    server_name example.org www.example.org;
}

# This is the default server.
server {
    listen      80 default_server;
    server_name example.net www.example.net;
}

server {
    listen      80;
    server_name example.com www.example.com;
}
  1. nginx first tests the IP address and port of the request against the listen directives of the server blocks.
  2. Then tests only the request's header field "Host" to determine which server the request should be routed to.
  3. If its value does not match any server name, or the request does not contain this header field at all, then nginx will route the request to the default server for this port, set by "default_server".
  4. If no "default_server" is set, the default server is the first one.

A default server is a property of the listen port, and different default servers may be defined for different ports:


server {
    listen      192.168.1.1:80 default_server;
    server_name example.net www.example.net;
    ...
}

server {
    listen      192.168.1.2:80 default_server;
    server_name example.com www.example.com;
    ...
}

Prevent processing requests with undefined server names


server {
    listen      80;

    # Since version 0.8.48, this is the default setting, so can be omitted.
    # In earlier versions, the machine's hostname was used as a default server name.
    server_name "";

    # 444 is a special nginx's non-standard code
    return      444;
}

server {
    listen      80;
    server_name example.org www.example.org;

    # Path to local file system.
    root        /data/www;

    location / {
        index   index.html index.php;
    }

    # case-insensitive regexp
    location ~* \.(gif|jpg|png)$ {
        expires 30d;
    }

    # case-sensitive regexp
    location ~ \.php$ {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME
                      $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}

Server names

Using nginx as HTTP load balancer

Configuring HTTPS servers

FAQ

ngix.conf 配置

Disable cache

When you Ctrl+Shift+R in Firefox but still receive old JS or CSS files, it may be because Nginx is caching them.

SO: clear the cache of nginx suggests to turn off the "sendfile" option to clear the cache.

What is the different usages for sites-available vs the conf.d directory for nginx

StackOverflow.

The sites-* folders are managed by nginx_ensite and nginx_dissite. For httpd users who find this with a search, the equivalents is a2ensite/a2dissite.

The sites-available folder is for storing all of your vhost configurations, whether or not they're currently enabled.
The sites-enabled folder contains symlinks to files in the sites-available folder. This allows you to selectively disable vhosts by removing the symlink.

conf.d does the job, but you have to move something out of the folder, delete it, or make changes to it when you need to disable something.

Basics

Reverse proxy

ServerFault.


# Set up nginx to listen on 80, and proxy all queries on "/" to port 5010.
server {
	listen       80;
	# Set sever_name only for virtual host.
	# If "I don't want to put a name on this", use "server_name _;" or just comment it.
	server_name  YOUR_HOSTNAME;
	location / {
		proxy_pass         http://127.0.0.1:5010/;
		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       10m;
		client_body_buffer_size    128k;
		
		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;
	}

	location /certs {
		alias /etc/wcf/certs/;
	}
	# Suppress error log caused by missing favicon.ico.
	location = /favicon.ico {
		log_not_found off;
	}
}

Nginx.

Buffers


# The default number of buffers is increased and the size of the buffer for the first portion of the response is made smaller than the default.
location /some/path/ {
	proxy_buffers 16 4k;
	proxy_buffer_size 2k;
	proxy_pass http://localhost:8000;
}

# For fast interactive clients, disable buffering:
location /some/path/ {
	proxy_buffering off;
	proxy_pass http://localhost:8000;
}

Variables

nginx http proxying, load balancing, buffering and caching.

Log

NginxDoc. "log_format" must be in "http" context. "$http_authorization" will output the http header authorization to access.log. You can log request headers "$http_<header>" too and sent headers with "$sent_http_<header>", see this stackoverflow.


http {
	include		  /etc/nginx/mime.types;

	log_format	main  '$http_authorization $remote_addr - $remote_user [$time_local] "$request" '
					  '$status $body_bytes_sent "$http_referer" '
					  '"$http_user_agent" "$http_x_forwarded_for"';
	...
}

Configure HTTPS

NginxDoc.

The "ssl" parameter must be enabled on listening sockets, and certificates must be provided.


# Enable multi-processing:
worker_processes auto;

# For optimization. See below: h3 - optimization.
http {
	# Default 1Mb cache contains about 4000 sessions. Here use 10Mb shared cache:
	ssl_session_cache	shared:SSL:10m;
	# The default cache timeout is 5:
	ssl_session_timeout 10m;
}

server {
	# HTTP/HTTPS at the same time.
	listen				80;
	listen				443 ssl;
	server_name			www.example.com;
	# This is also important for optimization:
	keepalive_timeout	70;

	ssl_certificate		www.example.com.crt;
	ssl_certificate_key www.example.com.key;
	ssl_protocols		TLSv1 TLSv1.1 TLSv1.2;
	ssl_ciphers			HIGH:!aNULL:!MD5;
}

cp ca.crt /etc/pki/tls/certs
cp ca.key /etc/pki/tls/private/ca.key
cp ca.csr /etc/pki/tls/private/ca.csr

Security enhancement

Raymii.


# Disable SSLv2 and SSLv3
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

# If your version of OpenSSL is old, unavailable ciphers will be discarded automatically. Always use the full ciphersuite above and let OpenSSL pick the ones it supports.
# The ordering of a ciphersuite is very important.
# The recommended cipher suite:
ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

# The recommended cipher suite for backwards compatibility (IE6/WinXP):
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:ECDHE-RSA-AES128-GCM-SHA256:AES256+EECDH:DHE-RSA-AES128-GCM-SHA256:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";

Optimization

The most CPU-intensive operation is the SSL handshake. Two ways to minimize its effect:

The authority provides a bundle of chained certificates which should be concatenated to the signed server certificate. The server certificate must appear before the chained certificates in the combined file:


# The resulting file should be used in the ssl_certificate directive:
cat www.example.com.crt bundle.crt > www.example.com.chained.crt

To ensure the server sends the complete certificate chain:


openssl s_client -connect www.godaddy.com:443
# Certificate chain
# 0 s:/C=US/ST=Arizona/L=Scottsdale/1.3.6.1.4.1.311.60.2.1.3=US
#     /1.3.6.1.4.1.311.60.2.1.2=AZ/O=GoDaddy.com, Inc
#     /OU=MIS Department/CN=www.GoDaddy.com
#     /serialNumber=0796928-7/2.5.4.15=V1.0, Clause 5.(b)
#   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
#     /OU=http://certificates.godaddy.com/repository
#     /CN=Go Daddy Secure Certification Authority
#     /serialNumber=07969287
# 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
#     /OU=http://certificates.godaddy.com/repository
#     /CN=Go Daddy Secure Certification Authority
#     /serialNumber=07969287
#   i:/C=US/O=The Go Daddy Group, Inc.
#     /OU=Go Daddy Class 2 Certification Authority
# 2 s:/C=US/O=The Go Daddy Group, Inc.
#     /OU=Go Daddy Class 2 Certification Authority
#   i:/L=ValiCert Validation Network/O=ValiCert, Inc.
#     /OU=ValiCert Class 2 Policy Validation Authority
#     /CN=http://www.valicert.com//[email protected]

# Chains:
# In this example the subject (s) of the www.GoDaddy.com server certificate #0 is signed by an issuer (i)
# The issuer itself is the subject of the certificate #1, which is signed by an issuer which itself is the subject of the certificate #2, which signed by the well-known issuer ValiCert, Inc. whose certificate is stored in the browsers' built-in certificate base.

An SSL certificate with several names

The SSL connection is established before the browser sends an HTTP request and nginx does not know the name of the requested server. Therefore, it may only offer the default server’s certificate.

Solution 1:
A certificate contains exact and wildcard names in the SubjectAltName field, for example, example.org and *.example.org.
It is better to place a certificate file with several names and its private key file at the http level of configuration:


ssl_certificate     common.crt;
ssl_certificate_key common.key;

server {
	listen			443 ssl;
	server_name		www.example.com;
}

server {
	listen			443 ssl;
	server_name		www.example.org;
}

Solution 2:
A more generic solution for running several HTTPS servers on a single IP address is TLS Server Name Indication extension (SNI, RFC 6066), 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.

uwsgi

Nginx中,用uwsgi代替mod_wsgi:


location / {
  include uwsgi_params
  uwsgi_pass 127.0.0.1:9090
}

把所有url传给9090端口的uwsgi协议程序来互动。

为uwsgi配置多个站点

为了让多个站点共享一个uwsgi服务,必须把uwsgi运行成虚拟站点:去掉“-w myapp”加上”–vhost”:

uwsgi -s :9090 -M -p 4 -t 30 --limit-as 128 -R 10000 -d uwsgi.log --vhost

然后必须配置virtualenv,virtualenv是Python的一个很有用的虚拟环境工具,这样安装:

apt-get install Python-setuptools
easy_install virtualenv

然后设置一个/多个app基准环境:

virtualenv /var/www/myenv

应用环境,在此环境下安装的软件仅在此环境下有效:

source /var/www/myenv/bin/activate  
pip install django  
pip install mako  

最后配置nginx,注意每个站点必须单独占用一个server,同一server不同location定向到不同的应用不知为何总是失败,估计也算是一个bug。

server {
	listen       80;
	server_name  app1.mydomain.com;
	location / {
		include uwsgi_params;
		uwsgi_pass 127.0.0.1:9090;
		uwsgi_param UWSGI_PYHOME /var/www/myenv;
		uwsgi_param UWSGI_SCRIPT myapp1;
		uwsgi_param UWSGI_CHDIR /var/www/myappdir1;
	}
}

server {
	listen       80;
	server_name  app2.mydomain.com;
	location / {
		include uwsgi_params;
		uwsgi_pass 127.0.0.1:9090;
		uwsgi_param UWSGI_PYHOME /var/www/myenv;
		uwsgi_param UWSGI_SCRIPT myapp2;
		uwsgi_param UWSGI_CHDIR /var/www/myappdir2;
	}
}
这样,重启nginx服务,两个站点就可以共用一个uwsgi服务了。

监控uwsgi运行状态

uwsgi自带了基于django的监控uwsgi运行状态的工具,就拿它来部署好了:


server {
	listen 80;
	root   /var/www/django1.23;
	index  index.html index.htm;
	server_name uwsgiadmin.django.obmem.info;
	access_log	/var/log/nginx/django.access.log;
	location /media/ {
		root /var/www/django1.23/adminmedia;
		rewrite ^/media/(.*)$ /$1 break;
	}
	location / {
		include uwsgi_params;
		uwsgi_pass 127.0.0.1:9090;
		uwsgi_param UWSGI_PYHOME /var/www/django1.23/vtenv;
		uwsgi_param UWSGI_CHDIR /var/www/django1.23/uwsgiadmin;
		uwsgi_param UWSGI_SCRIPT uwsgiadmin_wsgi;
	}
}

于是uwsgi的监控信息可以在 http://uwsgiadmin.django.obmem.info看到,用户名密码都是admin。

Directives

alias

SO: nginx alias/location.

Both the alias and root directives are best used with absolute paths. You can use relative paths, but they are relative to the prefix config option used to compile nginx.

You can see this by executing nginx -V and finding the value following --prefix=.

nginx.org: alias.

Syntax: 	alias path;
Default: 	—
Context: 	location

The path value can contain variables, except $document_root and $realpath_root.

If alias is used inside a location defined with a regular expression:


location ~ ^/users/(.+\.(?:gif|jpe?g|png))$ {
    alias /data/w3/images/$1;
}

However in this case, it is better to use the root directive instead:


location /images/ {
    root /data/w3;
}

proxy_pass

nginxOrg: proxy_pass.

How request URI is passed to the server

wcf Question: how to make Nginx to remove prefix when doing reverse proxy? The anwser is: add trailing "/"! See explanation below.

nginx.org: http proxy module - proxy_pass. A request URI is passed to the server as follows:


# Specified with a URI:
location /name/ {
    proxy_pass http://127.0.0.1/remote/;
}

# Even adding one trailing '/' makes it a URI:
location /name2/ {
    proxy_pass http://127.0.0.1:3000/;
}
### In previous cases, "/name/" and "/name2/" will both be replaced from request.

# Specified without a URI:
location /some/path/ {
    proxy_pass http://127.0.0.1;
}
### In this case, "/some/path/" will not be removed from request.

wcfNote: the Nginx adopts the format "schema://$host$uri;". So "http://127.0.0.1:3000" is only a "host" while in "http://127.0.0.1:3000/" the trailing "/" alone is the "uri" part. You can simply skip the following subsection, which help little in undertanding previous knowledge.

URL, URN and URI

A generic URI is of the form:
 scheme:[//[user:[email protected]]host[:port]][/]path[?query][#fragment]
or simply
 [scheme:][//authority][path][?query][#fragment]

  abc://username:[email protected]:123/path/data?key=value&key2=value2#fragid1
  └┬┘   └───────┬───────┘ └────┬────┘ └┬┘           └─────────┬─────────┘ └──┬──┘
scheme  user information     host     port                  query         fragment

  urn:example:mammal:monotreme:echidna
  └┬┘ └──────────────┬───────────────┘
scheme              path
Examples of absolute URIs

    https://example.org/absolute/URI/with/absolute/path/to/resource.txt
    ftp://example.org/resource.txt
    urn:ISSN:1535–3613

Examples of URI references

    https://example.org/absolute/URI/with/absolute/path/to/resource.txt
    //example.org/scheme-relative/URI/with/absolute/path/to/resource.txt
    /relative/URI/with/absolute/path/to/resource.txt
    relative/path/to/resource.txt
    ../../../resource.txt
    ./resource.txt#frag01
    resource.txt
    #frag01

gzip

NginxConfig.

Syntax: 	gzip on | off;
Default: 	gzip off;
Context: 	http, server, location, if in location


gzip on;
# Sets the minimum length of a response that will be gzipped:
gzip_min_length 1k;
# gzip_buffers number size:
gzip_buffers 16 64k;
# Sets the minimum HTTP version of a request required to compress a response:
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_types text/plain application/x-javascript text/css application/xml;
# Enables or disables inserting the “Vary: Accept-Encoding” response header field:
gzip_vary on;

Location

The default root for nginx on Linux is: /usr/share/nginx/html/.


location / {
	index index.php;
}

# Turn on directory indexing:
location  /  {
	autoindex  on;
}

NginxDocs.


# In response to the http://localhost/images/example.png request nginx will send the /data/images/example.png file. Requests with URIs not starting with /images/ will be mapped onto the /data/www directory.
server {
	location / {
		root /data/www;
	}

	location /images/ {
		root /data;
	}
}

LowEndTalk.


# Disallow the display of the original jpg files and allowing access to the rest:
location /pictures {
	location ~ \.jpg$ {
	deny all;
	}
}

Precedence

StackOverflow: nginx location priority.
HttpCoreModule.

Algorithm.

location optional_modifier location_match {
	. . .
}
  1. Directives with the "=" prefix that match the query exactly. If found, searching stops.
  2. All remaining directives with conventional strings. If this match used the "^~" prefix, searching stops.
  3. Regular expressions, in the order they are defined in the configuration file.
  4. If #3 yielded a match, that result is used. Otherwise, the match from #2 is used.

location  = / {
  # matches the query / only.
  [ configuration A ] 
}
location  / {
  # matches any query, since all queries begin with /, but regular
  # expressions and any longer conventional blocks will be
  # matched first.
  [ configuration B ] 
}
location /documents/ {
  # matches any query beginning with /documents/ and continues searching,
  # so regular expressions will be checked. This will be matched only if
  # regular expressions don't find a match.
  [ configuration C ] 
}
location ^~ /images/ {
  # matches any query beginning with /images/ and halts searching,
  # so regular expressions will not be checked.
  [ configuration D ] 
}
location ~* \.(gif|jpg|jpeg)$ {
  # matches any request ending in gif, jpg, or jpeg. However, all
  # requests to the /images/ directory will be handled by
  # Configuration D.   
  [ configuration E ] 
}

user

Syntax: user user [group];
Default: user nobody nobody;
Context: 	main

Defines user and group credentials used by worker processes. If group is omitted, a group whose name equals that of user is used.

charset

NginxDoc.


# Choose one below:
charset utf-8;
charset off;

upstream

NginxDocs. Defines a group of servers. Servers can listen on different ports. In addition, servers listening on TCP and UNIX-domain sockets can be mixed.


upstream backend {
	server backend1.example.com weight=5;
	server 127.0.0.1:8080		max_fails=3 fail_timeout=30s;
	server unix:/tmp/backend3;
	server backup1.example.com	backup;
}

By default, requests are distributed between the servers using a weighted round-robin balancing method.