How to setup NGINX reverse proxy for application server dev and prod setup with Let’s Encrypt SSL certificate on Ubuntu 18.04

  Reading Time:

Assume we have two app servers running on port 8181 and 8080 Prod on 8080 and dev on 8181

We want to redirect

http --> https --> localhost
http://prod.example.com --> https://prod.example.com --> localhost:8080
http://dev.example.com --> https://dev.example.com --> localhost:8181

 

Lets Install Nginx on Ubuntu 18.04

 

Connect to your Ubuntu box via SSH and run the following command on terminal

sudo apt update
sudo apt install nginx

 

Configure Ubuntu firewall

Ubuntu Firewall setup for Nginx HTTPS  and HTTP

sudo ufw status
To                         Action      From
--                         ------      ----
22                         ALLOW       Anywhere
22 (v6)                    ALLOW       Anywhere (v6)
sudo ufw allow 'Nginx HTTPS'
sudo ufw allow 'Nginx HTTP'
sudo ufw status
To                         Action      From
--                         ------      ----

22                         ALLOW       Anywhere
Nginx HTTPS                ALLOW       Anywhere
Nginx HTTP                 ALLOW       Anywhere
22 (v6)                    ALLOW       Anywhere (v6)
Nginx HTTPS (v6)           ALLOW       Anywhere (v6)
Nginx HTTP (v6)            ALLOW       Anywhere (v6)

Check if nginx is running and make sure nginx  auto starts on reboot by enabling nginx service

sudo systemctl start nginx
sudo systemctl enable nginx

Check status

sudo systemctl status nginx

In console we would see

 nginx.service - A high performance web server and a reverse proxy server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: e
   Active: active (running) since Mon 2019-05-13 13:02:22 UTC; 25min ago
 Main PID: 613 (nginx)
   CGroup: /system.slice/nginx.service
           ├─613 nginx: master process /usr/sbin/nginx -g daemon on; master_pro
           ├─614 nginx: worker process
           └─615 nginx: worker process

May 13 13:02:22 ubuntu-sb-blr1-01 systemd[1]: Starting A high performance web s
May 13 13:02:22 ubuntu-sb-blr1-01 systemd[1]: Started A high performance web se
May 13 13:24:28 ubuntu-sb-blr1-01 systemd[1]: Started A high performance web se
lines 1-12/12 (END)

In case you get an error then try the below command to make sure there is no service running on port 80 or 443 . Refer Stackoverflow

Try to run the following two commands:

sudo fuser -k 80/tcp
sudo fuser -k 443/tcp

Enter the http url in your browser's address bar

http://ip_address

and you should see the welcome to nginx page , if you dont see the page then check firewall settings on you cloud service provider system

Nginx welcome page

Install Let's Encrypt client Certbot

 

Automatically enable HTTPS on your website with EFF's Certbot, deploying Let's Encrypt certificates. Visit https://certbot.eff.org/ for more information

Certbot has an Nginx plugin, which is supported on many platforms, and automates certificate installation.

Certbot helps us fetch the SSL certificate from Let's Encrypt  server from cmd prompt , so lets go ahead and install it

sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository universe
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot python-certbot-nginx 

Obtaining an SSL Certificate for our domain

We use the Certbot nginx plugin to obtain SSL certificate

Now run the certbot command to get the SSL certificate for our domain and auto install it on  nginx under the ‘server_name  dev.example.com and prod.example.com server block for port 443 and 80

sudo certbot --nginx -d dev.example.com -d prod.example.com

Follow the instructions in the terminal to get the SSL certificate from 'Let's Encrypt'

Chose Option 2 : Auto redirect HTTP to HTTPS

Certbot would have updated the file

/etc/nginx/sites-enabled/default

The lines added by certbot shown below


server {

        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;
    server_name prod.example.com dev.example.com; # managed by Certbot


        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #        include snippets/fastcgi-php.conf;
        #
        #        # With php7.0-cgi alone:
        #        fastcgi_pass 127.0.0.1:9000;
        #        # With php7.0-fpm:
        #        fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        #}

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #        deny all;
        #}


    listen [::]:443 ssl ipv6only=on; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/dev.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/dev.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot


}
server {
    if ($host = prod.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = dev.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


        listen 80 ;
        listen [::]:80 ;
    server_name prod.example.com dev.example.com;
    return 404; # managed by Certbot
}

Enter the http url in your browser's address bar

http://ip_address

It will get redirected to  https (443 port)

https://ip_address


Lets setup the reverse proxy in Nginx

We want to forward

dev.example.com  →  localhost:8181
prod.example.com → localhost:8080

We need to modify file /etc/nginx/sites-enabled/default




server {
        
    server_name prod.example.com ;

        location / {
                include /etc/nginx/proxy_params;
                proxy_pass  http://localhost:8080;
                proxy_read_timeout  90s;
        }

    listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/dev.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/dev.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

server {
        
    server_name dev.example.com ;

        location / {
                include /etc/nginx/proxy_params;
                proxy_pass  http://localhost:8181;
                proxy_read_timeout  90s;
        }


    listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/dev.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/dev.example.com/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}


server {
    if ($host = prod.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    if ($host = dev.example.com) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


        listen 80 ;
        listen [::]:80 ;
    server_name prod.example.com dev.example.com;
    return 404; # managed by Certbot

}

 

Verify the nginx conf file for any syntax issue

nginx -t

Note : If we get an error during ‘nginx -t’ command then remove 'ipv6only=on' section  , it is a bug in nginx . Cerbot adds that to nginx ipv6 ssl line by default

listen [::]:443 ssl ipv6only=on; # managed by Certbot

modify it as

listen [::]:443 ssl; # managed by Certbot

On 'nginx -t' we will see this in the console

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

Run the command to restart nginx

sudo systemctl reload nginx
sudo systemctl restart nginx

Summary

When we point our browser to http://dev.example.com  it redirects to https then to dev server running on port 8181 and when we point to http://prod.example.com it redirects to https then to prod server running on port 8080

Create custom spring AOP annotation for caching in Spring boot

Lets see how to add custom annotation to cache data to redis , we do have spring @Cacheable but we will not use it because it doesn't...

App & Geek   Never miss a story from App & Geek, get updates in your inbox.