Configure NginX to Host Secured Tomcat Application with Wordpress on the Same Ubuntu server

Alex KondratievAlex Kondratiev

10 min read

Imagine you have two web servers on one Ubuntu machine. One of the applications uses Apache Tomcat and another - Nginx with PHP-FPM. You are going to have both of them secured with an SSL certificate. For this purpose, you need to bind them to a single SSL port - 443. There are several options: allocate each SSL port to a dedicated IP / put your app behind Nginx and use SSL in front of your application. The easiest way to manage such a setup is to terminate the SSL connection on the Nginx level.


Prerequisites

Let's check the installation and configuration process on the fresh DigitalOcean Ubuntu 22.04 machine. Also, I will not cover the installation of WordPress in this article. You should have at least two domains pointed to &LTyour-server-ip>. In my case, I will use 'tomcat-lab.itsyndicate.org' and 'wp-lab.itsyndicate.org'.

Step 1: Install Nginx web server

First, you need to log in to your server via SSH with the command ssh root@&LTyour-server-ip> and execute the following:

  • Upgrade your server and package lists

shell

1apt-get update
2apt-get dist-upgrade
  • Install Nginx web server

shell

1apt-get install nginx-extras

Step 2: PHP-FPM installation

shell

1apt-get install php-fpm php-curl php-gd php-mbstring php-mcrypt php-xml php-xmlrpc php-mysql

Step 3: MySQL server installation

shell

1apt-get install mysql-server

Setup root password for MySQL:

mysql

Step 4: Install Apache Tomcat

The easiest way to download Tomcat is using apt-get:

shell

1apt-get install tomcat8

When the installation process is completed you can check that everything works by accessing http://&LTyour-server-ip>:8080/ . You should see "It Works!" greeting.

Step 5: Configure Apache Tomcat to listen only localhost

For now for security reasons and in order not to duplicate content we should bind Tomcat to 127.0.0.1. Open "/etc/tomcat8/server.xml" with your favorite editor and change:

Connector port="8080" protocol="HTTP/1.1"

to:

Connector address="127.0.0.1" port="8080" protocol="HTTP/1.1"

For more information, you could check: https://tomcat.apache.org/tomcat-8.0-doc/config/http.html

When changes are made, restart your Tomcat:

service tomcat8 restart

Now we can check that it's listening on 127.0.0.1 with the following command:

shell

1netstat -nlp | grep java
2tcp6 0 0 127.0.0.1:8080 :::* LISTEN 26917/java

Step 6: Configuring Nginx to serve Tomcat and WordPress

I'm using Let's Encrypt for both of my domains as it's a good solution to secure your app fast and easily.

WordPress site Nginx VHost config

I configured vhost '/etc/nginx/sites-enabled/wp-lab.itsyndicate.org' for WordPress site which is hosted on the same server with Tomcat in the following way:

nginx

1upstream php {
2 server unix:/run/php/php7.0-fpm.sock;
3}
4
5server {
6 ## Domain configuration
7 server_name wp-lab.itsyndicate.org;
8 listen 443 ssl;
9
10 ## SSL configuration (Let's Encrypt)
11 ssl_certificate /etc/letsencrypt/live/wp-lab.itsyndicate.org/fullchain.pem;
12 ssl_certificate_key /etc/letsencrypt/live/wp-lab.itsyndicate.org/privkey.pem;
13 ssl_session_timeout 1d;
14 ssl_session_cache shared:SSL:50m;
15 ssl_session_tickets off;
16
17 # Modern configuration – adjust if needed
18 ssl_protocols TLSv1.2;
19 ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:
20 ECDHE-RSA-AES256-GCM-SHA384:
21 ECDHE-ECDSA-CHACHA20-POLY1305:
22 ECDHE-RSA-CHACHA20-POLY1305:
23 ECDHE-ECDSA-AES128-GCM-SHA256:
24 ECDHE-RSA-AES128-GCM-SHA256:
25 ECDHE-ECDSA-AES256-SHA384:
26 ECDHE-RSA-AES256-SHA384:
27 ECDHE-ECDSA-AES128-SHA256:
28 ECDHE-RSA-AES128-SHA256';
29 ssl_prefer_server_ciphers on;
30
31 ## Root directory
32 root /var/www/wp-lab.itsyndicate.org/public_html;
33 index index.php;
34
35 ## Special cases
36 location = /favicon.ico {
37 log_not_found off;
38 access_log off;
39 }
40
41 location = /robots.txt {
42 allow all;
43 log_not_found off;
44 access_log off;
45 }
46
47 ## Main request handler
48 location / {
49 # Serve static files directly, fallback to WordPress front controller
50 try_files $uri $uri/ /index.php?$args;
51 }
52
53 ## PHP processing
54 location ~ \.php$ {
55 # Ensure "cgi.fix_pathinfo = 0;" in php.ini
56 include fastcgi.conf;
57 fastcgi_intercept_errors on;
58 fastcgi_pass php;
59 }
60
61 ## Static files caching
62 location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
63 expires max;
64 log_not_found off;
65 }
66
67 ## Let's Encrypt challenge
68 location ~ /\.well-known/acme-challenge/ {
69 allow all;
70 root /var/www/letsencrypt;
71 try_files $uri =404;
72 break;
73 }
74}
75

Java Tomcat application Nginx VHost config

I configured vhost '/etc/nginx/sites-enabled/tomcat-lab.itsyndicate.org' for Tomcat application which is hosted on the same server with WordPress in the following way:

shell

1server {
2 ## Domain configuration
3 server_name tomcat-lab.itsyndicate.org;
4 listen 443 ssl;
5
6 ## SSL configuration (Let's Encrypt)
7 ssl_certificate /etc/letsencrypt/live/tomcat-lab.itsyndicate.org/fullchain.pem;
8 ssl_certificate_key /etc/letsencrypt/live/tomcat-lab.itsyndicate.org/privkey.pem;
9 ssl_session_timeout 1d;
10 ssl_session_cache shared:SSL:50m;
11 ssl_session_tickets off;
12
13 # Modern configuration — tweak if needed
14 ssl_protocols TLSv1.2;
15 ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:
16 ECDHE-RSA-AES256-GCM-SHA384:
17 ECDHE-ECDSA-CHACHA20-POLY1305:
18 ECDHE-RSA-CHACHA20-POLY1305:
19 ECDHE-ECDSA-AES128-GCM-SHA256:
20 ECDHE-RSA-AES128-GCM-SHA256:
21 ECDHE-ECDSA-AES256-SHA384:
22 ECDHE-RSA-AES256-SHA384:
23 ECDHE-ECDSA-AES128-SHA256:
24 ECDHE-RSA-AES128-SHA256';
25 ssl_prefer_server_ciphers on;
26
27 ## Document root (for optional static content)
28 root /usr/share/tomcat8-root/default_root;
29
30 ## Proxy to Tomcat backend
31 location / {
32 proxy_pass http://127.0.0.1:8080/;
33
34 proxy_set_header Host $host;
35 proxy_set_header X-Real-IP $remote_addr;
36 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
37 proxy_set_header X-Forwarded-Proto $scheme;
38 proxy_set_header X-Forwarded-Host $host;
39 proxy_set_header X-Forwarded-Server $host;
40
41 proxy_connect_timeout 60s;
42 proxy_send_timeout 90s;
43 proxy_read_timeout 90s;
44 }
45
46 ## Let's Encrypt challenge location
47 location ~ /\.well-known/acme-challenge/ {
48 allow all;
49 root /var/www/letsencrypt;
50 try_files $uri =404;
51 break;
52 }
53}
54

Step 7: Test Tomcat and WordPress are secured and running simultaneously

After our modifications we should check Nginx config and restart web server:

shell

1nginx -t
2nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
3nginx: configuration file /etc/nginx/nginx.conf test is successful
4service nginx restart

Checking WordPress installation:

wp

Conclusion

Setting up Tomcat and WordPress on the same server is a pretty easy job. After reading my post you'll be able to secure your Java and PHP applications that are hosted on the same server. It takes around 30 minutes to get everything done from scratch.

You should also consider that not all topics are cleared here, like Java application deployment and WP secure setup. I hope I have time to create a new post with this info for you.

Comments and critics are more than welcome!

Alex Kondratiev

Alex Kondratiev

Founder of ITsyndicate. DevOps Enthusiast with 15+ years of experience in cloud, Infrastructure as Code, Kubernetes, and automation. Specialized in architecting secure, scalable, and resilient systems.

An Infrastructure Review Should Give You a Plan, Not a Dependency

Why we want the review to be useful even if your own team does all the work afterward. Of course we want to help with the implementation. We are an engineering company. We like solving infrastructure problems, and we want relationships where we can take responsibility for the work over time. So why offer an Infrastructure Review that a client can take back to their own team? Because I want the first engagement to earn its fee on its own, the client should leave with a better understanding of their situation, clear priorities, and a practical next step. They can then decide whether they want us to carry out the changes. That is the principle behind how we are building our Infrastructure Review. It shapes what we agree to investigate, how we explain our findings, and what the client can do with them afterward.

Your Infrastructure Can Be Expensive Even When Nothing Is Broken

A quiet production environment can still hide rising costs, wasted engineering capacity, and risks that appear only during growth or recovery. A familiar weekly update sounds like this: production is stable, the latest release went out, and there were no serious customer complaints. The cloud bill is higher again, but there is probably a reasonable explanation. One engineer spent half a day helping with the release, another fixed a monitoring issue, and the database may need attention next quarter. Nothing is broken badly enough to become a leadership problem. That is exactly why the underlying problem can survive for so long. I have seen this pattern more than once. Production looks stable, while senior engineers quietly spend much of their time keeping it that way. The platform works, but the company is paying for that stability through cloud spend, manual effort, slower releases, and assumptions about growth or recovery that nobody has tested recently. Infrastructure doesn’t need to cause an outage to become expensive. Outages are obvious. Inefficiency is quieter, and it can keep working for years while charging you for the privilege.

How to Run a Docker Container on Your Local Machine

This article is a quick, hands-on guide to running Docker locally. It walks through essential CLI commands for managing images and containers (build, pull, run, ps, start/stop, rm/rmi) and shows how to automate image creation with a Dockerfile. You’ll build an image, run a container with port mapping, verify it’s running, and learn tips for environment setup - everything you need to spin up and manage local containers efficiently.

Stay online.
Stay in command.