It is quite common in AWS to locate nginx Web servers running on EC2 instances behind ELB. There’re some tips to enhance nginx performance.

Core

Worker Process

Number of process(es) for worker(s). This value should be equal to the number of cores of CPU. Setting auto will automatically set it that way. You don’t have to change this number even if you change the instance type of ELB.

Config

worker_processes  auto;

Directive

Syntax:	worker_processes number | auto;
Default:	worker_processes 1;
Context:	main

See ngx_core_module: worker_processes

Connection settigns

keepalive_timeout

This is a parameter that defines timeout for keep-alive connections. Nginx will close connections after this time.

For ngixn behind ELB, this value must be higher than ELB’s Idle timeout. Otherwise it end up with increasing in ELB 408 errors.

Directive

Syntax:	keepalive_timeout timeout [header_timeout];
Default:	keepalive_timeout 75s;
Context:	http, server, location

See ngx_http_core_module: keepalive_timeout

Example

keepalive_timeout  75;

Assuming that ELB’s Idle timeout is default 60 seconds.

Get Client IP address instead of ELB’s

By default just putting nginx under ELB will make a client IP address, which is used (like for logging), ELB’s one not real client one. Adding those lines below, you can get a real client IP address. This is based on ELB’s X-Forwarded-For header.

Assume that your VPC CIDR Block is 10.0.0.0/16.

Config

set_real_ip_from   10.0.0.0/16; # VPC CIDR
real_ip_header     X-Forwarded-For

Directive

Syntax:	**set_real_ip_from** address | CIDR | unix:;
Default:	—
Context:	http, server, location

See ngx_http_realip_module

Terminate SSL/TLS at ELB

You can terminate https at ELB, and process the request to Web servers with http, for performance ehnahcement, easier maintenance of SSL/TLS Certificates files.

SSL Termination at ELB
- https -> [ ELB :443 ] - http -> [nginx :80]
SSL Termination at Nginx
- https -> [ ELB :443 ] - https -> [nginx :443]

Redirect http to https

Sometimes you need to redirect all the http requests to https, or visa versa. By terminating SSL at ELB, Web server only need to listen http 80 port. Still you can detect protocol based on ELB’s header $http_x_forwarded_proto.

Config (Example)

server {
  listen 80;

  ...
  
  if ($http_x_forwarded_proto != "https") {
    return 301 https://$host$request_uri;
  }
  
  ...

}

Tell backend server for reverse proxy the protocol

One more thing, you can tell backend application the protocol.

Config

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;

Directive

Syntax:	proxy_set_header field value;
Default:	
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
Context:	http, server, location

See ngx_http_proxy_module: proxy_set_header

Etc

Change DNS Server

Sometimes need to change name server for looking up DNS, it rarely happens though.

Config

resolver 10.0.0.2;

Directive

Syntax:	resolver address ... [valid=time] [ipv6=on|off];
Default:	—
Context:	http, server, location

See ngx_http_core_module: resolver

Conclusion

Most of the configuration for nginx benihd ELB is not diffrent from the one facing the Internet directly. Configuring a little bit for ELB will ehnance performance and availability of nginx.