Nginx – how to configure nginx reverse proxy for tomcat servers

nginxreverse-proxytomcat

Well, I have been given the task of "modernizing" an application of the Pleistocene and I can't make this work. Let me explain:

I have a series of tomcat servers, each with the following structure:

(partner1 - tomcatServer1)
http://myServerIp1:8080/ ->tomcat index
http://myServerIp1:8080/webapp1 ->webapp1(main)
http://myServerIp1:8080/webapp2 ->webapp2
(partner2 - tomcatServer2)
http://myServerIp2:8080/ ->tomcat index
http://myServerIp2:8080/webapp1 ->webapp1(main)
http://myServerIp2:8080/webapp2 ->webapp2
http://myServerIp2:8080/webapp3 ->webapp3

As you can see, at first I find several very visible problems.

  1. To begin with, they use a public ip, which complicates the task of
    finding an ssl certificate (but this will be addressed later).
  2. Each server contains several applications.

My initial idea to "modernize" the application was to use a domain and through a dedicated nginx server, make a reverse proxy that uses the following structure

(partner1 - tomcatServer1)
http://partner1.myDomain.com/ ->webapp1(main)
http://partner1.myDomain.com/webapp2 ->webapp2
(partner2 - tomcatServer2)
http://partner2.myDomain.com/ ->webapp1(main)
http://partner2.myDomain.com/webapp2 ->webapp2
http://partner2.myDomain.com/webapp3 ->webapp3

And once this was achieved I would start fighting with the use of ssl. I say this, and I make special mention to it, because I don't want to start with ssl without first checking that it works without it, because I can't even make a good proxy_pass to the tomcat index since it only loads the text without images. If I made a redirect there would be no problems, but the idea is that the client stops using an ip and finally has a serious domain

Of course, not only have I tried with the tomcat index, before I had started to try directly with the webapp1 and found that it gave no error… but it showed absolutely nothing. Seeing this has been when I went to look at the index and I realized that it did not load well either.

At first I thought that the problem could be solved by creating a virtualhost in tomcat for each webapp because I thought that the problem was a brute and make a direct proxy_pass to http://myServerIp1:8080/webapp1/, but once configured the virtual host of tomcat, the result was the same, a completely white page.

I need help, and I think the best way to start is to start from the beginning. Let's see if you can help me by making the tomcat index load correctly

For this, I leave the tomcat configuration for now without virtualhosts and this would be the nginx configuration for the tomcat index at http://partner1.myDomain.com/ (later, if this loads well I start testing with the applications)

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    index index.html index.htm index.nginx-debian.html;
    server_name partner1.myDomain.com;

    location / {
        proxy_pass  http://myServerIp1: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;
        try_files $uri $uri/ =404;
    }
}

As you can see, it is a slight modification of the default nginx file in debian.
If I look at the development tools of the browser, I can see that it has problems with the loading of elements such as "tomcat.css, favicon.ico…".

Best Answer

You have a situation similar to this question. Tomcat does not know it is being proxied and the generated absolute URLs start with http://myServerIp:8080.

You need to add a RemoteIpValve to you <Host>:

<Valve className="org.apache.catalina.valves.RemoteIpValve"
       protocolHeader="X-Forwarded-Proto" />

and set requestAttributesEnabled=true on your AccessLogValve (so the logs contain the real IPs).

NGINX will need to send to Tomcat the Host, X-Forwarded-For and X-Forwarded-Proto headers:

proxy_set_header Host $server_name;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

(the X-Real-IP header is already contained in X-Forwarded-For).

After you modify the configuration the applications running on Tomcat will behave as if Tomcat was running on partner1.example.com:80. Moreover, when you switch to HTTPS, Tomcat will know that the request came from a secure channel and will generate https:// links.

Edit: In your updated configuration you change the absolute path of the proxied pages from /myWebapp/ to /. I'll advise against it: Tomcat sets the cookie path for JSESSIONID to the context path /myWebapp/ so the web browser never sends the cookie back. Use a configuration like this instead:

    location = / {
        return 301 http://partner1.example.com/myWebapp/;
    }

    location / {
        proxy_pass http://myServerIp.8080;
        include    nginxconfig.io/proxy.conf;
    }

which redirects clients from / to /myWebapp/, but otherwise keeps the paths intact.

Note: myDomain.com is a valid domain belonging to someone, therefore it is better to use the domains reserved for documentation in questions and answers.