Apache Tomcat is a Java servlet container: it runs Java web applications packaged as WAR files (Spring, Jakarta EE apps, many enterprise tools). It is not the same as the Apache HTTP Server. This guide installs Tomcat on a Linux VPS as a service and publishes it securely through Nginx.
Before you start
- A Linux VPS with at least 2 GB RAM; Java apps are memory-hungry.
- A domain pointing to the server and ports 80/443 open.
- Check your app's required Tomcat and Java versions. Tomcat 10.1+ uses the
jakarta.*namespace; older apps written forjavax.*need Tomcat 9.
Install Java
- Ubuntu/Debian:
sudo apt install -y openjdk-17-jdk-headless - AlmaLinux/Rocky:
sudo dnf install -y java-17-openjdk-headless
Confirm with java -version. Use 21 if your app supports it.
Install Apache Tomcat
- Create a system user:
sudo useradd -r -m -d /opt/tomcat -s /bin/false tomcat - Download the current 10.1.x "core" tar.gz from the official Apache Tomcat download page, verify its SHA-512 checksum, and extract it:
sudo tar xzf apache-tomcat-10.1.*.tar.gz -C /opt/tomcat --strip-components=1 - Set ownership:
sudo chown -R tomcat:tomcat /opt/tomcat.
Run Tomcat with systemd
Create /etc/systemd/system/tomcat.service:
[Unit]
Description=Apache Tomcat
After=network.target
[Service]
Type=forking
User=tomcat
Group=tomcat
Environment=JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
Environment=CATALINA_HOME=/opt/tomcat
Environment=CATALINA_PID=/opt/tomcat/temp/tomcat.pid
Environment="CATALINA_OPTS=-Xms512m -Xmx1024m"
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh
Restart=on-failure
[Install]
WantedBy=multi-user.targetAdjust JAVA_HOME (find it with readlink -f $(which java), minus /bin/java). Then:
sudo systemctl daemon-reload && sudo systemctl enable --now tomcatBind Tomcat to localhost
In /opt/tomcat/conf/server.xml, edit the HTTP connector so only Nginx can reach it:
<Connector port="8080" address="127.0.0.1" protocol="HTTP/1.1" connectionTimeout="20000" />Also add a RemoteIpValve inside the <Host> element so Tomcat trusts X-Forwarded-For and X-Forwarded-Proto from the proxy:
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" />Restart Tomcat afterwards.
Put Nginx in front
server {
listen 80;
server_name java.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Reload Nginx, then add HTTPS with sudo certbot --nginx -d java.example.com. See Certbot on Linux.
Deploy an application
- Copy
myapp.warto/opt/tomcat/webapps/; Tomcat unpacks it and serves it at/myapp. - To serve it at the root, name the file
ROOT.war(remove the default ROOT folder first).
Secure the Manager app
The Manager and Host Manager apps can deploy code, so they are a prime target. Either delete webapps/manager and webapps/host-manager, or keep them restricted to localhost (the default RemoteAddrValve in their context.xml) and reach them through an SSH tunnel. Also delete webapps/examples and webapps/docs on production.
Troubleshooting
- 502 Bad Gateway: Tomcat is not running or still starting. Check
journalctl -u tomcatand/opt/tomcat/logs/catalina.out. - java.lang.OutOfMemoryError: raise
-Xmxor add RAM; leave memory for the OS. - Redirects go to http:// or port 8080: RemoteIpValve missing or headers not forwarded.
FAQ: Apache Tomcat
Is Tomcat the same as Apache HTTP Server?
No. Both are Apache Software Foundation projects, but Tomcat runs Java apps; httpd serves files and proxies.
Can Tomcat run on shared cPanel hosting?
Not on standard shared plans. Use a VPS.
Should Tomcat face the internet directly?
It can, but a reverse proxy makes TLS, compression and security headers simpler.
