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

Where server.xml Fits

text
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 users

Always backup before editing:

bash
cp conf/server.xml conf/server.xml.bak

Configuration Hierarchy

Tomcat container config is a tree of nested elements:

text
Server (shutdown port)
└── Service (named "Catalina")
    ├── Connector(s)     ← HTTP, HTTPS, AJP
    └── Engine
        └── Host(s)      ← virtual hosts
            └── Context(s)  ← web apps (often auto from webapps/)
ElementRole
<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> in server.xml—apps appear automatically from webapps/

Compare to Nginx:

text
Nginx server { }     ≈  Tomcat Host
Nginx location { }   ≈  Servlet mapping / Context path
Nginx listen 80      ≈  Connector port

Default 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 by shutdown.sh, not browsers
  • <Connector port="8080"> — HTTP port you curl and browsers use
  • <Host appBase="webapps"> — WARs and folders under webapps/ deploy here
  • autoDeploy="true" — Tomcat picks up new/changed WARs without editing XML

Open your live file:

bash
less conf/server.xml

The Server Element and Shutdown Port

xml
<Server port="8005" shutdown="SHUTDOWN">
AttributeMeaning
portShutdown socket port (default 8005)
shutdownString 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 shutdown from the default is a minor hardening step—update ops docs if you do

Connectors

HTTP Connector (default)

xml
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           maxThreads="200" />
AttributePurpose
portHTTP listen port
protocolHTTP/1.1 uses Tomcat’s NIO HTTP implementation (modern default)
connectionTimeoutMs to wait for request line/headers (20000 = 20s)
redirectPortPort used when a web app asks for HTTPS redirect (8443 if SSL Connector exists)
maxThreadsUpper bound on worker threads handling requests

Change HTTP port

When 8080 conflicts with Spring Boot or another Tomcat:

xml
<Connector port="8081" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           maxThreads="200" />

Restart, then verify:

bash
curl -I http://127.0.0.1:8081/

Bind to localhost (production pattern)

When Nginx terminates TLS and proxies to Tomcat:

xml
<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:

xml
<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:

xml
<!--
<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.xml often 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:

xml
<!-- Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->

Leave AJP disabled unless you maintain a legacy integration.

Engine and Host

xml
<Engine name="Catalina" defaultHost="localhost">
  <Host name="localhost" appBase="webapps"
        unpackWARs="true" autoDeploy="true">
  </Host>
</Engine>
AttributeOnMeaning
defaultHostEngineHost used when request hostname does not match any <Host name="…">
nameHostVirtual host name—must match Host HTTP header for vhost routing
appBaseHostDirectory relative to CATALINA_BASE (usually webapps)
unpackWARsHostIf true, expand WAR files into directories at deploy time
autoDeployHostIf true, watch appBase for new/updated apps

Development vs production

SettingDevelopmentProduction
autoDeploytrue — convenientOften false — controlled deploy via scripts/CI
unpackWARstrue — easier inspectiontrue or false per ops policy
Deploy methodDrop 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:

xml
<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/ alongside webapps/
  • DNS for api.example.com must point to this server (or Nginx server_name proxies with correct Host header)

Full multi-domain + Nginx patterns appear in Nginx + Tomcat.

Context: Inline vs Files vs Auto Deploy

Three ways to define a Context:

MethodLocationWhen
Autowebapps/myapp.warDefault learning path
Fragment fileconf/Catalina/localhost/myapp.xmlExternal docBase, fixed path
Inline in server.xmlInside <Host>Possible but discouraged—harder to maintain

Example fragment (preview—details in deploy chapter):

xml
<!-- conf/Catalina/localhost/hello.xml -->
<Context docBase="/opt/apps/hello.war" path="/hello" />

Code explanation:

  • docBase — WAR or directory on disk (can be outside webapps/)
  • path — URL context path (/hello)
  • Prefer fragment files over editing server.xml for 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

  1. Stop Tomcat (or plan a maintenance window)
  2. Backup conf/server.xml
  3. Edit with a sane editor (VS Code, vim—not Word)
  4. Validate XML well-formedness (matching tags)—Tomcat has no separate nginx -t equivalent
  5. Start with catalina.sh run first to see errors on the console
  6. Once stable, use startup.sh or systemctl restart tomcat

Syntax error symptom:

text
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 /myapp comes from deployment, not from the Connector alone

Common Edits Cheat Sheet

GoalEdit
Change HTTP port<Connector port="…">
Localhost onlyaddress="127.0.0.1" on Connector
UTF-8 pathsURIEncoding="UTF-8" on Connector
Disable hot deployautoDeploy="false" on Host
More threads (basic)maxThreads="400" — see JVM and Connector tuning for real sizing

Relationship to Other Config Files

FileScope
server.xmlPorts, hosts, container skeleton
web.xmlDefault servlet mappings, session timeout for all apps
context.xmlDefault resources (e.g. JNDI) per Context
WEB-INF/web.xmlSingle 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.