tomcat Apache Tomcat

Overview

Apache Tomcat is a free and open-source implementation of the Java Servlet, JavaServer Pages, Java Expression Language and WebSocket technologies. Tomcat provides a “pure Java” HTTP web server environment in which Java code can run.

Description

Architecture

../_images/Tomcat-Architechture.webp

Note

  • A Server represents the whole container.

  • A Service is an intermediate component which lives inside a Server and ties one or more Connectors to exactly one Engine.

  • A Connector handles communications with the client.

  • An Engine represents request processing pipeline for a specific Service.

  • A Host is an association of a network name to the Tomcat server.

  • A Context represents a web application.

Configuration Files

$CATALINA_HOME/conf

catalina.policy :
The configuration file for security decisions.
This file is only used if you invoke Tomcat with the -security option.
catalina.properties :
The standard Java properties file for the Catalina class.
logging.properties :
This file configures the way that Catalina’s built-in logging functions, including things such as threshold and log location.
context.xml :
The default context settings that are applied to all deployed contexts of all hosts in this installation of Tomcat.
server.xml :
The main Tomcat configuration file.
tomcat-users.xml
The default list of roles, users, and passwords used by Tomcat’s UserDatabaseRealm for authentication.
web.xml :
This file configures options and values that will be applied to all applications loaded into a given instance of Tomcat.

Default Webapps

ROOT :
The ROOT web application is the default page shown to users.
The ROOT web application should normally be removed from a publicly accessible Tomcat instance.
Documentation :
It should normally be removed from a publicly accessible Tomcat instance.
Examples :
The examples web application should always be removed from any security sensitive installation.
Manager :
The Manager application allows the remote deployment of web applications.
Host Manager :
The Host Manager application allows the creation and management of virtual hosts.

Warning

Applications that are not required should be removed so the system will not be at risk if a vulnerability is discovered.

Directory

/bin :
This directory contains the startup and shutdown scripts for both Windows and Linux.
/conf :
This directory contains the main configuration files for Tomcat.
The two most important are the server.xml and the global web.xml.
/server :
This directory contains the Tomcat Java Archive files.
/lib :
This directory contains Java Archive files that Tomcat is dependent upon.
/logs :
This directory contains Tomcat’s log files.
/src :
This directory contains the source code used by the Tomcat server.
Once Tomcat is released, it will probably contain interfaces and abstract classes only.
/webapps :
All web applications are deployed in this directory; it contains the WAR file.
/work :
This is the directory in which Tomcat will place all servlets that are generated from JSPs.
If you want to see exactly how a particular JSP is interpreted, look in this directory.

Ports

Connector Port :
This is the port where Apache Tomcat listen for the HTTP requests.
Shutdown Port :
This port is used when we try to shutdown the Apache Tomcat Server.
AJP (Apache JServ Protocol) Connector Port :
The Apache JServ Protocol (AJP) is a binary protocol that can conduct inbound requests
from a web server through to an application server that sits behind the web server.
Redirect Port :
Any redirection happening inside Apache Tomcat will happen through this port.
In Apache TOMCAT there are two instance where redirect Port is mentioned.
First one is for the Apache TOMCAT server and other one is for the AJP port.

Properties

CATALINA_HOME :
Represents the root of your Tomcat installation.
CATALINA_BASE :
Represents the root of a runtime configuration of a specific Tomcat instance.
JAVA_OPTS :
This variable is used to set various Java Virtual Machine options.
CATALINA_OPTS :
This variable is used to set various Tomcat-specific options.

Multiple Instances with Systemd Template

Downloading

apt install default-jdk
mkdir /usr/local/tomcat
wget https://archive.apache.org/dist/tomcat/tomcat-10/v10.0.6/bin/apache-tomcat-10.0.6.tar.gz
tar xvzf apache-tomcat-10.0.6.tar.gz -C /usr/local/tomcat
cd /usr/local/tomcat

Creating two instances

for i in 1 2;do cp -rp apache-tomcat-10.0.6/ tomcat${i}; done
rm -rf tomcat{1,2}/{bin,lib,*.txt,*.md}
rm -rf tomcat{1,2}/{LICENSE,NOTICE,RELEASE-NOTES}
rm -rf apache-tomcat-10.0.6/{conf,logs,temp,webapps,work}
mv tomcat{1,2} apache-tomcat-10.0.6/
ln -s apache-tomcat-10.0.6/ current

Creating tomcat user

useradd -r -U -d /usr/local/tomcat -M -s /bin/false tomcat
chown -R tomcat: /usr/local/tomcat/current/

Updating server.xml

current/tomcat1/conf/server.xml

<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <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">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <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="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>
    </Engine>
  </Service>
</Server>

Tip

To remove the blank and commented lines from an xml file :

sed '/<!--/,/-->/d;/^$/d' current/tomcat1/conf/server.xml
diff -u current/tomcat{1,2}/conf/server.xml
--- current/tomcat1/conf/server.xml     2021-05-08 17:24:15.000000000 +0200
+++ current/tomcat2/conf/server.xml     2021-06-05 18:45:53.857036987 +0200
@@ -19,7 +19,7 @@
      define subcomponents such as "Valves" at this level.
      Documentation at /docs/config/server.html
  -->
-<Server port="8005" shutdown="SHUTDOWN">
+<Server port="8006" shutdown="SHUTDOWN">
   <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
   <!-- Security listener. Documentation at /docs/config/listeners.html
   <Listener className="org.apache.catalina.security.SecurityListener" />
@@ -65,9 +65,9 @@
          AJP  Connector: /docs/config/ajp.html
          Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
     -->
-    <Connector port="8080" protocol="HTTP/1.1"
+    <Connector port="8081" protocol="HTTP/1.1"
                connectionTimeout="20000"
-               redirectPort="8443" />
+               redirectPort="8444" />
     <!-- A "Connector" using the shared thread pool-->
     <!--
     <Connector executor="tomcatThreadPool"

Creating a systemd template

/etc/systemd/system/tomcat@.service

[Unit]
Description=Tomcat - instance %i
After=syslog.target network.target

[Service]
Type=forking
User=tomcat
Group=tomcat
WorkingDirectory=/usr/local/tomcat/current/%i
Environment="JAVA_HOME=/usr/lib/jvm/java-1.11.0-openjdk-amd64"
Environment="JAVA_OPTS=-Djava.security.egd=file:///dev/urandom"
Environment="CATALINA_PID=/usr/local/tomcat/current/%i.pid"
Environment="CATALINA_BASE=/usr/local/tomcat/current/%i"
Environment="CATALINA_HOME=/usr/local/tomcat/current"
EnvironmentFile=/usr/local/tomcat/current/.%i
ReadWritePaths=/usr/local/tomcat/
ExecStart=/usr/local/tomcat/current/bin/startup.sh -security
ExecStop=/usr/local/tomcat/current/bin/shutdown.sh
RestartSec=10
Restart=on-abort

[Install]
WantedBy=multi-user.target

/usr/local/tomcat/current/.tomcat1

CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC

/usr/local/tomcat/current/.tomcat2

CATALINA_OPTS=-Xms1024M -Xmx2048M -server -XX:+UseParallelGC
systemctl daemon-reload
systemctl start tomcat@tomcat{1,2}.service

Directory in tree-like format

/usr/local/tomcat/
├── [drwxr-xr-x tomcat   tomcat  ]  apache-tomcat-10.0.6
│   ├── [drwxr-x--- tomcat   tomcat  ]  bin
│   ├── [-rw-r----- tomcat   tomcat  ]  BUILDING.txt
│   ├── [-rw-r----- tomcat   tomcat  ]  CONTRIBUTING.md
│   ├── [drwxr-x--- tomcat   tomcat  ]  lib
│   ├── [-rw-r----- tomcat   tomcat  ]  LICENSE
│   ├── [-rw-r----- tomcat   tomcat  ]  NOTICE
│   ├── [-rw-r----- tomcat   tomcat  ]  README.md
│   ├── [-rw-r----- tomcat   tomcat  ]  RELEASE-NOTES
│   ├── [-rw-r----- tomcat   tomcat  ]  RUNNING.txt
│   ├── [-rw-r----- tomcat   tomcat  ]  .tomcat1
│   ├── [drwxr-x--- tomcat   tomcat  ]  tomcat1
│   │   ├── [drwx------ tomcat   tomcat  ]  conf
│   │   ├── [drwxr-x--- tomcat   tomcat  ]  logs
│   │   ├── [drwxr-x--- tomcat   tomcat  ]  temp
│   │   ├── [drwxr-x--- tomcat   tomcat  ]  webapps
│   │   └── [drwxr-x--- tomcat   tomcat  ]  work
│   ├── [-rw-r----- tomcat   tomcat  ]  tomcat1.pid
│   ├── [-rw-r----- tomcat   tomcat  ]  .tomcat2
│   ├── [drwxr-x--- tomcat   tomcat  ]  tomcat2
│   │   ├── [drwx------ tomcat   tomcat  ]  conf
│   │   ├── [drwxr-x--- tomcat   tomcat  ]  logs
│   │   ├── [drwxr-x--- tomcat   tomcat  ]  temp
│   │   ├── [drwxr-x--- tomcat   tomcat  ]  webapps
│   │   └── [drwxr-x--- tomcat   tomcat  ]  work
│   └── [-rw-r----- tomcat   tomcat  ]  tomcat2.pid
└── [lrwxrwxrwx root     root    ]  current -> apache-tomcat-10.0.6/

Checking the instances

pgrep -u tomcat -a
ps -L -C java -o pid,tid,pcpu,pmem,comm
awk '/java/' <(netstat -tupane)

Securing Management Applications

current/tomcat2/webapps/host-manager/META-INF/context.xml current/tomcat2/webapps/manager/META-INF/context.xml

<Valve className="org.apache.catalina.valves.RemoteAddrValve"
       allow="192\.168\.122\.\d+|127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />

current/tomcat2/conf/tomcat-users.xml

<role rolename="admin-gui"/>
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<user username="guisam" password="turlututu" roles="admin-gui,manager-gui,manager-script"/>

Note

manager-gui
Access to the HTML interface.
manager-status
Access to the “Server Status” page only.
manager-script
Access to the tools-friendly plain text interface and to the “Server Status” page.
manager-jmx
Access to JMX proxy interface and to the “Server Status” page.
systemctl reload tomcat

SSL/TLS Configuration

cd /usr/local/tomcat/current/tomcat1/conf
keytool -genkey -keyalg RSA -alias debian10.guisam.lan \
-keystore debian10.guisam.lan.jks -validity 365 -keysize 2048
  Enter keystore password:
  Re-enter new password:
  What is your first and last name?
    [Unknown]:  debian10.guisam.lan
  What is the name of your organizational unit?
    [Unknown]:  guisam
  What is the name of your organization?
    [Unknown]:  guisam
  What is the name of your City or Locality?
    [Unknown]:  ivry
  What is the name of your State or Province?
    [Unknown]:  94
  What is the two-letter country code for this unit?
    [Unknown]:  FR
  Is CN=debian10.guisam.lan, OU=guisam, O=guisam, L=ivry, ST=94, C=FR correct?
    [no]:  y

$CATALINA_HOME/tomcat1/conf/server.xml

+    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
+               maxThreads="150" SSLEnabled="true">
+       <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol"/>
+        <SSLHostConfig>
+               <Certificate
+                       certificateKeystorePassword="<mysuperpassword>"
+                       certificateKeystoreFile="conf/debian10.guisam.lan.jks"
+                       type="RSA" />
+        </SSLHostConfig>
+    </Connector>

$CATALINA_HOME/tomcat1/conf/web.xml

     </welcome-file-list>

+  <!-- ======================= HTTP to HTTPS ============================== -->
+
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Protected Context</web-resource-name>
+            <url-pattern>/*</url-pattern>
+        </web-resource-collection>
+        <!-- auth-constraint goes here if you require authentication -->
+        <user-data-constraint>
+            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+        </user-data-constraint>
+    </security-constraint>
+
 </web-app>
systemctl restart tomcat@tomcat1.service
curl -I http://192.168.122.232:8080
[...]
Location: https://192.168.122.232:8443/
[...]

curl -kI https://192.168.122.232:8443
HTTP/2 200
[...]

Manager Commands

Tip

alias curl="curl -u guisam:turlututu -k"
TOMCAT1="https://192.168.122.232:8443"
TOMCAT2="https://192.168.122.232:8444"
curl $TOMCAT1/manager/text/list
curl $TOMCAT1/manager/text/serverinfo
curl $TOMCAT1/manager/text/threaddump
curl $TOMCAT1/manager/text/vminfo
curl $TOMCAT1/manager/text/sessions\?path\=/sample
  OK - Session information for application at context path [/sample]
  Default maximum session inactive interval is [30] minutes
  Inactive for [<1] minutes: [1] sessions
curl $TOMCAT1/manager/text/expire\?path\=/sample\&idle\=num
  OK - Session information for application at context path [/sample]
  Default maximum session inactive interval is [30] minutes
  Inactive for [1 - <2] minutes: [1] sessions
curl $TOMCAT1/manager/text/stop\?path\=/docs
  OK - Stopped application at context path [/docs]
curl $TOMCAT1/manager/text/start\?path\=/docs
  OK - Started application at context path [/docs]
curl $TOMCAT1/manager/text/reload\?path\=/docs
  OK - Reloaded application at context path [/docs]
curl $TOMCAT1/manager/text/deploy\?path\=/sample -T sample.war
  OK - Deployed application at context path [/sample]
curl $TOMCAT1/manager/text/undeploy\?path\=/sample
  OK - Undeployed application at context path [/sample]