server.xml and Connectors
Introduction
conf/server.xml is the main Tomcat configuration file. It defines which ports Tomcat listens on, how requests flow through Engine and Host components, and where applications are deployed from. This chapter maps the XML hierarchy, explains the default HTTP Connector, and shows safe edits—backup, change port, bind to localhost—that you will use before deploying WARs or putting Nginx in front.
Prerequisites
- Tomcat Directory Layout
- Start, Stop, and Environment — restart Tomcat after edits
- Tomcat stopped or ready for restart; backup habit established
Where server.xml Fits
conf/
├── server.xml ← Connectors, Engine, Host (this chapter)
├── web.xml ← global defaults for all apps (next chapter pair)
├── context.xml ← default Context settings
└── tomcat-users.xml ← Manager usersAlways backup before editing:
cp conf/server.xml conf/server.xml.bakConfiguration Hierarchy
Tomcat container config is a tree of nested elements:
Server (shutdown port)
└── Service (named "Catalina")
├── Connector(s) ← HTTP, HTTPS, AJP
└── Engine
└── Host(s) ← virtual hosts
└── Context(s) ← web apps (often auto from webapps/)| Element | Role |
|---|---|
<Server> | Top-level; shutdown port and global listeners |
<Service> | Groups one Engine with its Connectors |
<Connector> | Accepts client connections (HTTP on 8080) |
<Engine> | Request pipeline; routes to the correct Host |
<Host> | Virtual host name + appBase directory |
<Context> | One web application (path, docBase, reload settings) |
Code explanation:
- Connectors face the network; Engine/Host decide which app handles the URL
- Many installs never add a
<Context>inserver.xml—apps appear automatically fromwebapps/
Compare to Nginx:
Nginx server { } ≈ Tomcat Host
Nginx location { } ≈ Servlet mapping / Context path
Nginx listen 80 ≈ Connector portDefault server.xml (Tomcat 10.1 — Simplified)
Below is a reduced view of the stock file—your exact copy may include extra comments and optional blocks:
Code explanation:
<Server port="8005">— used byshutdown.sh, not browsers<Connector port="8080">— HTTP port you curl and browsers use<Host appBase="webapps">— WARs and folders underwebapps/deploy hereautoDeploy="true"— Tomcat picks up new/changed WARs without editing XML
Open your live file:
less conf/server.xmlThe Server Element and Shutdown Port
<Server port="8005" shutdown="SHUTDOWN">| Attribute | Meaning |
|---|---|
port | Shutdown socket port (default 8005) |
shutdown | String shutdown.sh must send to trigger stop |
Code explanation:
- This port must be free and reachable from localhost for graceful shutdown
- Do not expose 8005 to the public internet
- Changing
shutdownfrom the default is a minor hardening step—update ops docs if you do
Connectors
HTTP Connector (default)
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="200" />| Attribute | Purpose |
|---|---|
port | HTTP listen port |
protocol | HTTP/1.1 uses Tomcat’s NIO HTTP implementation (modern default) |
connectionTimeout | Ms to wait for request line/headers (20000 = 20s) |
redirectPort | Port used when a web app asks for HTTPS redirect (8443 if SSL Connector exists) |
maxThreads | Upper bound on worker threads handling requests |
Change HTTP port
When 8080 conflicts with Spring Boot or another Tomcat:
<Connector port="8081" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="200" />Restart, then verify:
curl -I http://127.0.0.1:8081/Bind to localhost (production pattern)
When Nginx terminates TLS and proxies to Tomcat:
<Connector port="8080" protocol="HTTP/1.1"
address="127.0.0.1"
connectionTimeout="20000"
redirectPort="8443" />Code explanation:
address="127.0.0.1"— Tomcat accepts connections only from the same machine- Nginx on the same VPS forwards to
http://127.0.0.1:8080 - Pair with firewall rules blocking 8080 from the public network
URI encoding (UTF-8)
For paths or query strings with non-ASCII characters, add:
<Connector port="8080" protocol="HTTP/1.1"
URIEncoding="UTF-8"
connectionTimeout="20000"
redirectPort="8443" />Also set request/response encoding in your app or a Filter—Connector alone is not the whole story.
HTTPS Connector (awareness)
Tomcat can terminate SSL directly:
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
certificateKeystorePassword="changeit" />
</SSLHostConfig>
</Connector>
-->Code explanation:
- Default
server.xmloften ships HTTPS commented out - Many teams prefer Nginx + Let's Encrypt on 443 and HTTP to Tomcat on localhost—simpler certificate renewal
Deep SSL on Tomcat is optional; this track emphasizes Nginx in front.
AJP Connector (legacy awareness)
Older stacks used AJP between Apache httpd and Tomcat. Modern Hello Code deploys use HTTP reverse proxy (proxy_pass) instead. You may see:
<!-- Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->Leave AJP disabled unless you maintain a legacy integration.
Engine and Host
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
</Host>
</Engine>| Attribute | On | Meaning |
|---|---|---|
defaultHost | Engine | Host used when request hostname does not match any <Host name="…"> |
name | Host | Virtual host name—must match Host HTTP header for vhost routing |
appBase | Host | Directory relative to CATALINA_BASE (usually webapps) |
unpackWARs | Host | If true, expand WAR files into directories at deploy time |
autoDeploy | Host | If true, watch appBase for new/updated apps |
Development vs production
| Setting | Development | Production |
|---|---|---|
autoDeploy | true — convenient | Often false — controlled deploy via scripts/CI |
unpackWARs | true — easier inspection | true or false per ops policy |
| Deploy method | Drop WAR in webapps/ | External docBase, CI pipeline, no hot-drop |
Warning
autoDeploy on Production
Auto-deploy can restart apps when files change unexpectedly—risky under load. Prefer explicit deploy procedures in Deploying WAR and webapps.
Multiple virtual hosts (preview)
Two Host blocks serve different hostnames on the same Tomcat:
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps" />
<Host name="api.example.com" appBase="webapps-api"
unpackWARs="true" autoDeploy="true" />
</Engine>Code explanation:
- Create
webapps-api/alongsidewebapps/ - DNS for
api.example.commust point to this server (or Nginxserver_nameproxies with correctHostheader)
Full multi-domain + Nginx patterns appear in Nginx + Tomcat.
Context: Inline vs Files vs Auto Deploy
Three ways to define a Context:
| Method | Location | When |
|---|---|---|
| Auto | webapps/myapp.war | Default learning path |
| Fragment file | conf/Catalina/localhost/myapp.xml | External docBase, fixed path |
| Inline in server.xml | Inside <Host> | Possible but discouraged—harder to maintain |
Example fragment (preview—details in deploy chapter):
<!-- conf/Catalina/localhost/hello.xml -->
<Context docBase="/opt/apps/hello.war" path="/hello" />Code explanation:
docBase— WAR or directory on disk (can be outsidewebapps/)path— URL context path (/hello)- Prefer fragment files over editing
server.xmlfor each app
Listeners on Server
Default server.xml registers several <Listener className="…"> entries—lifecycle hooks for version logging, APR/native SSL, leak prevention, JMX.
Code explanation:
- Beginners rarely touch Listeners
- Do not remove listeners unless Apache documentation for your version says so
- Mis-deleting listeners can cause subtle startup failures
Edit Workflow
- Stop Tomcat (or plan a maintenance window)
- Backup
conf/server.xml - Edit with a sane editor (VS Code, vim—not Word)
- Validate XML well-formedness (matching tags)—Tomcat has no separate
nginx -tequivalent - Start with
catalina.sh runfirst to see errors on the console - Once stable, use
startup.shorsystemctl restart tomcat
Syntax error symptom:
org.xml.sax.SAXParseException; … Element type "Connector" must be followed by …Fix the reported line in server.xml, restore from .bak if needed.
Request Flow (Putting It Together)
Code explanation:
- Connector knows nothing about your business logic—it passes to the Container pipeline
- Context path
/myappcomes from deployment, not from the Connector alone
Common Edits Cheat Sheet
| Goal | Edit |
|---|---|
| Change HTTP port | <Connector port="…"> |
| Localhost only | address="127.0.0.1" on Connector |
| UTF-8 paths | URIEncoding="UTF-8" on Connector |
| Disable hot deploy | autoDeploy="false" on Host |
| More threads (basic) | maxThreads="400" — see JVM and Connector tuning for real sizing |
Relationship to Other Config Files
| File | Scope |
|---|---|
server.xml | Ports, hosts, container skeleton |
web.xml | Default servlet mappings, session timeout for all apps |
context.xml | Default resources (e.g. JNDI) per Context |
WEB-INF/web.xml | Single application |
Next: web.xml and context.
Post-Chapter Checklist
- You can draw Server → Service → Connector → Engine → Host → Context
- You know default ports 8080 (HTTP) and 8005 (shutdown)
- You changed a setting only after backup and restart
- You understand
appBase,autoDeploy,unpackWARs
FAQ
Does server.xml hot-reload?
No for most changes—restart Tomcat. Some commercial managers exist; open-source Tomcat expects restart for Connector/Host edits.
One Connector or many?
One HTTP Connector on 8080 is enough for learning. Separate Connectors for HTTPS (8443) or AJP (8009) when needed.
maxThreads vs JVM heap?
maxThreads caps concurrent request workers; heap (-Xmx) caps memory for the whole JVM. Both matter; chapter 13 goes deeper.
Can I delete commented blocks in server.xml?
Keep backups. Removing unused SSL/AJP blocks simplifies reading—ensure you do not delete required Listeners or the active HTTP Connector.
Host name must match domain?
For virtual hosting, <Host name="api.example.com"> must match the Host header on incoming requests (or Nginx must send that header via proxy_set_header Host).
Where is Context path set?
Usually from the WAR file name or conf/Catalina/localhost/*.xml, not from the HTTP Connector port.
Package Tomcat: which server.xml?
Debian/Ubuntu often use /etc/tomcat10/server.xml—edit that file for package installs, not only the copy under /usr/share.