Installing Tomcat
Introduction
Before you deploy a WAR or edit server.xml, you need a working standalone Tomcat on your machine. This chapter installs Apache Tomcat 10.1.x (Jakarta Servlet, jakarta.*), verifies JDK 17+, starts the server, and confirms the default welcome page at http://127.0.0.1:8080/. A brief directory map is included here; Tomcat Directory Layout goes deeper in the next chapter.
Prerequisites
- What Is Tomcat
- JDK 17 or 21 installed and on
PATH— see Installing Java for Spring Boot if needed - Administrator rights (Windows) or
sudo(Linux) for install paths and ports - ~150 MB disk for Tomcat; more for deployed apps and logs
Version and JDK Matrix
| Tomcat | Servlet API | Recommended JDK | Hello Code default |
|---|---|---|---|
| 10.1.x | Jakarta (jakarta.*) | 17 or 21 | Yes |
| 9.0.x | Java EE (javax.*) | 8+ | Legacy apps only |
This track uses Tomcat 10.1.x to align with Spring Boot 3.
Verify Java First
Tomcat is a Java program—it will not start without a valid JDK.
java -version
echo $JAVA_HOME # macOS/Linux
echo %JAVA_HOME% # Windows CMDCode explanation:
- Output should show 17 or 21 (not an ancient JRE-only install)
JAVA_HOMEshould point to the JDK root (folder containingbin/java), notbinitself
Warning
Wrong Java on PATH
If java -version shows an old version while IDEA uses 21, Tomcat may fail with version errors. Fix PATH and JAVA_HOME, then open a new terminal.
Choose Your Install Method
| Method | Best for | Paths |
|---|---|---|
| Official zip/tar.gz (recommended) | Learning, full control, matches docs | You pick (e.g. C:\apache-tomcat-10.1.x, /opt/tomcat) |
OS package (apt, dnf, Homebrew) | Quick system service | Distro-specific (/usr/share/tomcat*, /etc/tomcat*) |
| Docker | Isolated experiments, CI | /usr/local/tomcat/ inside container |
Examples below use the official binary unless noted. Package paths differ—always run catalina.sh version or check your distro docs after install.
Download Tomcat 10.1
- Open Apache Tomcat 10 downloads
- Under Core, download:
- Windows:
64-bit Windows zip(e.g.apache-tomcat-10.1.xx-windows-x64.zip) - macOS / Linux:
tar.gz(e.g.apache-tomcat-10.1.xx.tar.gz)
- Windows:
Verify the archive checksum on the download page when you want extra assurance (optional for local learning).
Install on Windows
- Unzip to a short path without spaces or non-ASCII characters, for example:
C:\apache-tomcat-10.1.34- Optional but recommended—set environment variables (System Properties → Environment Variables):
| Variable | Example value |
|---|---|
JAVA_HOME | C:\Program Files\Eclipse Adoptium\jdk-21.x.x |
CATALINA_HOME | C:\apache-tomcat-10.1.34 |
- Do not add Tomcat
bintoPATHuntil you are comfortable—use full paths orcdintobinfirst.
Start Tomcat from PowerShell or CMD:
cd C:\apache-tomcat-10.1.34\bin
startup.batStop:
shutdown.batCode explanation:
startup.batlaunches Tomcat in a separate console window by default- A new window shows log lines ending with Server startup in … ms
- Default HTTP port is 8080
Tip
Run in Foreground for Learning
Use catalina.bat run in bin/ to keep logs in the current terminal—easier for debugging. Covered in more detail in Start, Stop, and Environment.
Install on macOS
Option A: Official tar.gz (recommended)
cd ~/tools
curl -O https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.34/bin/apache-tomcat-10.1.34.tar.gz
tar xzf apache-tomcat-10.1.34.tar.gz
export CATALINA_HOME=$HOME/tools/apache-tomcat-10.1.34
export JAVA_HOME=$(/usr/libexec/java_home -v 21)Add to ~/.zshrc or ~/.bash_profile:
export JAVA_HOME=$(/usr/libexec/java_home -v 21)
export CATALINA_HOME=$HOME/tools/apache-tomcat-10.1.34Start and stop:
$CATALINA_HOME/bin/startup.sh
$CATALINA_HOME/bin/shutdown.shOption B: Homebrew
brew install tomcat
brew services start tomcatCode explanation:
- Homebrew installs to a cellar path and may use different layout than the official zip
- For tutorials that reference
CATALINA_HOME/webapps/, prefer Option A unless you map Brew paths deliberately
Install on Linux (Ubuntu / Debian)
Option A: Official tar.gz under /opt (recommended)
sudo mkdir -p /opt
cd /tmp
curl -O https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.34/bin/apache-tomcat-10.1.34.tar.gz
sudo tar xzf apache-tomcat-10.1.34.tar.gz -C /opt
sudo ln -s /opt/apache-tomcat-10.1.34 /opt/tomcatCreate a dedicated user (production habit; good practice even when learning):
sudo useradd -r -m -U -d /opt/tomcat -s /bin/false tomcat || true
sudo chown -R tomcat:tomcat /opt/apache-tomcat-10.1.34Run as your own user for local learning (skip chown if only you use the machine):
export CATALINA_HOME=/opt/tomcat
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 # adjust if needed
/opt/tomcat/bin/startup.shOption B: APT package
sudo apt update
sudo apt install -y tomcat10 tomcat10-admin
sudo systemctl enable tomcat10
sudo systemctl start tomcat10Typical paths on Debian/Ubuntu:
| Path | Purpose |
|---|---|
/usr/share/tomcat10/ | Installation root (often CATALINA_HOME) |
/etc/tomcat10/ | Config overlays |
/var/lib/tomcat10/webapps/ | Deployed applications |
/var/log/tomcat10/ | Logs |
Code explanation:
- Package layout splits config and webapps from the upstream tar.gz tree
- Official
/opt/tomcatexamples in later chapters map cleanly to Option A
On Rocky / Alma / Fedora:
sudo dnf install -y tomcat tomcat-webapps
sudo systemctl enable --now tomcatInstall with Docker (optional)
Quick smoke test without touching the host filesystem:
docker run -d --name tomcat -p 8080:8080 tomcat:10.1-jdk21
curl -I http://127.0.0.1:8080/Code explanation:
tomcat:10.1-jdk21— Tomcat 10.1 with JDK 21 inside the image-p 8080:8080— maps container port 8080 to your host- WAR deploy and config mounts are covered in Tomcat and Docker
Stop and remove:
docker stop tomcat && docker rm tomcatVerify Tomcat Is Running
HTTP check
curl -I http://127.0.0.1:8080/Expected: HTTP/1.1 200 and a Server: Apache-Coyote/1.1 or similar header.
Fetch the page title:
curl -s http://127.0.0.1:8080/ | head -5You should see Apache Tomcat welcome HTML.
Browser
Open:
http://127.0.0.1:8080/
http://localhost:8080/On a remote VPS, use the public IP only if port 8080 is open in the firewall—production usually keeps Tomcat on localhost and uses Nginx on 80/443.
Version command
From bin/:
./catalina.sh version # Linux/macOS
catalina.bat version # WindowsShows Tomcat version, JVM version, and JAVA_HOME Tomcat detected.
Quick Directory Map (Official Install)
After unzipping, your tree looks like this:
apache-tomcat-10.1.x/
├── bin/ startup.sh, shutdown.sh, catalina.sh
├── conf/ server.xml, web.xml, tomcat-users.xml
├── lib/ Tomcat-wide JARs
├── logs/ catalina.*.log, localhost.*.log
├── webapps/ Deploy WARs here (default)
├── work/ JSP compile cache (auto-created)
├── temp/ Temporary files
└── RUNNING.txt Quick start notes from Apache| Path | Purpose |
|---|---|
bin/ | Start/stop scripts and launchers |
conf/ | Main configuration—backup before editing |
webapps/ | Each folder or .war becomes a web application |
logs/ | First place to look when startup fails |
Tip
Backup Before Editing conf/
cp conf/server.xml conf/server.xml.bakFull explanation of CATALINA_HOME, CATALINA_BASE, and each subdirectory is in Tomcat Directory Layout.
First Start / Stop Checklist
| Step | Command (Linux/macOS) |
|---|---|
| Start | $CATALINA_HOME/bin/startup.sh |
| Verify | curl -I http://127.0.0.1:8080/ |
| Stop | $CATALINA_HOME/bin/shutdown.sh |
| Confirm stopped | curl -I http://127.0.0.1:8080/ should fail to connect |
If shutdown hangs, something may still hold port 8080—check logs under logs/ and see Common Install Problems below.
Common Install Problems
| Symptom | Likely cause | Fix |
|---|---|---|
JAVA_HOME / JRE not found | JDK not installed or env var unset | Install JDK 17+; set JAVA_HOME; reopen terminal |
Address already in use (8080) | Another Tomcat, Spring Boot, or app on 8080 | ss -tlnp | grep 8080 (Linux) or netstat -ano | findstr 8080 (Windows); stop conflict or change port in conf/server.xml |
| Blank page / connection refused | Tomcat not started or wrong port | Check logs/catalina*.log; run catalina.sh run for console errors |
Permission denied on Linux | Running as wrong user after chown tomcat | Start as tomcat user or fix ownership for your learning account |
| Garbled path on Windows | Unzipped under folder with Chinese/spaces | Move to C:\apache-tomcat-10.1.x |
| Tomcat 10 + old WAR fails | App still uses javax.servlet | Use Tomcat 9 for legacy, or migrate app to Jakarta |
| Docker 8080 in use | Host service already on 8080 | docker run -p 8081:8080 ... and open port 8081 |
Peek at logs when startup fails
tail -50 logs/catalina.out # if present
tail -50 logs/catalina.$(date +%Y-%m-%d).logWindows: open the newest catalina.*.log under logs\ in a text editor.
Post-Install Checklist
-
java -versionshows 17 or 21 - Tomcat 10.1.x extracted or package installed
-
CATALINA_HOMEpoints at install root (official zip method) -
startupsucceeds; browser orcurlreturns 200 on port 8080 - You know where
webapps/,conf/, andlogs/live -
shutdownstops the server cleanly
What Comes Next
| Chapter | Topic |
|---|---|
| 03 — Directory layout | Every folder, env vars, package vs zip paths |
| 04 — Start, stop, environment | catalina.sh run, systemd, Windows service |
| 07 — Deploying WAR | Replace the default apps with your WAR |
FAQ
Do I need to install Tomcat if Spring Boot already runs on 8080?
For embedded Boot development, no. Install standalone Tomcat when you practice WAR deploy, shared servers, or ops tasks this track teaches.
Tomcat vs JDK—which install first?
Always JDK first. Tomcat is not a substitute for Java.
Can I run two Tomcat versions side by side?
Yes—use different install directories and different HTTP ports in each conf/server.xml. Only one process can bind to 8080.
Should I delete the default webapps (docs, examples)?
Not required for learning. Before production, remove sample apps and lock down Manager—see Tomcat Security Basics.
Official zip vs OS package—which should I use?
Use the official zip/tar.gz if you follow Hello Code paths literally. Use packages if your team standardizes on systemctl start tomcat10 and distro paths.
Why port 8080 and not 80?
Binding to port 80 on Linux requires root (or capabilities). Nginx on 80 proxying to Tomcat on 8080 is the usual production pattern.
WSL2 on Windows?
Install JDK and Tomcat inside WSL (Linux steps). Browse from Windows at http://127.0.0.1:8080/—same as other WSL services.