Project: Nginx + Tomcat

Introduction

This project puts Nginx on ports 80/443 (HTTP first) and Tomcat on 127.0.0.1:8080, serving a static SPA from disk and proxying /blog-api/ to your WAR. It combines Nginx reverse proxy Tomcat with Tomcat security into one VPS-style stack.

Prerequisites

Project Goals

text
  https://app.example.com/           →  Nginx static (SPA)
  https://app.example.com/blog-api/  →  Tomcat WAR
  Tomcat NOT on public 8080

Step 1: Harden Tomcat Connector

conf/server.xml:

xml
<Connector port="8080" protocol="HTTP/1.1"
           address="127.0.0.1"
           connectionTimeout="20000"
           redirectPort="8443" />

Restart:

bash
sudo systemctl restart tomcat
ss -tlnp | grep 8080    # 127.0.0.1:8080
curl http://127.0.0.1:8080/blog-api/posts

Step 2: Static Frontend

Step 3: Nginx Site Config

/etc/nginx/sites-available/hello-app:

Enable:

bash
sudo ln -sf /etc/nginx/sites-available/hello-app /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Local test without DNS:

bash
curl -H "Host: app.example.com" http://127.0.0.1/
curl -H "Host: app.example.com" http://127.0.0.1/blog-api/posts

Step 4: Firewall

bash
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw deny 8080/tcp
sudo ufw enable

Step 5: HTTPS (Production)

When DNS points to the server:

bash
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d app.example.com

See Nginx HTTPS.

Step 6: Compare Static Strategies

AssetServed byWhy
index.html, JS, CSSNginx rootFast, cache-friendly
/blog-api/*TomcatDynamic Servlet / Spring

Tomcat default servlet could serve static files from WAR—this project intentionally offloads static to Nginx.

Acceptance Checklist

  • ss shows Tomcat on 127.0.0.1
    only
  • Browser loads static page via Nginx
  • fetch('/blog-api/posts') succeeds (same origin—no CORS)
  • /var/log/nginx/hello-app.access.log shows requests
  • Public 8080 blocked (if using ufw)

Troubleshooting

SymptomCheck
502 on /blog-api/Tomcat running; loopback curl
Static OK, API failsproxy_pass trailing slashes
404 on /blog-api/WAR context path
CORS errorsUse same host for static + API (this design)

Next

Project: Spring Boot WAR