NGINX Plus looks great :)
Basic
Config file
- location:
/etc/nginx
- main:
/etc/nginx/nginx.conf
- include:
/etc/nginx/conf.d/*.conf
basic config:
server {
listen 80 default_server; # port, default_server means all the traffic and ignore server_name
server_name www.example.com; # only match the request for this server_name
location / { # all traffic
root /usr/share/nginx/html; # file location
index index.html index.htm; # default file
}
}
- test config:
nginx -t
- graceful reload:
nginx -s reload
High performance
Load balance
upstream backend {
least_conn; # load balancing method
server 10.0.0.1:80 weight=1 max_fails=3 fail_timeout=3s;
server app.example.com:80 weight=2;
}
server {
location / {
listen 80;
proxy_pass backend;
health_check interval=10 passes=2 fails=3;
}
}
Load balancing methods:
- Round Robin
- Least connection
- Least time (plus)
- Generic hash
- IP hash
- Random
Traffic management
A/B testing
split_clients "${remote_addr}AAA" $variant {
20.0% "backendv2";
* "backendv1";
}
server {
...
location / {
...
proxy_pass http://api.com/$variant
}
}
Limiting connections
http {
limit_conn_zone $binary_remote_addr zone=limitbyaddr:10m;
limit_conn_status 429;
...
server {
...
limit_conn limitbyaddr 40; # limit_zone & allowed number
...
}
}
Limiting rate
http {
limit_req_zone $binary_remote_addr zone=limitbyaddr:10m rate=1r/s;
limit_req_status 429;
...
server {
...
limit_req zone=limitbyaddr burst=10 nodelay;
...
}
}
Limiting bandwidth
This limit is per connection.
location /download/ {
limit_rate_after 10m;
limit_rate 1m;
}
Massive scalable content caching
proxy_cache_path /var/nginx/cache
keys_zone=CACHE:60m
levels=1:2
inactive=3h
max_size=20g;
server {
...
proxy_cache_key "$host$request_uri $cookie_user"; # default is $scheme$proxy_host$request_uri
proxy_set_header Range $slice_range;
proxy_http_version 1.1;
proxy_cache_valid 200 206 1h;
proxy_cache_bypass $http_cache_bypass;
proxy_cache CACHE;
slice 1m; # for HTML5 video
location / {
proxy_pass http://origin:80;
}
location ~* \.(css|js)$ {
expires 1y;
add_header Cache-Control "public";
}
Authentication
HTTP basic authentication
Provide a username-password file like:
name1:password1
name2:password2:comment
Both openssl
and htpasswd
can generate passwords with the apr1
algorithm, which can be understand by Nginx.
location / {
auth_basic "Not allowed for unauthenticated users";
auth_basic_user_file conf.d/passwd;
}
Authentication subrequest
location /private/ {
auth_request /auth;
auth_request_set $auth_status $upstream_status;
}
location = /auth {
internal;
proxy_pass http://auth-server;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
Security controls
Access based on IP address
location /admin/ {
deny 10.0.0.1;
allow 10.0.0.0/20;
allow 2001:0db8::/32;
deny all;
}
Allowing cross-origin resource sharing
map $request_method $cors_method {
OPTIONS 11;
GET 1;
POST 1;
default 0;
}
server {
...
location / {
if ($cors_method ~ '1') {
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS';
add_header 'Access-Control-Allow-Origin' '*.example.com';
add_header 'Access-Control-Allow-Headers'
'DNT,
Keep-Alive,
User-Agent,
X-Requested-With,
If-Modified-Since,
Cache-Control,
Content-Type';
}
if ($cors_method = '11') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
}
Client-side encryption
http { # All directives used below are also valid in stream
server {
listen 8433 ssl;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_certificate /etc/nginx/ssl/example.pem;
ssl_certificate_key /etc/nginx/ssl/example.key;
ssl_certificate /etc/nginx/ssl/example.ecdsa.crt;
ssl_certificate_key /etc/nginx/ssl/example.ecdsa.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
}
}
Elliptic Curve Cryptography(ECC) certifications are found to be faster than the equivalent-strength RSA certifications.
Upstream Encryption
location / {
proxy_pass https://upstream.example.com;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
proxy_ssl_protocols TLSv1.2;
}
Securing a location
location /resources {
secure_link_secret mySecret;
if ($secure_link = "") { return 403; }
rewrite ^ /secured/$secure_link;
}
location /secured/ {
internal;
root /var/www;
}
Securing a location with an expire date
location /resources {
root /var/www;
secure_link $arg_md5,$arg_expires;
secure_link_md5 "$secure_link_expires$uri$remote_addr mySecret";
if ($secure_link = "") { return 403; }
if ($secure_link = 0) { return 410; }
}
HTTPS redirects
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
Redirecting to HTTPS where SSL/TLS is terminated before Nginx
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
if ($http_x_forwarded_proto = 'http') {
return 301 https://$host$request_uri;
}
}
Satisfying any number of security methods
location / {
satisfy any;
allow 192.168.1.0/24;
deny all;
auth_basic "closed site";
auth_basic_user_file conf/htpasswd;
}
HTTP/2
Basic configuration
server {
listen 443 ssl http2 default_server;
ssl_certificate server.crt;
ssl_certificate_key server.key;
# add gRPC
location /service1 {
grpc_pass grpc://backend.local:50051; # unencrypted
}
location /service2 {
grpc_pass grpcs://backend.local:50052; # encrypted
}
...
}
gRPC
server {
listen 80 http2; # unencrypted
location / {
grpc_pass grpc://backend.local:50051;
}
}
HTTP/2 server push
server {
listen 443 ssl http2 default_server;
ssl_certificate server.crt;
ssl_certificate_key server.key;
root /usr/share/nginx/html;
location = /demo.html {
http2_push /style.css;
http2_push /image1.jpg;
}
}
Sophisticated media streaming
Serving MP4 and FLV
http {
server {
...
location /videos/ { # files in this directory are in MP4 format type
mp4;
}
location ~ \.flv$ { # any files ending in .flv are in FLV format
flv;
}
}
}
Containers/Microservices
Official NGINX image
docker run --name my-nginx -p 80:80 -v /path/to/content:/usr/share/nginx/html:ro -d nginx
This maps locolhost:80
to port 80 of the container, and mounts the local directory /path/to/content
as a container volume at /usr/share/nginx/html
as read only.
Creating an NGINX Dockerfile
FROM centos:7
RUN yum -y install epel-release && \
yum -y install nginx
ADD /nginx-conf /etc/nginx
EXPOSE 80 443
CMD ['nginx']
Use environment variables in NGINX
daemon off;
env APP_NDS;
include /usr/share/nginx/modules/*.conf;
...
http {
perl_set $upstream_app 'sub { return $ENV{"APP_DNS"}; }';
server {
...
location / {
proxy_pass https://$upstream_app;
}
}
}
To use perl_set
you must have the ngx_http_perl_module
installed. (yum -y install nginx nginx-mod-http-perl
)
Advanced activity monitoring
Enable NGINX Open Source stub status
location /stub_status {
stub_status;
allow 127.0.0.1;
deny all;
}
Debuggin and troubleshooting with access logs, error logs, and request tracing
Configuring access logs and error logs
http {
log_format geoproxy
'[$time_local] $remote_addr '
'$realip_remote_addr $remote_user '
'$request_method $server_protocol '
'$schema $server_name $uri $status '
'$request_time $body_bytes_sent '
'$geoip_city_country_code3 $geoip_region '
'"$geoip_city" $http_x_forwarded_for '
'$upstream_status $upstream_response_time '
'"$http_referer" "$http_user_agent"';
...
server {
access_log /var/log/nginx/access.log geoproxy;
error_log /var/log/nginx/error.log warn;
...
}
}
Forwarding to syslog
error_log syslog:server=10.0.0.1 debug;
access_log syslog:server=10.0.0.1,tag=nginx,severity=info geoproxy;
A common log aggregation stack is ElasticSearch, Logstash, and Kibana(ELK stack).
Request tracing
Using request_id
to track request. It will generate string of 32 hex characters.
log_format trace '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$http_x_forwarded_for" $request_id';
upstream backend {
server 10.0.0.1;
}
server {
listen 80;
add_header X-Request-ID $request_id;
location / {
proxy_pass http://backend;
proxy_set_header X-Request_ID $request_id;
access_log /var/log/nginx/access_trace.log trace;
}
}
Performance tuning
Keeping connections open to clients
http {
keepalive_requests 320; # default 100
keepalive_timeout 300s; # default 75
...
}
Keeping connections open upstream
proxy_http_version 1.1;
proxy_set_header Connection "";
upstream backend {
server 10.0.0.1;
server 10.0.0.2;
keepalive 32;
}
Buffering responses
server {
proxy_buffering on;
proxy_buffer_size 8k;
proxy_buffers 8 32;
proxy_busy_buffer_size 64k;
...
}
Buffering access log
http {
access_log /var/log/nginx/access.log main buffer=32k flush=1m; # flush the log older than 1 minute
}
OS tuning
- connection number:
net.core.osmaxconn
- open file descriptors:
sys.fs.file_max
,worker_connections
,worker_rlimit_nofile
- enable more ephemeral ports:
net.ipv4.ip_local_port_range