Skip to main content

Part 1: How to Configure Nginx as a Web/HTTP/HTTPS Load Balancer on Ubuntu 18.04 LTS ?

Load balancing across multiple application instances is a commonly used technique for optimizing resource utilization, maximizing throughput, reducing latency, and ensuring fault-tolerant configurations. 

It is possible to use nginx as a very efficient HTTP load balancer to distribute traffic to several application servers and to improve performance, scalability and reliability of web applications with nginx. The following load balancing mechanisms (or methods) are supported in nginx: 

  • round-robin: requests to the application servers are distributed in a round-robin fashion, 
  • least-connected: next request is assigned to the server with the least number of active connections, 
  • ip-hash: a hash-function is used to determine what server should be selected for the next request (based on the client’s IP address).  

Note: Please note that with round-robin or least-connected load balancing, each subsequent client’s request can be potentially distributed to a different server. There is no guarantee that the same client will be always directed to the same server. Learn More From Nginx Official Docs

In our case, We are using four Web/Application Server where Nginx will distribute HTTP/HTTPS traffic to each. Add Swap Memory to your Nginx Load Balancer for better PerformanceAllow 80 & 443 port on your UFW firewall and don't disable AppArmor for security purposes. Update your apt and add Nginx repo with signing key 

# apt update & apt upgrade -y
# vi /etc/apt/sources.list.d/nginx.list
deb [arch=amd64] bionic nginx
deb-src bionic nginx

# wget
# sudo apt-key add nginx_signing.key
# sudo apt-get update
# sudo apt-get install nginx -y
# sudo systemctl enable nginx
# sudo systemctl start nginx
# nginx -t
# nginx -V 
Adjust Default configuration
# cd /etc/nginx/conf.d/
# vi default.conf  
Secure Your Nginx Load Balancer
# cp -a /etc/nginx/nginx.conf /etc/nginx/nginx.conf.old
# openssl dhparam -out /etc/nginx/dhparam.pem 4096
# vi /etc/nginx/nginx.conf 
Add the following lines to your configuration [For Better Compression you can use Brotli]
user nginx;
worker_processes auto;
worker_rlimit_nofile    65535;
error_log               /var/log/nginx/error.log crit;
#error_log               /var/log/nginx/error.log warn;
pid                     /var/run/;

events {
        worker_connections  8096;
        use                 epoll;
        multi_accept        on;


http {

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;

        ## Start: Size Limits & Buffer Overflows ##
        client_body_buffer_size 256k;
        client_header_buffer_size 4k;
        client_max_body_size 256M;
        large_client_header_buffers 4 32k;
        ## END: Size Limits & Buffer Overflows ##

        ## Start: Timeouts ##
        client_header_timeout 300;
        client_body_timeout 300;
        keepalive_timeout 60 60;
        send_timeout 600;
        ## End: Timeouts ##

        reset_timedout_connection       on;
        server_names_hash_max_size 1024;
        server_names_hash_bucket_size 1024;

        ignore_invalid_headers on;
        connection_pool_size 256;
        request_pool_size 4k;
        output_buffers 4 32k;
        postpone_output 1460;

        ##add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
        add_header X-Frame-Options "SAMEORIGIN"  always;
        add_header X-Content-Type-Options "nosniff"  always;
        add_header X-XSS-Protection "1; mode=block";
        #add_header Content-Security-Policy "frame-ancestors;";
        add_header Referrer-Policy strict-origin-when-cross-origin;
        add_header Feature-Policy "accelerometer 'none'; ";

        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;

        # Compression gzip
        gzip on;
        gzip_vary on;
        gzip_disable "MSIE [1-6]\.";
        gzip_proxied any;
        gzip_min_length 512;
        gzip_comp_level 6;
        gzip_buffers 8 64k;
        gzip_types text/plain text/xml text/css text/js application/x-javascript application/xml image/png image/x-icon image/gif image/jpeg image/svg+xml application/xml+rss text/javascript application/atom+xml application/javascript application/json application/x-font-ttf font/opentype;

        # Proxy settings
        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_pass_header   Set-Cookie;
        proxy_connect_timeout   600;
        proxy_send_timeout  600;
        proxy_read_timeout  600;
        fastcgi_send_timeout 600s;
        fastcgi_read_timeout 600s;
        proxy_buffers       32 4k;
        proxy_cache_path /var/cache/nginx levels=2 keys_zone=cache:10m inactive=60m max_size=512m;
        proxy_cache_key "$host$request_uri $cookie_user";
        proxy_temp_path  /var/cache/nginx/temp;
        proxy_ignore_headers Expires Cache-Control;
        proxy_cache_use_stale error timeout invalid_header http_502;
        proxy_cache_valid any 1d;

        open_file_cache_valid 120s;
        open_file_cache_min_uses 2;
        open_file_cache_errors off;
        open_file_cache max=5000 inactive=30s;
        open_log_file_cache max=1024 inactive=30s min_uses=2;

        # SSL Settings
        #ssl_protocols TLSv1.3;# Requires nginx >= 1.13.0 else use TLSv1.2
        ssl_protocols TLSv1.2;
        ssl_prefer_server_ciphers   on;
        ssl_dhparam /etc/nginx/dhparam.pem; # openssl dhparam -out /etc/nginx/dhparam.pem 4096
        #ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
        ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0

        ssl_session_timeout 10m;
        ssl_session_cache   shared:SSL:10m;
        ssl_session_tickets off; # Requires nginx >= 1.5.9

        # OCSP stapling
        ssl_stapling on; # Requires nginx >= 1.3.7
        ssl_stapling_verify on; # Requires nginx => 1.3.7

        port_in_redirect off;
        resolver valid=300s;
        resolver_timeout 5s;
        ssl_buffer_size 4k;

        # Logs
        log_format  main    '$remote_addr - $remote_user [$time_local] $request '
                                '"$status" $body_bytes_sent "$http_referer" '
                                '"$http_user_agent" "$http_x_forwarded_for"';
        log_format  bytes   '$body_bytes_sent';
        #access_log          /var/log/nginx/access.log main;
        access_log off;

        # Cache bypass
        map $http_cookie $no_cache {
                default 0;
                ~SESS 1;
                ~wordpress_logged_in 1;

        # Include additional configuration
        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/;
        include /etc/nginx/fakegooglebots.rules;
        include /etc/nginx/blockuseragents.rules;
Add Cloudflare IP to your Nginx
# vi /etc/nginx/
# Cloudflare
set_real_ip_from   2400:cb00::/32;
set_real_ip_from   2606:4700::/32;
set_real_ip_from   2803:f800::/32;
set_real_ip_from   2405:b500::/32;
set_real_ip_from   2405:8100::/32;
set_real_ip_from   2c0f:f248::/32;
set_real_ip_from   2a06:98c0::/29;
real_ip_header     CF-Connecting-IP;
Block User agents
# vi /etc/nginx/blockuseragents.rules
map $http_user_agent $blockedagent {
        default         0;
        ~*malicious     1;
        ~*bot           1;
        ~*backdoor      1;
        ~*crawler       1;
        ~*bandit        1;
Block FakeBots
# vi /etc/nginx/fakegooglebots.rules
map $http_user_agent $isBot {
  ~*(Googlebot|Google-Site-Verification|Google\ Web\ Preview|Google\ Favicon|developers\.google\.com|Google-Structured-Data-Testing-Tool) "true";
  ~*(YandexBot|\+http\:\/\/yandex\.com\/bots) "true";
  ~*(bingbot|msnbot|BingPreview) "true";
  ~*Twitterbot "true";
  ~*slurp "true";
  default "false";

#rdns_allow (.*google\.com|.*googlebot\.com|.*yandex\.ru|.*yandex\.net|.*yandex\.com|.*search\.msn\.com|.*twttr\.com|.*crawl\.yahoo\.net);
#rdns_deny .*;

#if ($isBot = "true") {
#  rdns double;
Now Configure Load Balancing for
# vi /etc/nginx/conf.d/
upstream rubel {

    server {
        listen      80;
        listen      [::]:80;
        #access_log /var/log/nginx/ bytes;
        access_log /var/log/nginx/ combined;
        error_log /var/log/nginx/ error;

        location / {
                proxy_redirect      off;
                proxy_set_header    X-Real-IP $remote_addr;
                proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header    Host $http_host;
                proxy_pass http://rubel;
Now Check Nginx syntax , If everything is okay , start your Nginx as a Load Balancer . 
# nginx -t
# sudo systemctl start nginx 

Part 2: How to install Wildcard SSL to Nginx Load Balancer on Ubuntu 18.04 LTS ?