Apache Tomcat is a widely used web server and servlet container that's essential for deploying Java applications. In this tutorial, we will guide you through the installation of Apache Tomcat 10 on an Ubuntu 20.04 server. We'll also set up user authentication, configure access to Tomcat's admin interface, and ensure that your server is ready to serve Java applications.
## Prerequisites
Before we begin, make sure you have the following:
- A server running Ubuntu 20.04.
- Root or sudo access to the server.
Step 1: Install Tomcat and JDK
1.1. Create a Separate User for Tomcat:
For security purposes, it's best to run Tomcat under a separate user. Create a user named "tomcat" with the following command:
# useradd -m -d /opt/tomcat -U -s /bin/false tomcat
1.2. Install the Java Development Kit (JDK):
Apache Tomcat requires Java to run. Install the default JDK package with the following command:
# apt update
# apt install default-jdk
Check the installed Java version:
# java -version
Step 2: Download and Configure Tomcat
2.1. Navigate to the `/tmp` directory:
# cd /tmp
2.2. Download and Extract Tomcat:
Download the latest version of Apache Tomcat 10 using `wget`:
# wget https://archive.apache.org/dist/tomcat/tomcat-10/v10.0.11/bin/apache-tomcat-10.0.11.tar.gz
Extract the downloaded archive to the `/opt/tomcat` directory:
# tar xzvf apache-tomcat-10*tar.gz -C /opt/tomcat --strip-components=1
Set the correct permissions for the Tomcat installation:
# chown -R tomcat:tomcat /opt/tomcat/
# chmod -R u+x /opt/tomcat/bin
Step 3: Configure Admin Users
3.1. Open the `tomcat-users.xml` file for editing:
# vi /opt/tomcat/conf/tomcat-users.xml
3.2. Add the following lines before the closing `</tomcat-users>` tag:
<user username="manager" password="redhat" roles="manager-gui" />
<role rolename="admin-gui" />
<user username="admin" password="redhat" roles="manager-gui,admin-gui" />
3.3. Save and close the file.
Step 4: Remove IP Restrictions for Admin Pages
4.1. Remove IP restrictions for the Manager page:
# vi /opt/tomcat/webapps/manager/META-INF/context.xml
Comment out the Valve definition, like this:
allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> -->
4.2. Save and close the file.
Repeat the same process for the Host Manager:
#vi /opt/tomcat/webapps/host-manager/META-INF/context.xml
Comment out the Valve definition, like this:
allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> -->
4.3. Save and close the file.
Step 5: Create a systemd Service
5.1. Determine the Java path:
# update-java-alternatives -l
Note the path where Java is located.
5.2. Create a systemd service file for Tomcat:
# vi /etc/systemd/system/tomcat.service
Add the following content, modifying the `JAVA_HOME` path if necessary:
Description=Tomcat
After=network.target
[Service]
Type=forking
User=tomcat
Group=tomcat
Environment="JAVA_HOME=/usr/lib/jvm/java-1.11.0-openjdk-amd64"
Environment="JAVA_OPTS=-Djava.security.egd=file:///dev/urandom"
Environment="CATALINA_BASE=/opt/tomcat"
Environment="CATALINA_HOME=/opt/tomcat"
Environment="CATALINA_PID=/opt/tomcat/temp/tomcat.pid"
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC"
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh
RestartSec=10
Restart=always
WantedBy=multi-user.target
5.3. Save and close the file.
5.4. Reload the systemd daemon:
# systemctl daemon-reload
5.5. Start Tomcat and enable it to start on boot:
# systemctl start tomcat
# systemctl enable tomcat
Step 6: Configure Firewall
Allow traffic on port 8080 (Tomcat's default port) through the firewall:
# ufw allow 8080
Step 7: Access the Web Interface
A. You can now access the Tomcat web interface using your server's IP address:
http://192.168.2.202:8080
D. Press on the Host Manager button on the right. You’ll be prompted to enter the account credentials that you defined in a previous step.
Tomcat - Web Application Manager The Web Application Manager is used to manage your Java applications. You can start, stop, reload, deploy, and undeploy them from here. You can also run some diagnostics on your apps (for example, to find memory leaks). Information about your server is available at the very bottom of this page.
A. Download the war (https://tomcat.apache.org/tomcat-7.0-doc/appdev/sample/sample.war) on you desktop.
B. Go to the "Manager App" on the Tomcat web interface.
E. After deploying, you will find the "sample" application listed. Click on it to open the web page.
Below is a clean, working way to run 3 Tomcat apps (prod/dev/test) on one Linux server with:
Different
CATALINA_HOMEfor each appSame
CATALINA_BASEDifferent ports:
Prod → 8080
Dev → 8081
Test → 8082
You are currently running Tomcat 10.0.11 on Java 17, which is fine.
📌 Architecture (as requested)
CATALINA_BASE = /opt/tomcat-base (SAME for all)
CATALINA_HOME:
├─ /opt/tomcat-prod
├─ /opt/tomcat-dev
└─ /opt/tomcat-test
Each CATALINA_HOME has its own Tomcat binaries, but all share one base config & apps.
1️⃣ Prepare directories
mkdir -p /opt/tomcat-{prod,dev,test}
mkdir -p /opt/tomcat-base
2️⃣ Copy Tomcat binaries into each CATALINA_HOME
You already have Tomcat in /opt/tomcat.
cp -r /opt/tomcat/* /opt/tomcat-prod/
cp -r /opt/tomcat/* /opt/tomcat-dev/
cp -r /opt/tomcat/* /opt/tomcat-test/
3️⃣ Prepare common CATALINA_BASE structure
cd /opt/tomcat-base
mkdir -p conf logs temp webapps work
Copy configuration templates:
cp /opt/tomcat-prod/conf/* conf/
⚠️ Remove
server.xmlduplication later (we will manage ports per instance)
4️⃣ Configure ports (CRITICAL STEP)
Edit /opt/tomcat-base/conf/server.xml
We will use variables so each instance runs on different ports.
Replace ports like this:
<Server port="${shutdown.port}" shutdown="SHUTDOWN">
<Connector
port="${http.port}"
protocol="org.apache.coyote.http11.Http11NioProtocol"
connectionTimeout="20000"
redirectPort="${https.port}" />
<Connector
port="${ajp.port}"
protocol="AJP/1.3"
redirectPort="${https.port}" />
5️⃣ Create startup scripts per environment
🔴 PROD (8080)
cat <<EOF >/opt/tomcat-prod/start-prod.sh
#!/bin/bash
export CATALINA_HOME=/opt/tomcat-prod
export CATALINA_BASE=/opt/tomcat-base
export JAVA_OPTS="
-Dhttp.port=8080
-Dhttps.port=8443
-Dajp.port=8009
-Dshutdown.port=8005
"
\$CATALINA_HOME/bin/startup.sh
EOF
chmod +x /opt/tomcat-prod/start-prod.sh
🔵 DEV (8081)
cat <<EOF >/opt/tomcat-dev/start-dev.sh
#!/bin/bash
export CATALINA_HOME=/opt/tomcat-dev
export CATALINA_BASE=/opt/tomcat-base
export JAVA_OPTS="
-Dhttp.port=8081
-Dhttps.port=8444
-Dajp.port=8010
-Dshutdown.port=8006
"
\$CATALINA_HOME/bin/startup.sh
EOF
chmod +x /opt/tomcat-dev/start-dev.sh
🟢 TEST (8082)
cat <<EOF >/opt/tomcat-test/start-test.sh
#!/bin/bash
export CATALINA_HOME=/opt/tomcat-test
export CATALINA_BASE=/opt/tomcat-base
export JAVA_OPTS="
-Dhttp.port=8082
-Dhttps.port=8445
-Dajp.port=8011
-Dshutdown.port=8007
"
\$CATALINA_HOME/bin/startup.sh
EOF
chmod +x /opt/tomcat-test/start-test.sh
6️⃣ Start all environments
/opt/tomcat-prod/start-prod.sh
/opt/tomcat-dev/start-dev.sh
/opt/tomcat-test/start-test.sh
7️⃣ Verify
ps -ef | grep tomcat
Check URLs:
| Environment | URL |
|---|---|
| PROD | http://localhost:8080 |
| DEV | http://localhost:8081 |
| TEST | http://localhost:8082 |
8️⃣ Verify CATALINA values
/opt/tomcat-prod/bin/version.sh
Expected:
Using CATALINA_BASE: /opt/tomcat-base
Using CATALINA_HOME: /opt/tomcat-prod
📝 Important Notes
✔ Same webapps → apps deployed once
✔ Different Tomcat binaries → safe upgrades per env
✔ Clean port isolation
✔ Java 17 supported for Tomcat 10
🔥 Optional (Recommended)
Create systemd services for prod/dev/test
Separate logs per environment using logback/log4j
Add JVM tuning per env
If you want, I can:
Create systemd unit files
Show WAR deployment per env
Convert this into Ansible automation
Just tell me 👍
Your architecture (different CATALINA_HOME, same CATALINA_BASE, different ports) is a valid and professional Tomcat design. Below are the real, practical benefits, especially relevant for Linux admins / DevOps / production systems like yours.
🔷 1. Centralized Application & Configuration Management
(Single CATALINA_BASE)
✔ One place for:
conf/webapps/logs/work/temp/
Benefits
Deploy the app once, it’s available for prod/dev/test
Configuration changes (datasource, security, context.xml) apply consistently
Avoids config drift between environments
👉 Ideal for enterprise environments where consistency matters.
🔷 2. Binary Isolation (Safe Upgrades & Rollbacks)
(Different CATALINA_HOME)
Each environment has its own Tomcat binaries.
✔ Upgrade DEV first
✔ Test on TEST
✔ Promote to PROD
Benefits
Zero risk of breaking prod during testing
Rollback is easy (just switch binaries)
Different Tomcat patch levels if needed
👉 This is best practice for controlled production systems.
🔷 3. Port-Based Environment Separation
| Environment | Port |
|---|---|
| PROD | 8080 |
| DEV | 8081 |
| TEST | 8082 |
Benefits
All environments run simultaneously
No VM/container duplication required
Easy access for testing & validation
👉 Saves infrastructure cost while maintaining isolation.
🔷 4. Faster CI/CD & Testing Cycles
✔ One server
✔ Three environments
✔ One deployment artifact
Benefits
CI/CD pipelines deploy once, validate across environments
Developers can test changes without touching PROD
Faster feedback loop
👉 Very useful in Jenkins / GitLab / Azure DevOps pipelines.
🔷 5. Operational Simplicity for Linux Teams
✔ One base directory to back up
✔ One log location
✔ One app lifecycle
Benefits
Easier monitoring (Zabbix, Prometheus)
Easier troubleshooting
Faster recovery during incidents
👉 Matches SRE / Ops workflows.
🔷 6. Reduced Resource Consumption
Compared to:
3 separate VMs ❌
3 containers ❌
Your design:
Shared disk
Shared configs
Shared app
Benefits
Lower memory & CPU footprint
Fewer OS-level resources
Faster startup time
👉 Excellent for non-containerized legacy apps.
🔷 7. Security & Risk Containment
✔ Binary compromise in DEV won’t affect PROD
✔ JVM options can differ per env
✔ Easy to restrict access via firewall rules
Benefits
Controlled blast radius
Environment-specific JVM hardening
Easier compliance checks
🔷 8. Easier Troubleshooting & Debugging
✔ Same app
✔ Same config
✔ Same OS
Benefits
Issues reproduced quickly in DEV/TEST
Root cause analysis becomes faster
No “works in dev but not prod” excuses 😄
🔷 9. Enterprise-Approved Pattern
This architecture is commonly used in:
Banks 🏦
Utilities (like Yorkshire Water)
SAP-integrated Tomcat systems
Regulated production environments
✔ Auditable
✔ Predictable
✔ Maintainable
⚠️ When NOT to Use This Architecture
| Scenario | Better Option |
|---|---|
| High traffic isolation | Separate VMs |
| Auto-scaling needed | Containers / Kubernetes |
| Strict security zones | Dedicated hosts |
✅ Summary (Why this is GOOD)
✔ Professional-grade
✔ Cost-efficient
✔ Easy upgrades
✔ Safe testing
✔ Clean separation
✔ Production-friendly
If you want, next I can:
Compare this with Docker/Kubernetes
Design systemd services
Add log separation per env
Provide interview-ready explanation
Just tell me what you need 👍
------------------------------------------------------------------------------------
No comments:
Post a Comment