Wilson Mar bio photo

Wilson Mar

Hello!

Calendar YouTube Github

LinkedIn

The kick-ass secure front-end web server proxy

US (English)   Norsk (Norwegian)   Español (Spanish)   Français (French)   Deutsch (German)   Italiano   Português   Estonian   اَلْعَرَبِيَّةُ (Egypt Arabic)   Napali   中文 (简体) Chinese (Simplified)   日本語 Japanese   한국어 Korean

Overview

This tutorial intends to show complete newbies how to setup and configure NGINX (pronounced “engine-x”). Step by step.

Unlike other documents, this tutorial presents responses from commands.

NGINX Market Share

“The NGINX Docker image is the number one downloaded application image on Docker Hub.”

In the October, 2016 survey from Netcraft, NGINX (the green line) is shown to be gaining market share over time while others are declining:

nginx market mil 2016-10-650x286-101kb This is for the top million sites on the internet.

What’s more, based on counts by Alexa, Datanyze and W3Tech, NGINX is more common with high-traffic sites:

nginx mkt share 459x186-63kb

Unlike Apache, which spawns a new thread for each new connection, the NGINX web server is designed to be efficient at responding to static requests. This is because it uses an “event-driven” approach for high concurrency, high performance, with small, predictable usage of memory.

Among the 88 “others” are LightTPD (pronounced “lighty”). Google’s Seesaw load balancer, a fork of Apache.

Open-source products for ADC (Application Delivery Controllers) include HAProxy, Varnish, Zen Load Balancer (from SofIntel IT Engineering SL)

Gartner’s August 2016 Magic Quadrant for Application Delivery Controllers
nginx adc market 2016 650x650-61kb.png
includes F5 which is what Gartner calls a “Mode 1”. “Mode 1” products focus on predictability and stability with what can be identified by a process of analysis vs. “Mode 2” focus on exploratory with being basic, low-cost, easy-to-acquire.

There is some skepticism about speed benchmarks vs. Microsoft’s IIS and Apache Tomcat.

Configurations

Load Balancing

The revolution of NGINX is that unlike Apache, it doesn’t just die when overwhelmed because it keeps servers from being overwhelmed. NGINX servers notify others when it can handle more traffic, and those sending traffic use a server’s health-check status as the basis for sending load to the server. This is called the “circuit breaker” design pattern.

The default configuration option for load balancing is round-robin allocation among servers specified. There is also ip_hash which persists sessions from the source IP used to calcuate a random hash.

upstream backend {
    ip_hash
    server webserver01:80;
    server webserver02:80;
}   
   

There is also “least_conn” for least connections when serving the same content.

The Plus edition provides a list of servers shared among them.

Reverse proxy

NGINX is a “reverse proxy”. A “proxy” describes someone or something acting on behalf of someone else. A forward proxy hides the identities of clients(users) whereas
a reverse proxy hides the identities of your servers.

Spammers need to use different end-points so that they can continue with alternate IPs as the IPs they use are blocked.

But it’s more than just hiding. It’s being granularity to control what servers get accessed even though traffic comes in requesting another IP.

NGINX does all this to SMTP, POP3, IMAP, as well as web HTTP/HTTPS protocols.

On startup NGINX looks for a configuration file named conf.d in folder /etc/nginx. To configure a proxy server, the Dockerfile would have:

FROM nginx:alpine
COPY proxy.conf /etc/nginx/conf.d/
   

The proxy.conf file would contain:

server{
   listen:80;
   location / {
       proxy_pass http://app;
   }
}
   

The docker-compose.yml file used to instantiate servers would contain:

---
version: '2'
services:
    app:
        build: app
    proxy:       
        build: proxy
        ports:
         - "80:80"
   

Nginx can proxy requests using http, FastCGI, uwsgi, SCGI, or memcached.

Level 7 cache

NGINX operates at “Layer 7” (of the ISO 7-layer model), meaning the load balancer examines the content of messages from applications (URLs and cookies) to reuse existing connections kept alive and route traffic directly to a specific type of server.

Because NGINX can understand what is requested, it can fulfill requests without going to application servers to generate web pages.

A/B Testing

NGINX can thus route a percentage of traffic to alternate versions of content in order to measure wether visitors respond differently. This is called A/B testing, like you do at the eye doctor.

The server URL is varied by using a $servers variable in configuration to distribute traffic:

split_clients "${remote_addr}AAA" $servers {
    95% backends;
    5% 192.168.56.1:80;
}
server {
    listen 80;
    location / {
       proxy_pass http://$servers;
  }
}
   

App Version Migrations

Alternating traffic among servers is also handy for “blue/green” deployments where a complete set of servers holds a new version. This enables easy fall-back in case the new version has a problem.

NGINX can deliver a small percentage of traffic to the new version to test the waters.

To ensure that a session returns to the same server, NGINX is configured to use the group specification in a cookie that NGINX adds to the HTTP header for clients to return:

map $cookie_group $group {
   ~(?P<value>.+)$ $value;
   default backendDB; # the default upstream group.
}
server {
    listen 80;
    location / {
       add_header Set-Cookie "group=$group; path=/"
       proxy_pass http://$group;
  }
}
   

Fabric Mesh

The Fabric mesh defined in the NGINX Microservices Reference Architecture

Wide Linux OS support

NGINX runs on a multitude of operating systems.

There are different commands for different versions of different flavors of Linux.

  • RHEL, CentOS, Oracle Linux and Amazon Linux

    • RHEL5, CentOS5 or Oracle Linux5, install OpenSSL:
    • RHEL6, RHEL7, CentOS6, CentOS7, Oracle Linux6, Oracle Linux7, and Amazon Linux install ca-certificates

  • Debian 7 (Wheezy), Debian 8 (Jessie), Ubuntu 12.04 (Precise), Ubuntu 14.04 (Trusty), Ubuntu 16.04 (Xenial), Ubuntu 16.10 (Yakkety)

    apt-get

  • SLES (SUSE Linux Enterprise Server) 12 & 12 SP1

  • FreeBSD 9.3, 10.1+ and 11.0

    ports

  • Windows (as of NGINX 0.8.50) ???

See https://cs.nginx.com/repo_setup

Let’s start with:

Install manually locally on a Mac

  1. In a Terminal shell window:

    brew install nginx

    The response (redacted):

    ==> Installing dependencies for nginx: openssl@1.1
    ==> Installing nginx dependency: openssl@1.1
    ==> Caveats
    A CA file has been bootstrapped using certificates from the system
    keychain. To add additional certificates, place .pem files in
      /usr/local/etc/openssl@1.1/certs
     
    and run
      /usr/local/opt/openssl@1.1/bin/c_rehash
     
    This formula is keg-only, which means it was not symlinked into /usr/local.
     
    Apple has deprecated use of OpenSSL in favor of its own TLS and crypto libraries
     
    Generally there are no consequences of this for you. If you build your
    own software and it requires this formula, you'll need to add to your
    build variables:
     
     LDFLAGS:  -L/usr/local/opt/openssl@1.1/lib
     CPPFLAGS: -I/usr/local/opt/openssl@1.1/include
     PKG_CONFIG_PATH: /usr/local/opt/openssl@1.1/lib/pkgconfig
     
    ==> Summary
    🍺  /usr/local/Cellar/openssl@1.1/1.1.0b: 6,222 files, 15.3M
    ==> Installing nginx
    ==> Downloading https://homebrew.bintray.com/bottles/nginx-1.10.2_1.sierra.bottl
    ######################################################################## 100.0%
    ==> Pouring nginx-1.10.2_1.sierra.bottle.tar.gz
    ==> Caveats
    Docroot is: /usr/local/var/www
     
    The default port has been set in /usr/local/etc/nginx/nginx.conf to 8080 so that
    nginx can run without sudo.
     
    nginx will load all files in /usr/local/etc/nginx/servers/.
     
    To have launchd start nginx now and restart at login:
      brew services start nginx
    Or, if you don't want/need a background service you can just run:
      nginx
    ==> Summary
    🍺  /usr/local/Cellar/nginx/1.10.2_1: 8 files, 979.5K   
    

    OpenSSL Dependency

    PROTIP: NGINX negotiates HTTPS traffic so downstream servers can use plain HTTP traffic without the encryption overhead. This is important for companies who want to keep TLS/SSL certificate handling on only one set of servers by a small set of people.

  2. Verify install of OpenSSL:

    openssl version

    The response:

    OpenSSL 1.0.2g  1 Mar 2016
    

    The previous version with the Heartbleed vulnerability was 1.0.1p (which was why it was a prime target for hackers).

    There has been a shift in security:

    For newer RHEL6, RHEL7, CentOS6, CentOS7, Oracle Linux6, Oracle Linux7, and Amazon Linux, install ca-certificates:

    sudo yum install ca-certificates

    For older RHEL5, CentOS5, or Oracle Linux5, install OpenSSL:

    sudo yum install openssl

    Bring it up

  3. Run:

    nginx

    NOTE: The program is in /usr/bin by default.

    The prompt returns because a background process was started.

    Notice it runs under the bash shell, not as a separate process.

  4. Switch to an internet browser to view:

    localhost:8080

    The response is the NGINX Welcome page:


    nginx hello 527x208-100kb


    If you see this on other sites

    The difference between free and Plus licensed offerings include load balancing, session persistence, cache, additional health checks, live streaming, support for GeoIP2, nginScript.

    Pro Trial Keys

  5. Click on “Free Trial” and get an email from evaluations@nginx.com.
  6. In your email, click the link to accept the agreement:

    https://cs.nginx.com/t/…/accept

  7. Check the “I accept” and click Submit.

    “Trial successfully activated” appears.

  8. Click “Certificate” to download the nginx-repo.crt (X.509) file.

    NOTE: “.crt” means certificate. Alt-click on the file on a Mac Keychain Access. Open the file using a text editor to see it starts with:

    -----BEGIN CERTIFICATE-----
    
  9. Click “Private Key” to download the nginx-repo.key file.

    NOTE: On a Mac, the “.key” file is also used for Keynote files. But open this file in a text editor:

    -----BEGIN PRIVATE KEY-----
    
  10. Click the green “instructions” link for a web page containing a “one-time” license key embedded within code you execute on the one server you’re setting up:

    wget https://cs.nginx.com/static/install-nginx && sudo chmod +x install-nginx
    sudo ./install-nginx 3c3acc3abea9795eda91ac3956a96c30
    

    For multiple servers, you have to email evaluations@nginx.com.

    Skip to configuration after install.

Run using Vagrant and Docker

Install Vagrant and Docker

  1. Install Vagrant for your version of Mac, Windows, Debian, Centos.

    vagrant_1.8.7.dmg

    PROTIP: Vagrant is used to set-up virtual machines by importaing pre-made images called “boxes” containing settings.

    Think of it as a scripting engine for VirtualBox, a “free, cross-platform consumer virtualization product”.

  2. Install Virtualbox.

    The default provider is VirtualBox versions 4.0, 4.1, 4.2, 4.3 only. More recent ones are 5.0.x and 5.1.x.

    Download from https://www.virtualbox.org/wiki/Downloads file VirtualBox-5.1.8-111374-OSX.dmg

    If you do not want to use VirtualBox, other providers are listed at:
    https://docs.vagrantup.com/v2/providers/

    http://www.vagrantbox.es/

    PROTIP: Vagrant is a product from hashicorp.com which also makes Atlas (the enterprise edition) to open-source Packer, Terraform, Vault, Nomad, and Consul.

    Install providers

  3. Install provider for vagrant to start VM’s.

    ???

  4. Clone demo files to your local machine:

    git clone git@github.com:nginxinc/NGINX-Demos.git
    cd NGINX-Demos
    
  5. Be at the hello folder:

    cd nginx-hello
    
  6. Download nginx-repo.crt and nginx-repo.key files from NGINX Customer Portal.

  7. Copy license certs nginx-repo.key and nginx-repo.crt files from your account to the target server:

    TARGET="~/NGINX-Demos/autoscaling-demo/ansible/files/"
    sudo cp nginx-repo.key $TARGET
    sudo cp nginx-repo.crt $TARGET
    

    NOTE: In Linux the folder is /etc/ssl/nginx.

  8. Initialize:

    vagrant init hashicorp/precise64

    The response:

    A `Vagrantfile` has been placed in this directory. You are now
    ready to `vagrant up` your first virtual environment! Please read
    the comments in the Vagrantfile as well as documentation on
    `vagrantup.com` for more information on using Vagrant.
    
  9. Bring up the VM:

    vagrant up –provider=PROVIDER

    NOTE: A single vagrant up command creates and starts up all VMs, and distributes the templates and other files to them.

    It it’s not done already, this command also creates the box from your specified base box after fetching it from its URL and download it to your machine (no downloading ISO, unzip, etc.):

    ==>  Provider 'virtualbox' not found. We'll automatically install it now...
      The installation process will start below. Human interaction may be
      required at some points. If you're uncomfortable with automatically
      installing this provider, you can safely Ctrl-C this process and install
      it manually.
    ==>  Downloading VirtualBox 5.0.10...
      This may not be the latest version of VirtualBox, but it is a version
      that is known to work well. Over time, we'll update the version that
      is installed.
    ==>  Installing VirtualBox. This will take a few minutes...
      You may be asked for your administrator password during this time.
      If you're uncomfortable entering your password here, please install
      VirtualBox manually.
    Password: _
    
  10. Type in your administrator password. Then wait for response:

    ==> VirtualBox has successfully been installed!

Run simple Hello world

Have NGINX run a webserver in a Docker container to serve a simple index.html page containing the container’s hostname, IP address, and port.

  1. First, setup Docker according to my instructions. sudo systemctl status docker.service

  2. Run the “hello” image stored by user nginxdemos in Docker Hub:

    docker run -P -d nginxdemos/hello

    If it has not been loaded yet, you’ll see something like:

    Unable to find image 'nginxdemos/hello:latest' locally
    latest: Pulling from nginxdemos/hello
    3690ec4760f9: Pull complete 
    e13b170882f4: Downloading 5.176 MB/14.47 MB
    6a5d3c1484a0: Download complete 
    

    After download completes, you should see:

    Digest: sha256:d2ea7dfdd199e04bea10ca6a807f822b242552ff5306871cc588382fe396c45d
    Status: Downloaded newer image for nginxdemos/hello:latest
    2289fc019878fd78031ae83e55c1187ef5678331e3ebe2708a4d42b400ec780e
    
  3. In an internet browser, get to:

    http://127.0.0.1:8080
    

    The NGINX Welcome screen should appear.

  4. Use a text editor to see the Docker file https://github.com/nginxinc/NGINX-Demos/tree/master/nginx-hello nginx-hello</a>

    FROM nginx:mainline-alpine
    RUN rm /etc/nginx/conf.d/*
    ADD hello.conf /etc/nginx/conf.d/
    ADD index.html /usr/share/nginx/html/
    
  5. The NGINX conf file

    server {
     listen 80;
     
     root /usr/share/nginx/html;
     try_files /index.html =404;
     
     expires -1;
     
     sub_filter_once off;
     sub_filter 'server_hostname' '$hostname';
     sub_filter 'server_address' '$server_addr:$server_port';
     sub_filter 'server_url' '$request_uri';
     sub_filter 'remote_addr' '$remote_addr:$remote_port';
     sub_filter 'server_date' '$time_local';
     sub_filter 'client_browser' '$http_user_agent';
     sub_filter 'request_id' '$request_id';
    }
    

    NGINX Plus exposes configuration settings with a GUI, much like what F5 does with their dashboard.

Edit NGINX Configuration

  1. Verify if configuration is ok (without killing the running instance), and print info, warnings, and error messages.

    nginx -t

    The response if good:

    nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
    


    PROTIP: This command displays the location of the conf (configuration) file.

  2. Highlight the path and copy it for use in commands to edit the conf file.

    /usr/local/etc/nginx/nginx.conf

  3. Use a text editor to edit the configuration file:

    atom /usr/local/etc/nginx/nginx.conf

    #user  nobody;
    worker_processes  1;
    #error_log  logs/error.log;
    #error_log  logs/error.log  notice;
    #error_log  logs/error.log  info;
    #pid        logs/nginx.pid;
    events {
     worker_connections  1024;
    }
    http {
     include       mime.types;
     default_type  application/octet-stream;
     #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
     #                  '$status $body_bytes_sent "$http_referer" '
     #                  '"$http_user_agent" "$http_x_forwarded_for"';
     #access_log  logs/access.log  main;
     sendfile        on;
     #tcp_nopush     on;
     #keepalive_timeout  0;
     keepalive_timeout  65;
     #gzip  on;
     server {
         listen       8080;
         server_name  localhost;
    
         #charset koi8-r;
    
         #access_log  logs/host.access.log  main;
    
         location / {
             root   html;
             index  index.html index.htm;
         }
         #error_page  404              /404.html;
         # redirect server error pages to the static page /50x.html
         #
         error_page   500 502 503 504  /50x.html;
         location = /50x.html {
             root   html;
         }
         # proxy the PHP scripts to Apache listening on 127.0.0.1:80
         #
         #location ~ \.php$ {
         #    proxy_pass   http://127.0.0.1;
         #}
         # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
         #
         #location ~ \.php$ {
         #    root           html;
         #    fastcgi_pass   127.0.0.1:9000;
         #    fastcgi_index  index.php;
         #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
         #    include        fastcgi_params;
         #}
         # deny access to .htaccess files, if Apache's document root
         # concurs with nginx's one
         #
         #location ~ /\.ht {
         #    deny  all;
         #}
     }
     # another virtual host using mix of IP-, name-, and port-based configuration
     #
     #server {
     #    listen       8000;
     #    listen       somename:8080;
     #    server_name  somename  alias  another.alias;
     #    location / {
     #        root   html;
     #        index  index.html index.htm;
     #    }
     #}
     # HTTPS server
     #
     #server {
     #    listen       443 ssl;
     #    server_name  localhost;
     #    ssl_certificate      cert.pem;
     #    ssl_certificate_key  cert.key;
     #    ssl_session_cache    shared:SSL:1m;
     #    ssl_session_timeout  5m;
     #    ssl_ciphers  HIGH:!aNULL:!MD5;
     #    ssl_prefer_server_ciphers  on;
     #    location / {
     #        root   html;
     #        index  index.html index.htm;
     #    }
     #}
     include servers/*;
    }
    

    Changes

    Reload Configuration

  4. After editing config, do a hot reload without downtime: disconnecting users:

    service nginx reload

    or

    /etc/init.d/nginx reload

    These send a SIGHUP signal to the nginx master process.

    See http://nginx.org/en/docs/control.html

nginScript

Embed snippets of JavaScript in NGINX configuration, to dynamically control the internal operation of NGINX precisely for each request.

This is a new Pro feature.

See https://www.nginx.com/resources/wiki/nginScript/

Stop and Restart

https://www.nginx.com/resources/wiki/start/topics/tutorials/commandline/

nginx -s reload

Install on Linux

This is for reals with real servers.



  1. In a shell:

    sudo apt-get update
    sudo apt-get install nginx

    Configure HTTPS

  2. Create a directory to hold SSL/TLS keys:

    
    sudo mkdir /etc/ssl/nginx
    cd /etc/ssl/nginx
    
  3. Ansible

    https://github.com/nginxinc/NGINX-Demos/tree/master/ansible

  4. View the process ID of the master process written to the file:

    cat /usr/local/nginx/logs/nginx.pid

Examine config

  1. List the files installed (from path output during Mac installation above):

    ls /usr/local/etc/nginx/servers/

    The response:

    conf.d          mime.types        proxy_params    uwsgi_params
    fastcgi_params  naxsi_core.rules  scgi_params     win-utf
    koi-utf         naxsi.rules       sites-available
    koi-win         nginx.conf        sites-enabled
    

    On Linux:

    cd /etc/nginx/
    

    Examine config

  2. How mancy cores does your machine have?

    The cross-platform approach:

       
    python -c 'import multiprocessing as mp; print(mp.cpu_count())'
    

    On a Mac, use a utility from Apple:

    sysctl -n hw.ncpu
    sysctl hw.physicalcpu

    The response is 8 logical cores from 2 physical cores from system_profiler SPHardwareDataType .

    On Linux:

    grep ^processor /proc/cpuinfo | wc -l

Configuration

  1. Examine the default configuration file (substituting vim with atom or whatever text editor you prefer):

    vim nginx.conf

    Directives are defined in
    http://nginx.org/en/docs/http/ngx_http_core_module.html

    Processes

    For worker_processes specify one for each core on the machine being used. The default is a 4-core server.

    Each worker can handle thousands of concurrent connections asynchronously in a single thread.

    Connections

    The worker_connections default of 768 needs to be adjusted based on what a server can handle based on the set of applications running on it.

    Since separate connections are used for incoming and outgoing, each end-user browser uses at least two connections.

  2. Check your machine’s connection limit:

    ulimit -n

    On my Mac, it’s 256.

    On a small Linux droplet (512 MB), it may be 1024.

    Have a script do this upon start-up.

    Keepalive

    The keepalive_timeout default of 65 also needs to be adjusted based on the remoteness of users from servers. For example, if the majority of users are in South Africa are accessing a server in Menlo Park, then you’ll likely need a longer one.

    Buffer sizes

    If you encounter a HTTP 413 “Rquest Entity Too Large” error, adjust these:

    client_body_buffer_size 10K; defines the max POST actions received (typically HTML FORMs).

    client_max_body_size 8m;

    client_header_buffer_size 1K; usually need to be increased if the header contains a lot of info. 64K is a good size.

    The companion is to up to 4 64K large_client_header_buffers 2 1K;

    Gzip

    If gzip_comp_level is too high, the server wastes CPU cycles.

    location /api {
      expires 10m;
    }
    

    Chef replace

    Chef knows to look in the file and replaces values from a file such as this:

    node.set[’nginx’][‘worker_connections’] = 8192
    node.set[’nginx’][‘worker_rlimit_nofile’] = 32768
    node.set[’nginx’][‘event’] = ‘epoll'
    node.set[’nginx’][‘client_max_body_size’] = ‘4m'
    

sites-enabled defaults

  1. Define a defaults file within site-enabled folder:

    cd sites-enabled
    sudo vim defaults

    Define nodes (backend), all listening on port 80:

    upstream backend {
      server 22.22.22.2:3000;
    #  server 22.22.22.3:3000;
    # server 22.22.22.4:3000;
    }
    server {
    listen 80;
     
    location / {
      proxy_pass https://backend;
    }
     
      # Cache static assets 7 days (168/24):
      location ~* \.(ico|gif|jpe?g|png|mp4|mp3|svg|css|js)$ {
     exprires 168h;
      }
    }
    

    The http://backend forward incoming requests among ip addresses defined under backend (app container). This load balances.

    NOTE: HTTP 304 is issued for requests proxied.

    Reconfig

    On-the-fly reconfiguration (provided by the Plus edition) by a URL such as:

curl 'http://host/upstream_conf?upstram=backend&id=3&down=1'

### With Docker:

Use a resolver server:

server {
   listen 80;
 
   resolver 127.0.0.11 valid=5s;
   set $upstream http://project;
   location / {
     proxy_pass $upstream;
   }
 
  # Cache static assets 7 days (168/24):
  location ~* \.(ico|gif|jpe?g|png|mp4|mp3|svg|css|js)$ {
    exprires 168h;
  }
}
   

Remember for 5 seconds.

### Which ports are listening?

lsof -nP +c 15 | grep LISTEN

The response is long lines. So drag your Terminal window wider to remove word-wrap.

Multiple upstreams & rewrite rules

Load Balancing a Dynamic Infrastructure with NGINX, Chef, and Consul by Kevin Reedy (of Belly) presented this at ngix.conf 2014:

Using Chef’s templating:

upstream api {
  least_conn;
  <$ @servers.each do |server\ %>
  server <%= server['ipaddress %>:8080;
  <% end %>
}
upstream homepage {
  least_conn;
  server 10.0.0.201:8080;
  server 10.0.0.202:8080;
}
server {
  listen: 80;
  server_name api.bellycard.com;
  location / {
    proxy_pass http://api;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_add;
    proxy_set_header X-Forwarded-Proto https;
  }
}
server {
  listen: 80;
  server_name www.bellycard.com;
  location / {
    proxy_pass http://homepage;
  }
  location /api {
    proxy_pass http://api;
  }
}
   

### SSL/TLS

See https://bjornjohansen.no/letsencrypt-nginx

# Usign a certificate created for multiple domains:
 
   # Certificate chain: 
   ssl_certificate /usr/local/etc/openssl@1.1/certs/signed_cert_plus_intermediates.crt;
 
   # Private key:
   ssl_certificate_key /path/to/private.key;
 
   # 50 megabyte Session caching for faster connections from existing clients:
   ssl_session_timeout 1d;
   ssl_session_cache shared:SSL:50m;
 
   ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
   ssl_ciphers EECHD+CHACHA20:EECDH+AES128:RSA+AES128:EECD+AES256:RSA+AES256:EECD+3DES:RSA+3DES:!MD5;
   ssl_prefer_server_ciphers on;
 
   # HSTS (Hypertext Strick Transport Security) to always reach using HTTPS 
   # which prevents hijacking of HTTP for 6 months:
   # (requires ngx_http_headers_module)
   # add_header Strict-Transport-Security max-age=15768000;
 
   # Session tickets for Chrome & Firefox users:
   # Generate a random 48-byte file.
 
   # Fetch OCSP (Online Certificate Status Protocol) records from 
   # URL in ssl_certs and to pre-fetch OSCP response, to save a round trip
   # (30A% faster) by providing file from CA:
   ssl_stapling on;
   ssl_stapling_verify on;
   ssl_trusted_certificate /usr/local/etc/openssl@1.1/certs/root_CA_cert_plus_intermediates.crt;
 
server {
   listen 443 ssl;
   server_name   www.example.com;
...
}
server {
   listen 443 ssl;
   server_name   www.example.org;
}
...
   

### Back-end encryption #

http {
  server {
    proxy_ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

    proxy_ssl_ciphers EECHD+CHACHA20:EECDH+AES128:RSA+AES128:EECD+AES256:RSA+AES256:EECD+3DES:RSA+3DES:!MD5;

    # Internal or public: On Ubuntu:
    proxy_ssl_trusted_certificate /etc/ssl/certs/trusted_ca_cert.crt;

    proxy_ssl_verify on;
    proxy_ssl_verify_depth 2;
    proxy_ssl_session_reuse on;
...
   

Start service

  1. Define a defaults file within site-enabled folder:

    sudo service nginx start

    Stress test

  2. Use Apache bench to run 1000 requests 40 concurrent (at a time):

    ab -c 40 -n 1000 http://22.22.22.4/

    1000 / 40 = 25 / .5 seconds = 5 seconds to complete benchmark run.

    Add servers

  3. PROTIP: When more are needed, edit the file and reload.

    sudo service nginx reload

Docker

https://www.youtube.com/watch?v=HJ9bECmuwKo July 2016 by Quentin Stafford-Fraser uses a dockerfile:

   FROM nginx:alpine
   COPY index.html /usr/share/nginx/html
   

The docker-compose.yml file:

version: '2'
services:
  app:
    build: app
  proxy:
    build: proxy
    ports:
    - "80:80"
   

Version 2 means Docker uses its DNS server so a link is not needed here.

The build is to the proxy directory.

“80:80” binds from local host to port on proxy.

  1. Build

    docker-compose build

  2. Up

    docker-compose up

  3. Verify

    docker ps

  4. View in proxy:

    docker-compose exec proxy sh

    List IPs addressed by proxy:

    nslookup app

  5. Scale

    docker-compose scale -h

    To fire up 4 instances of app services and 2 workers:

    docker-compose scale app=4 worker=2

Interconnecting containers at scale with NGINX by Sarah Novotny, Technical Evangelist, NGINX

  1. To create traffic on a command line:

    curl -k -i https://localhost:8081

Verify security

When deployed to a public site:

https://ssllabs.com

See https://blog.qualys.com/ssllabs/2013/06/25/ssl-labs-deploying-forward-secrecy

Videos

On the NGINX YouTube channel:

Others:


Websites by NGINX