Skip to main content
Advertisement

server.xml Structure Analysis

server.xml is Tomcat's core configuration file that defines the entire server component hierarchy. Understanding this file gives you full control over ports, virtual hosts, and application contexts.


Overall Hierarchy

server.xml uses an XML tree structure to express Tomcat's component layers.

<Server>                          <!-- Top level: one JVM process -->
<Service> <!-- Group of connectors + engine -->
<Connector port="8080" .../> <!-- Request receiving port -->
<Connector port="8009" .../> <!-- AJP port (optional) -->
<Engine name="Catalina"> <!-- Request processing engine -->
<Host name="localhost"> <!-- Virtual host -->
<Context path="/" /> <!-- Web application -->
</Host>
</Engine>
</Service>
</Server>

Component Roles

ComponentRoleKey Attributes
ServerRepresents the entire JVM instanceport (shutdown command port), shutdown
ServiceCollection of connectors + enginename
ConnectorReceives network requests (HTTP/AJP)port, protocol, maxThreads
EngineRoutes requests to Hostsname, defaultHost
HostVirtual host (domain-based routing)name, appBase
ContextWeb application path mappingpath, docBase

Server Element

<Server port="8005" shutdown="SHUTDOWN">
AttributeDescriptionDefault
portPort for receiving shutdown commands8005
shutdownShutdown command stringSHUTDOWN

Security recommendation: Setting port="-1" disables the shutdown port — useful to prevent remote shutdown command vulnerabilities.

<!-- Disable shutdown port (production recommended) -->
<Server port="-1" shutdown="SHUTDOWN">

Service Element

<Service name="Catalina">
<!-- Connectors and Engine are nested here -->
</Service>

Multiple Services can be registered inside one Server, but typically a single "Catalina" Service is used.


Engine Element

<Engine name="Catalina" defaultHost="localhost">
AttributeDescription
nameEngine identifier (used in logs)
defaultHostDefault host when no Host matches
jvmRouteSticky Session identifier in load-balanced clusters
<!-- jvmRoute for cluster environments -->
<Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">

Host Element

<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
AttributeDescriptionDefault
nameVirtual host name (domain matching)
appBaseBase directory for applicationswebapps
unpackWARsAuto-extract WAR filestrue
autoDeployAuto-deploy WARs at runtimetrue
deployOnStartupAuto-scan appBase on startuptrue

Multiple Virtual Hosts

<Engine name="Catalina" defaultHost="localhost">

<!-- Default host -->
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs" prefix="localhost_access_log"
suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b"/>
</Host>

<!-- Additional virtual host -->
<Host name="api.example.com" appBase="/var/www/api"
unpackWARs="true" autoDeploy="false">
<Alias>api2.example.com</Alias>
</Host>

<Host name="admin.example.com" appBase="/var/www/admin"
unpackWARs="true" autoDeploy="false">
</Host>

</Engine>

Context Element

Context maps a specific web application to a URL path. It's recommended to use separate conf/Catalina/localhost/appname.xml files rather than embedding Context directly in server.xml.

<!-- Directly in server.xml (not recommended) -->
<Context path="/myapp" docBase="/var/www/myapp" reloadable="true"/>

<!-- Recommended: conf/Catalina/localhost/myapp.xml -->
<!-- conf/Catalina/localhost/myapp.xml -->
<Context docBase="/var/www/myapp"
path="/myapp"
reloadable="false"
crossContext="false">

<!-- JNDI DataSource -->
<Resource name="jdbc/myDB"
auth="Container"
type="javax.sql.DataSource"
maxTotal="100"
maxIdle="30"
maxWaitMillis="10000"
username="dbuser"
password="dbpass"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/mydb?useSSL=false"/>
</Context>
AttributeDescriptionDefault
pathURL context path"" (ROOT)
docBaseActual file path
reloadableAuto-reload on class changesfalse
crossContextAllow access from other contextsfalse

Production warning: Use reloadable="true" only in development. It causes performance degradation in production.


GlobalNamingResources

Defines global JNDI resources (data sources, mail sessions, etc.).

<GlobalNamingResources>
<!-- User authentication DB (built-in) -->
<Resource name="UserDatabase"
auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml"/>

<!-- Global JDBC DataSource -->
<Resource name="jdbc/globalDB"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://db-host:3306/mydb"
username="appuser"
password="secret"
maxTotal="50"
maxIdle="10"/>
</GlobalNamingResources>

Production server.xml Example

<?xml version="1.0" encoding="UTF-8"?>
<Server port="-1" shutdown="SHUTDOWN">

<Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>

<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml"/>
</GlobalNamingResources>

<Service name="Catalina">

<!-- HTTP/1.1 Connector -->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="200"
minSpareThreads="10"
acceptCount="100"
enableLookups="false"
compression="on"
compressionMinSize="2048"
compressibleMimeType="text/html,text/xml,text/plain,text/css,application/json"/>

<Engine name="Catalina" defaultHost="localhost">

<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>

<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="false">

<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="localhost_access_log"
suffix=".txt"
pattern="%h %l %u %t &quot;%r&quot; %s %b %D"/>

<Valve className="org.apache.catalina.valves.ErrorReportValve"
showReport="false"
showServerInfo="false"/>

</Host>
</Engine>
</Service>
</Server>

Summary

ComponentKey SettingNotes
Serverport="-1" (security)Disable shutdown port in production
HostautoDeploy="false"Disable auto-deploy in production
ContextSeparate XML file recommendedreloadable="false" in production
EnginejvmRouteRequired for cluster Sticky Sessions
RealmWrap in LockOutRealmProtects against brute-force attacks
Advertisement