Tomcat

Apache Tomcat (or simply Tomcat, formerly known as Jakarta Tomcat) is an open source web server and servlet container developed by the Apache Software Foundation (ASF).
The Apache Tomcat software is developed in an open and participatory environment and is released under version 2 of the Apache License .
It implements several Java EE specifications, including Java Servlet, JavaServer Pages (JSP), Java EL, and WebSocket, and provides a "pure Java" HTTP server environment in which Java code can run.

Tomcat 4.x was released with Catalina (a servlet container), Coyote (an HTTP connector), and Jasper (a JSP engine).

Catalina

Catalina is Tomcat's servlet container. Catalina implements the specifications of Sun Microsystems for servlets and JavaServer Pages (JSP).

Coyote

Coyote is a Connector component for Tomcat that supports the HTTP 1.1 protocol as a web server. This allows Catalina, commonly referred to as a Java servlet or JSP container, to also act as a simple web server that serves local files as HTTP documents. Coyote listens for incoming connections to the server on a specific TCP port and forwards the request to the Tomcat Engine to process the request and send back a response to the requesting client. Another Coyote connector, Coyote JK, similarly listens but forwards its requests to another web server, such as Apache, using the JK protocol. Usually, this provides better performance.

Jasper

Jasper is Tomcat's JSP engine. Jasper analyzes JSP files to compile them into Java code as servlets (which can be managed by Catalina). During execution, Jasper detects changes made to JSP files and will recompile them.

Three new components were added with the release of Tomcat 7:

Cluster

This component was added to manage large applications. It is used for load balancing that can be achieved through many techniques. Clustering support currently requires JDK version 1.5 or higher.

High availability

A high availability feature has been added to facilitate the scheduling of system updates (e.g., new releases, change requests) without affecting the surrounding environment. This is done by routing live traffic requests to a temporary server on a different port while the main server is being upgraded on the main port. It is very useful for managing user requests on high-traffic web applications.

Web application

Additionally, an enhancement has been added for user and system-based web applications to provide support for deployment across a range of environments.

Installation

To run the service, we need to have Java initially installed. Version 17 of the JDK will be installed because at least this version is necessary to compile applications created with jmix 2.0. For the same reason, Tomcat version 10 will be installed from source, as in the Ubuntu 22.04 distribution we find the package for Tomcat 9.

apt install openjdk-17-jdk

We will create a user tomcat and a group tomcat without login rights with home in /opt/tomcat

useradd -m -U -d /opt/tomcat -s /bin/false tomcat

We download the application Tomcat and we will pay attention to which is the latest stable version and we will create a variable VERSION in bash:

VERSIUNE=10.1.17

After creating the previous variable, we use wget to download Tomcat into the temporary directory /tmp:

wget https://www-eu.apache.org/dist/tomcat/tomcat-10/v${VERSIUNE}/bin/apache-tomcat-${VERSIUNE}.tar.gz -P /tmp

We extract the previously downloaded archive into the directory /opt/tomcat:

tar -xf /tmp/apache-tomcat-${VERSIUNE}.tar.gz -C /opt/tomcat/

Then we will create a symbolic link (link) /opt/tomcat/latest to the directory created earlier by extraction:

ln -s /opt/tomcat/apache-tomcat-${VERSIUNE} /opt/tomcat/latest

We change the owner of the files and the group they belong to be tomcat created earlier,

chown -R tomcat: /opt/tomcat

and using the command ls -la /opt/tomcat we check:

We mark the scripts in the bin directory as executable:

chmod +x /opt/tomcat/latest/bin/*.sh

Using the nano editor, we will create the file tomcat.service in the directory /etc/systemd/system:

nano /etc/systemd/system/tomcat.service

a file that will contain the following:

[Unit]
Description=Tomcat 10 servlet container
After=network.target

[Service]
Type=forking

User=tomcat
Group=tomcat

Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64"
Environment="JAVA_OPTS=-Djava.security.egd=file:///dev/urandom -Djava.awt.headless=true"

Environment="CATALINA_BASE=/opt/tomcat/latest"
Environment="CATALINA_HOME=/opt/tomcat/latest"
Environment="CATALINA_PID=/opt/tomcat/latest/temp/tomcat.pid"
Environment="CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC"

ExecStart=/opt/tomcat/latest/bin/startup.sh
ExecStop=/opt/tomcat/latest/bin/shutdown.sh

[Install]
WantedBy=multi-user.target

pay attention to the variable path JAVA_HOME:

After saving and closing the file, we will notify the systemd system of the appearance of a new file:

systemctl daemon-reload

We will start and enable the service to start on system reboot:

systemctl enable --now tomcat

We check if the tomcat service has started and if everything is in order:

systemctl status tomcat

To facilitate external connections, we will need to create a firewall rule using the nano editor, in this case for ufw:

nano /etc/ufw/applications.d/tomcat-server

in which we will write the following:

[Tomcat]
title=Web server and Java servlet container
description=Apache Tomcat is an web server and java servlet container.
ports=8080/tcp

Using the following commands, we will establish a new access rule:

ufw app list
ufw allow Tomcat
ufw reload

We check if the new rule is loaded:

ufw status

With the help of a browser, in this case firefox, we check if our tomcat service is running and functional:

With the help of our preferred editor, we will configure the user/users who have administrative rights:

nano /opt/tomcat/latest/conf/tomcat-users.xml

where we will specify the username, password, and roles:

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">
<!--
  By default, no user is included in the "manager-gui" role required
  to operate the "/manager/html" web application.  If you wish to use this app,
  you must define such a user - the username and password are arbitrary.

  Built-in Tomcat manager roles:
    - manager-gui    - allows access to the HTML GUI and the status pages
    - manager-script - allows access to the HTTP API and the status pages
    - manager-jmx    - allows access to the JMX proxy and the status pages
    - manager-status - allows access to the status pages only

  The users below are wrapped in a comment and are therefore ignored. If you
  wish to configure one or more of these users for use with the manager web
  application, do not forget to remove the <!.. ..> that surrounds them. You
  will also need to set the passwords to something appropriate.
-->
<!--
  <user username="admin" password="<must-be-changed>" roles="manager-gui"/>
  <user username="robot" password="<must-be-changed>" roles="manager-script"/>
-->
<!--
  The sample user and role entries below are intended for use with the
  examples web application. They are wrapped in a comment and thus are ignored
  when reading this file. If you wish to configure these users for use with the
  examples web application, do not forget to remove the <!.. ..> that surrounds
  them. You will also need to set the passwords to something appropriate.
-->
<!--
  <role rolename="tomcat"/>
  <role rolename="role1"/>
  <user username="tomcat" password="<must-be-changed>" roles="tomcat"/>
  <user username="both" password="<must-be-changed>" roles="tomcat,role1"/>
  <user username="role1" password="<must-be-changed>" roles="role1"/>
-->
   <role rolename="admin-gui"/>
   <role rolename="manager-gui"/>
   <user username="username" password="username_password" roles="admin-gui,manager-gui"/>
</tomcat-users>

we restart the service to implement the new changes:

systemctl restart tomcat

In order to connect to the web page http://ip.ip.ip.ip:8080/manager with the username and password set in the previous step from any IP, we will need to comment out the line <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> or to add the privileged IP for connection, as below:

nano /opt/tomcat/latest/webapps/manager/META-INF/context.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<Context antiResourceLocking="false" privileged="true" >
  <CookieProcessor className="org.apache.tomcat.util.http.Rfc6265CookieProcessor"
                   sameSiteCookies="strict" />
<!--
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|192.168.1.243" />
-->
  <Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Nu>
</Context>

After the above modification, we restart the service with:

systemctl restart tomcat

and we will be able to connect to the administration page after entering the previously defined username and password:

http://ip.ip.ip.ip:8080/manager/html

In the same manner, we will proceed with the manager for virtual pages found at:

nano /opt/tomcat/latest/webapps/host-manager/META-INF/context.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<Context antiResourceLocking="false" privileged="true" >
  <CookieProcessor className="org.apache.tomcat.util.http.Rfc6265CookieProcessor"
                   sameSiteCookies="strict" />
<!--
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|192.168.1.243" />
-->
  <Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Nu>
</Context>

http://ip.ip.ip.ip:8080/host-manager/html

To gain access to external documentation, we will make the following modifications:

nano /opt/tomcat/latest/webapps/docs/META-INF/context.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<Context antiResourceLocking="false" >
<!--
  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1|192.168.1.243" />
-->
</Context>

Information security is implemented similarly to version 8.

Attention to the path, the paths used below are for version 8.

Since the communication is in clear text and usually Tomcat runs Java applications that have access to databases, it is imperative to use encrypted/secured communication. For this purpose, we will use certificates from Let's Encrypt.
The installation of the client and the generation of keys is described here .

The keys generated by Let's Encrypt will be copied to the directory that holds the configuration files for the Tomcat service:

cp /etc/letsencrypt/live/yo8tff.ro/cert.pem /var/lib/tomcat8/conf
cp /etc/letsencrypt/live/yo8tff.ro/chain.pem /var/lib/tomcat8/conf
cp /etc/letsencrypt/live/yo8tff.ro/privkey.pem /var/lib/tomcat8/conf

We grant the user under which Tomcat runs the rights to access the keys:

chown tomcat8:tomcat8 /var/lib/tomcat8/conf/*.pem

We edit the configuration file of the Tomcat service to start a secured SSL instance on port 8443:
nano /etc/tomcat8/server.xml

and the file will look like this:

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with
  this work for additional information regarding copyright ownership.
  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with
  the License.  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<!-- Note:  A "Server" is not itself a "Container", so you may not
     define subcomponents such as "Valves" at this level.
     Documentation at /docs/config/server.html
 -->
<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

  <!-- Global JNDI resources
       Documentation at /docs/jndi-resources-howto.html
  -->
  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <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>

  <!-- A "Service" is a collection of one or more "Connectors" that share
       a single "Container" Note:  A "Service" is not itself a "Container",
       so you may not define subcomponents such as "Valves" at this level.
       Documentation at /docs/config/service.html
   -->
    <!--The connectors can use a shared executor, you can define one or more named thread pools-->
    <!--
    <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
        maxThreads="150" minSpareThreads="4"/>
    -->

    <!-- A "Connector" represents an endpoint by which requests are received
         and responses are returned. Documentation at :
         Java HTTP Connector: /docs/config/http.html
         Java AJP  Connector: /docs/config/ajp.html
         APR (HTTP/AJP) Connector: /docs/apr.html
         Define a non-SSL/TLS HTTP/1.1 Connector on port 8080
    -->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <!-- A "Connector" using the shared thread pool-->
    <!--
    <Connector executor="tomcatThreadPool"
               port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    -->
    <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443
         This connector uses the NIO implementation. The default
         SSLImplementation will depend on the presence of the APR/native
         library and the useOpenSSL attribute of the
         AprLifecycleListener.
         Either JSSE or OpenSSL style configuration may be used regardless of
         the SSLImplementation selected. JSSE style configuration is used below.
    -->
    <!--
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150" SSLEnabled="true">
        <SSLHostConfig>
            <Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>
    -->
    <!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443 with HTTP/2
         This connector uses the APR/native implementation which always uses
         OpenSSL for TLS.
         Either JSSE or OpenSSL style configuration may be used. OpenSSL style
         configuration is used below.
    -->
  <!--
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
               maxThreads="150" SSLEnabled="true" >
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
        <SSLHostConfig>
            <Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
                         certificateFile="conf/localhost-rsa-cert.pem"
                         certificateChainFile="conf/localhost-rsa-chain.pem"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>
    -->

<!-- Criptarea SSL a comunicație la portul 8443 -->

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
           maxThreads="150" SSLEnabled="true">
  <SSLHostConfig>
    <Certificate certificateFile="conf/cert.pem"
                 certificateKeyFile="conf/privkey.pem"
                 certificateChainFile="conf/chain.pem" />
  </SSLHostConfig>
</Connector>

    <!-- Define an AJP 1.3 Connector on port 8009 -->
    <!--
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    -->

    <!-- An Engine represents the entry point (within Catalina) that processes
         every request.  The Engine implementation for Tomcat stand alone
         analyzes the HTTP headers included with the request, and passes them
         on to the appropriate Host (virtual host).
         Documentation at /docs/config/engine.html -->

    <!-- You should set jvmRoute to support load-balancing via AJP ie :
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
    -->
    <Engine name="Catalina" defaultHost="localhost">

      <!--For clustering, please take a look at documentation at:
          /docs/cluster-howto.html  (simple how to)
          /docs/config/cluster.html (reference documentation) -->
      <!--
      <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
      -->

      <!-- Use the LockOutRealm to prevent attempts to guess user passwords
           via a brute-force attack -->
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <!-- This Realm uses the UserDatabase configured in the global JNDI
             resources under the key "UserDatabase".  Any edits
             that are performed against this UserDatabase are immediately
             available for use by the Realm.  -->
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

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

        <!-- SingleSignOn valve, share authentication between web applications
             Documentation at: /docs/config/valve.html -->
        <!--
        <Valve className="org.apache.catalina.authenticator.SingleSignOn" />
        -->

        <!-- Access log processes all example.
             Documentation at: /docs/config/valve.html
             Note: The pattern used is equivalent to using pattern="common" -->
        <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>

We will restart the Tomcat service for the changes to take effect:

systemctl restart tomcat8

After restarting, we check at the domain address using the https protocol, port 8443, with our preferred browser to see if the server started correctly and if the keys are valid: