Nginx reverse proxy with Private Networking on Digital Ocean

Standard
Spread the love
  • 5
    Shares

Exposing application servers to the Internet is considered as a bad practice. The recommendation is to shield it using a web server (reverse proxy). This not only reduces traffic to the application server but it also prevents from exposing critical ports to the world. Another advantage is to route static resource requests to a different server or location. The practice is known as Reverse proxy.

While using Digital Ocean cloud infrastructure, I came across an interesting feature – Private Networking. The feature caught my eye as it is definitely a must have to host services / servers on private IP. I decided to try this feature and host Nginx and spring boot application on Digital Ocean infrastructure.

  • Nginx as reverse proxy
  • Application server in Private Networking (Spring boot)

Application server

This is going to be pretty easy step. We will build a simple Spring boot application which will host a REST API. To get started visit https://start.spring.io website and enter following details.

Import the project in Eclipse and let Maven plugin to download all the required dependencies.

Greeting Service

Once the project configuration is complete, create a package – com.demo.digital.spring.reverseproxy.api

Inside the package, we will create our very own REST API. Please refer to following class for simple greeting service.

@RestController
public class GreetingService {
@RequestMapping(path = { "/greeting" }, method = { RequestMethod.GET }, produces = { "application/json" })
public Message greetUser() {

    Message m = new Message();
    m.setMessage("It's a beautiful day!!!");
    return m;
}
}

Run the spring boot application and you should be able to see following response in browser.

REST API in browser

Congratulations!!! we are done with our very first step and successfully ran application server.

Nginx Setup

Digital Ocean is definitely a cost-effective and quality solution for Cloud deployments. I personally found it much better option to carry out R&D stuffs on Digital Ocean(DO) than on other cloud vendors. Interestingly, DO has been spending a lot of efforts in bringing new services to the masses and believe me they are very pocket friendly (I am not paid to do the promotion of DO. This is purely my personal experience). Anyways lets proceed with Nginx setup on DO.

I will keep this very short and assume that you are already familiar with the DO’s interface. Choose options as depicted below

Operating System selection

Scroll down and select the appropriate capacity. For this experiment we are good with $5 server.

Region selection and Security configuration

Make sure that you have “Private Networking” option checked in. Configure SSH keys to restrict access to the Droplet. In the next section, name the server as “ubuntu-nginx-1cpu”. This will help us to easily identify what has been deployed on which server.

That’s all required to create your first Droplet on DO. Click the “Create” button and wait for a few seconds to spin up Droplet.

Nginx installation

Nginx is an awesome server. It is capable of handling much larger concurrent number of users than it’s peer competitors. The installation of Nginx is pretty straightforward. Once the droplet is up and running, just SSH into it with your SSH key. You can make use of tools like PuTTY to gain console access. Just enter following code and you should see Nginx up and running.

sudo apt install nginx

If you wish to know more about Nginx setup, firewall configuration, service checks etc. I will recommend you to visit this cool article from Digital Ocean itself.

Spring Boot on Digital Ocean

Now that we have spun up Nginx, we must proceed with the configuration of Spring Boot. Just repeat the above steps to create one more server and host it in the same region. The application deployed on this server will be running in Private networking. Thereby it will restric public access and only Nginx server is allowed to send requests to this server.

Once the Droplet is up and running, copy the Spring boot application on the Droplet. To run the application, we must setup Java, Maven on the Droplet.

Java Setup

This is definitely a must step to start spring boot application. The step is pretty simple. Go to SSH again and execute following command to install Open JDK.

sudo apt install openjdk-8-jdk

The command will take some time, as it will download required binaries and configure the operating system. Once the installation is over, verify the installation by executing following command.

java -version

If you wish to install Oracle JDK or any other version, just visit this link from Digital Ocean. (Believe me, these guys are not just good in Infrastructure but they have awesome knowledge site. I get solutions to lot of my technical queries from their blog.)

Maven Setup

Maven is very handy to build and run the Spring boot application. If you are comfortable with any other build tool please use that. We don’t have any dependency of build tools for this exercise.

If you wish to use Maven, perform following steps to install it on Ubuntu

cd /opt/
sudo wget http://www-eu.apache.org/dist/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz
sudo tar -xvzf apache-maven-3.3.9-bin.tar.gz
sudo mv apache-maven-3.3.9 maven

Code setup

Now that we have Java and Maven ready to test the application, we must start deploying Spring boot project. You can either use FTP or Git to transfer the project to Digital Ocean server.

Once you have source code available on Digital Ocean server. Run following command to ensure the application is working properly.

mvn spring-boot:run

This command will perform following activities

Compile the project.
Run test cases, if available
Locate the SpringBootApplicaiton (main class) and run it,

If everything is working fine you are able to access the REST API using curl command, we should be good.

Private IP

We must instruct Spring boot application to use Private IP. To do that, just locate the Droplet in Digital Ocean Control Panel, click on the Droplet and you should be able to see the Private IP.

There is also an alternate way to locate Private IP. SSH into the Droplet and execute the following command

ifconfig

You will see a bunch of information along with an IP address being displayed on the console. Locate the eth1 interface and note the IP address displayed against inet. We will require this IP address to access service.

Now go to Spring boot project and in src/main/resources/application.properties add following property

server.name=XXX.XXX.XXX.XXX

The intention is to make sure that the Spring boot application ignores the Public IP address while binding the application server. Assign the private IP located on eth1 interface to server.name property.

Nginx configuration

While both of our servers are ready we must proceed with configuring Nginx to point the web application hosted on Private IP (Spring Boot server).

SSH to droplet containing Nginx server and enter following command.

vi /etc/nginx/sites-available/myserver.conf

Enable insert mode and add following block of configuration

server {
        root /home/do/api;
        index index.html;

        location / {
                if ($request_method = 'OPTIONS') {
                        add_header 'Access-Control-Allow-Origin' '*';
                        add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE';
                        add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Conten
t-Range,Range,x-org-id';
                        add_header 'Access-Control-Max-Age' 1728000;
                        add_header 'Content-Length' 0;
                        return 204;
                }

                proxy_redirect off;
                proxy_pass http://YYY.YYY.YYY.YYY:8080/;
                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_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-Proto https;
                proxy_set_header X-Forwarded-Port $server_port;
        }

        server_name XXX.XXX.XXX.XXX;
        listen 8080;
}

The root directive indicates the root folder for our service. In this case it is pointing to a directory in user home.

The next block maps root location of Web URL and add CORS configuration. With these settings the Nginx URL should be accessible from any domain. To restrict the access you can replace the * (star) with the domain of your choice.

proxy_xxx blocks are the actual crux of the configuration. It instructs Nginx that all the requests starting with location (/) should be forwarded to URL mentioned in proxy_pass. Note that you must mention the private IP address of the Spring Boot application here.

Additionally, you can indicate which headers should be forwarded to the target application using proxy_set_header directive.

We are almost at the end of the configuration. The final block indicates at which domain or IP the Nginx server should listen to and the PORT it should bind. Once all this confiugration is done, you should be able to access Spring boot service hosted on the Private network via Nginx Public IP.

Leave a Reply

Your email address will not be published. Required fields are marked *