How to use NGINX as a Reverse Proxy for an Apache Tomcat Web Server?

This is going to be a quick-start article to Configuring NGINX as a reverse proxy server for HTTP and other protocols. You will learn how to pass a request from NGINX to proxied servers over different protocols and TCP ports, modify client request headers that are sent to the proxied server.

What is NGINX?

As per Wikipedia, NGINX (pronounced "engine x", stylized as NGINX or nginx) is a web server that can also be used as a reverse proxy, load balancer, mail proxy and HTTP cache.

What is Apache Tomcat?

Wikipedia also defines Apache Tomcat (called "Tomcat" for short) as a free and open-source implementation of the Jakarta Servlet, Jakarta Expression Language, and WebSocket technologies. It provides a "pure Java" HTTP web server environment in which Java code can also run. Thus it is a Java web application server, although not a full JEE application server.

LAB SETUP

Azure Virtual Machine VM1 - Running Ubuntu 2204 + NGINX + Tomcat Server

Configure your environment

Azure subscription: If you don't have an Azure subscription, create a Azure free account before you begin.

Open Cloud Shell

If you already have a Cloud Shell session open, you can skip to the next section.

Browse to the Azure Portal

If necessary, log in to your Azure subscription and change the Azure directory with the subscription that you would like to use.

Open Cloud Shell.

image

Create the Azure Virtual Machine

Create a new Resource Group

az group create --name nginxrg267 --location eastus2

Create a new Azure VM

az vm create \
--resource-group nginxrg267 \
--name nginxvm267 \
--image Ubuntu2204 \
--admin-username "azureuser" \
--ssh-key-value ~/.ssh/id_rsa.pub \
--public-ip-sku Standard \

Open Firewall port 8080 for TOMCAT

az vm open-port \
--resource-group nginxrg267 \
--name nginxvm267  \
--port 8080 --priority 1010

Open Firewall port 80 for NGINX

az vm open-port \
--resource-group nginxrg267 \
--name nginxvm267  \
--port 80 --priority 1011

Install NGINX, JAVA and TOMCAT

Login to the Azure VM

sudo apt-get update -y && sudo apt-get install nginx fontconfig openjdk-17-jre -y 
sudo systemctl start nginx && sudo systemctl enable nginx 
sudo mkdir /opt/tomcat 
sudo wget https://downloads.apache.org/tomcat/tomcat-10/v10.1.20/bin/apache-tomcat-10.1.20.tar.gz 
sudo tar xzvf apache-tomcat-10tar.gz -C /opt/tomcat --strip-components=1 
sudo sh -c 'chmod +x /opt/tomcat/bin/.sh' 
sudo /opt/tomcat/bin/startup.sh

##OUTPUT should say "TOMCAT STARTED"

You should now be able to browse to the public IP or DNS Name of your Azure VM over the port 8080 and get the default TOMCAT page

image

You should also be able to browse to the public IP or DNS Name of your Azure VM and get the default NGINX page

image

You may configure a DNS Name for the Azure VM as shown below

image

image

Basic Proxy Routing with the Default NGINX Configuration File

We shall be using the Portfolio Template from github repository for this LAB.

git clone https://github.com/mfkhan267/nginx2024.git

sudo mv nginx2024/portfoliotemplate/ /portfoliotemplate/ -f

Backup the Default NGINX Configuration File

sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak

EDIT the NGINX CONF File

sudo vi /etc/nginx/nginx.conf

COPY PASTE the below configuration code into the NGINX Conf File and Save / Close

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
    worker_connections 768;
}

http {
    sendfile on;
    tcp_nopush on;
    types_hash_max_size 2048;
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
    server {
        listen 80;
        server_name localhost;
        root /portfoliotemplate/;
    }
}

image

Validate the NGINX Configuration

sudo nginx -t

Reload the NGINX Configuration File

nginx -s reload

Your Portfolio website should now be rendered on the http://localhost:80 OR http://localhost

image

Application Level Routing with the Custom Configuration File

Create a NGINX Conf File for TOMCAT

sudo vi /etc/nginx/sites-available/tomcat.conf

Copy paste below snippet to the tomcat.conf as below and save / close the file

server {
  listen 8000;
  server_name    <Domain Name or Public IP of VM>;
  access_log /var/log/nginx/tomcat-access.log;
  error_log /var/log/nginx/tomcat-error.log;
  location / {
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:8080/;
  }
}

The tomcat.conf file should look like as shown below

Screenshot of the file tomcat.conf

Validate the NGINX Configuration

sudo nginx -t

Enable the NGINX host configuration file for TOMCAT and restart the NGINX web server to apply the changes

sudo ln -s /etc/nginx/sites-available/tomcat.conf /etc/nginx/sites-enabled/

sudo systemctl reload nginx OR sudo nginx -s reload

If all OK, Restart the NGINX Service

sudo systemctl restart nginx

If you now browse to the DNS name of your Azure VM, you should see the TOMCAT Default Page instead of the NGINX Default Page.

Now, you can access your Tomcat default webpage using the URL http://domain_name OR http://<PUBLIC_IP>

image

OPTIONAL - You may also create a systemd service for Tomcat

sudo vi /etc/systemd/system/tomcat.service

Copy and Paste the below Tomcat Systemd Service Script

[Unit]
Description=Apache Tomcat Web Application Container
After=syslog.target network.target

[Service]
Type=forking

Environment="JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64"
Environment="CATALINA_PID=/opt/tomcat/temp/tomcat.pid"
Environment="CATALINA_HOME=/opt/tomcat/"
Environment="CATALINA_BASE=/opt/tomcat/"
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC"
Environment="JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom"

ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh

[Install]
WantedBy=multi-user.target

Reload Daemon

sudo systemctl daemon-reload

Start and Enable the Tomcat Service

sudo systemctl start tomcat && sudo systemctl enable tomcat

References

https://docs.nginx.com/nginx/deployment-guides/load-balance-third-party/apache-tomcat/

https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/

https://www.digitalocean.com/community/tutorials/install-tomcat-on-linux

https://www.atlantic.net/vps-hosting/how-to-setup-tomcat-with-nginx-as-a-reverse-proxy-on-ubuntu/