
How to Install Apache Tomcat 10 on Ubuntu 24
Apache Tomcat 10 represents a significant milestone in the Java servlet container landscape, introducing Jakarta EE 9 support with the namespace migration from javax.* to jakarta.*. If you’re running Ubuntu 24 (Jammy), setting up Tomcat 10 properly requires understanding both the traditional installation methods and modern containerized approaches. This guide walks through multiple installation techniques, covers essential configuration tweaks, and addresses the gotchas that’ll save you hours of debugging servlet deployment issues.
Understanding Tomcat 10 Architecture Changes
Tomcat 10 isn’t just a version bump – it’s a breaking change that implements Jakarta EE 9 specifications. The major shift involves package namespace changes where all javax.servlet.* packages become jakarta.servlet.*. This affects every servlet, JSP, and related Java EE component.
Key architectural improvements include:
- Enhanced memory management with improved garbage collection integration
- Better HTTP/2 support with reduced overhead
- Streamlined connector architecture for improved performance
- Updated security defaults with stronger cipher suites
Feature | Tomcat 9 | Tomcat 10 | Impact |
---|---|---|---|
Servlet API | javax.servlet.* | jakarta.servlet.* | Breaking change – requires code migration |
Java Version | Java 8+ | Java 11+ | Modern JVM features, better performance |
Memory Usage | Baseline | ~15% reduction | Lower resource footprint |
HTTP/2 Performance | Standard | ~25% improvement | Better concurrent request handling |
Method 1: Manual Installation from Apache Archive
The manual installation gives you complete control over the Tomcat setup and is preferred for production environments where you need specific versions or custom configurations.
First, ensure your system is updated and has Java installed:
sudo apt update && sudo apt upgrade -y
sudo apt install openjdk-17-jdk wget curl -y
java -version
Create a dedicated tomcat user for security isolation:
sudo groupadd tomcat
sudo useradd -s /bin/false -g tomcat -d /opt/tomcat tomcat
Download and extract Tomcat 10:
cd /tmp
wget https://downloads.apache.org/tomcat/tomcat-10/v10.1.16/bin/apache-tomcat-10.1.16.tar.gz
sudo tar xzvf apache-tomcat-10.1.16.tar.gz -C /opt/tomcat --strip-components=1
Set proper ownership and permissions:
sudo chown -R tomcat: /opt/tomcat
sudo sh -c 'chmod +x /opt/tomcat/bin/*.sh'
sudo chmod -R g+r /opt/tomcat/conf
sudo chmod g+x /opt/tomcat/conf
sudo chown -R tomcat /opt/tomcat/webapps/ /opt/tomcat/work/ /opt/tomcat/temp/ /opt/tomcat/logs/
Create a systemd service file for automatic startup:
sudo nano /etc/systemd/system/tomcat.service
Add this configuration:
[Unit]
Description=Apache Tomcat Web Application Container
After=network.target
[Service]
Type=forking
Environment=JAVA_HOME=/usr/lib/jvm/java-17-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
User=tomcat
Group=tomcat
UMask=0007
RestartSec=10
Restart=always
[Install]
WantedBy=multi-user.target
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable tomcat
sudo systemctl start tomcat
sudo systemctl status tomcat
Method 2: APT Package Installation
Ubuntu 24’s repositories include Tomcat 10 packages, making installation straightforward but with less flexibility:
sudo apt update
sudo apt install tomcat10 tomcat10-webapps tomcat10-admin -y
The APT installation automatically:
- Creates tomcat user and group
- Sets up systemd service
- Configures proper file permissions
- Installs default webapps and admin tools
Key file locations for APT installation:
- Installation directory:
/usr/share/tomcat10
- Configuration:
/etc/tomcat10
- Webapps:
/var/lib/tomcat10/webapps
- Logs:
/var/log/tomcat10
Essential Configuration and Security Hardening
Default Tomcat installations are notoriously insecure. Here’s how to lock things down properly.
Configure admin users by editing tomcat-users.xml
:
sudo nano /opt/tomcat/conf/tomcat-users.xml
Add these roles and users before the closing tag:
<role rolename="manager-gui" />
<role rolename="manager-script" />
<role rolename="manager-jmx" />
<role rolename="manager-status" />
<role rolename="admin-gui" />
<role rolename="admin-script" />
<user username="admin" password="StrongPassword123!" roles="manager-gui,admin-gui" />
<user username="deployer" password="DeployerPass456!" roles="manager-script" />
Secure the Manager app by restricting access. Edit the context file:
sudo nano /opt/tomcat/webapps/manager/META-INF/context.xml
Replace the Valve configuration to allow specific IP ranges:
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|192\.168\.\d+\.\d+" />
Configure JVM memory settings for optimal performance. Edit the service file:
Environment='CATALINA_OPTS=-Xms1024M -Xmx2048M -server -XX:+UseG1GC -XX:MaxGCPauseMillis=200'
Firewall Configuration and Reverse Proxy Setup
Configure UFW to allow Tomcat traffic:
sudo ufw allow 8080/tcp
sudo ufw allow 8443/tcp
sudo ufw enable
For production deployments, set up nginx as a reverse proxy. Install nginx:
sudo apt install nginx -y
Create a virtual host configuration:
sudo nano /etc/nginx/sites-available/tomcat
Add this configuration:
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost: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;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
}
Enable the site:
sudo ln -s /etc/nginx/sites-available/tomcat /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Real-World Deployment Examples
Here’s a practical example of deploying a Jakarta EE 9 application. Create a simple servlet:
package com.example.webapp;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<h1>Hello from Tomcat 10 on Ubuntu 24!</h1>");
out.println("<p>Jakarta EE 9 is working properly.</p>");
}
}
Deploy applications using the manager interface or by copying WAR files:
sudo cp myapp.war /opt/tomcat/webapps/
sudo chown tomcat:tomcat /opt/tomcat/webapps/myapp.war
Performance Tuning and Monitoring
Enable JMX monitoring by adding these JVM options:
Environment='CATALINA_OPTS=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false'
Monitor Tomcat performance with these key metrics:
Metric | Good Range | Warning Signs | Monitoring Command |
---|---|---|---|
Memory Usage | <80% of heap | >90% consistently | jstat -gc [pid] |
Thread Count | <200 active | >500 active | Check manager app |
Response Time | <200ms average | >1000ms average | Access log analysis |
Error Rate | <1% | >5% | Error log monitoring |
Common Issues and Troubleshooting
The most frequent problem is the “javax vs jakarta” namespace issue. If you’re migrating applications from Tomcat 9, use the migration tool:
cd /opt/tomcat/bin
java -jar jakartaee-migration-1.0.0.jar ../webapps/oldapp.war ../webapps/newapp.war
Port binding issues often occur when other services occupy port 8080:
sudo netstat -tlnp | grep :8080
sudo lsof -i :8080
Memory errors typically manifest as OutOfMemoryError. Check current usage:
sudo -u tomcat jcmd $(pgrep -f tomcat) VM.info
sudo -u tomcat jcmd $(pgrep -f tomcat) GC.run_finalization
Permission problems are common after manual installations:
sudo chown -R tomcat:tomcat /opt/tomcat
sudo find /opt/tomcat -type d -exec chmod 755 {} \;
sudo find /opt/tomcat -type f -exec chmod 644 {} \;
sudo chmod +x /opt/tomcat/bin/*.sh
Integration with Development Tools
For IDE integration, configure remote debugging by adding these JVM options:
Environment='CATALINA_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000'
Maven deployment configuration for automated builds:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<url>http://localhost:8080/manager/text</url>
<server>tomcat-server</server>
<path>/myapp</path>
</configuration>
</plugin>
Docker containerization for development consistency:
FROM tomcat:10.1-jdk17-openjdk-slim
COPY target/myapp.war /usr/local/tomcat/webapps/
EXPOSE 8080
CMD ["catalina.sh", "run"]
This setup provides a robust foundation for running Jakarta EE applications on Ubuntu 24. The namespace migration requires careful attention, but the performance improvements and modern Java features make Tomcat 10 worth the upgrade effort. Regular monitoring and proper security configuration ensure your deployment remains stable and secure in production environments.
For additional information, check the official Apache Tomcat 10 documentation and the Jakarta EE specifications for detailed API references.

This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.
This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.