Install Apache Tomcat 9 Complete with Updated Scripts

In this exercise, Tomcat 9 will be installed with OpenJDK 8 using a self-signed certificate using the http2.Http2Protocol protocol.  I’ve updated and simplified the script since my last attempt at a similar Tomcat 9 installation.  I have also added SELinux context, log rotation, and speed!

########################################################################################
# Apache Tomcat 9
########################################################################################

yum install wget firewalld java-1.8.0-openjdk-devel policycoreutils-python epel-release -y
yum install tomcat-native -y
wget http://us.mirrors.quenda.co/apache/tomcat/tomcat-9/v9.0.27/bin/apache-tomcat-9.0.27.tar.gz -P /opt
tar xzf /opt/apache-tomcat-9.0.27.tar.gz -C /opt
ln -s /opt/apache-tomcat-9.0.27 /opt/tomcat

########################################################################################
# Create a User
########################################################################################

id -u tomcat &>/dev/null || useradd -s /sbin/nologin tomcat
#or
[ "$(grep tomcat /etc/passwd | cut -f1 -d":")" = "tomcat" ] || useradd -s /sbin/nologin tomcat

########################################################################################
# Apply Firewall Rules
########################################################################################

systemctl enable --now firewalld
firewall-cmd --permanent --add-port=8443/tcp
firewall-cmd --reload

########################################################################################
# Create a Service
########################################################################################
# Helpful for the /dev/urandom https://gist.github.com/drmalex07/e6e99dad070a78d5dab24ff3ae032ed1
#Source(s) https://blog.longyb.com/2019/06/09/tomcat_hang_creation_of_securerandom_instance_for_sessionid_english/
# Introducing /dev/urandom as a replacement for /dev/random significantly reduces startup time no WARNING in catalina.out

cat << 'EOF' > /etc/systemd/system/tomcat.service
[Unit]
Description=Starts and stops Tomcat Server
After=syslog.target network.target

[Service]
User=tomcat
Group=tomcat
Type=forking
Environment="JAVA_OPTS=-Djava.security.egd=file:///dev/urandom"
ExecStart=/opt/tomcat/bin/catalina.sh start
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload

########################################################################################
# server.xml configuration modifications
########################################################################################

sed -i.bak '/^\s*<!--/!b;N;/org.apache.coyote.http11.Http11AprProtocol/s/.*\n//;T;:a;n;/^\s*-->/!ba;d' /opt/tomcat/conf/server.xml
# Source: https://stackoverflow.com/questions/17996497/sed-uncomment-specfic-xml-comments-out-of-a-file

# Use this if there is a certificate chain
#sed -i '/certificateKeyFile/s/=.*$/="\/etc\/pki\/tls\/private\/server1.example.com.key"/' /opt/tomcat/conf/server.xml
#sed -i '/certificateFile/s/=.*$/="\/etc\/pki\/tls\/certs\/server1.example.com.crt"/' /opt/tomcat/conf/server.xml
#sed -i '/certificateChainFile/s/=.*$/="\/etc\/pki\/tls\/certs\/server1.example.com_chain.crt"/' /opt/tomcat/conf/server.xml

# Use this if there is not a certificate chain
sed -i '/certificateKeyFile/s/=.*$/="\/etc\/pki\/tls\/private\/server1.example.com.key"/' /opt/tomcat/conf/server.xml
sed -i '/certificateFile/s/=.*$/="\/etc\/pki\/tls\/certs\/server1.example.com.crt" type="RSA" \/\> <!--/' /opt/tomcat/conf/server.xml
sed -i '/certificateChainFile/s/=.*$/="\/etc\/pki\/tls\/certs\/server1.example.com_chain.crt"/' /opt/tomcat/conf/server.xml
sed -i '/certificateChainFile/!b;n;c\\t\t\ttype="RSA" /> -->'  /opt/tomcat/conf/server.xml
# Source: https://unix.stackexchange.com/questions/427291/key-value-lines-how-to-replace-a-specific-keys-value

########################################################################################
# generate the self-signed certs (otherwise use certs provided by CA cert provider)
########################################################################################

FQDN=server1.example.com
openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
-keyout $FQDN.key -out $FQDN.crt -subj "/CN=$FQDN" \
-extensions san \
-config <(echo '[req]'; echo 'distinguished_name=req';
echo '[san]'; echo "subjectAltName=DNS:$FQDN")

/bin/cp $FQDN.key /etc/pki/tls/private/
/bin/cp $FQDN.crt /etc/pki/tls/certs/

unset FQDN

########################################################################################
# Cleanup
########################################################################################

rm -rf /opt/tomcat/webapps/{docs,examples,host-manager,manager}

########################################################################################
# Apply Permissions
########################################################################################

chown -R tomcat:tomcat /opt/tomcat/ /opt/tomcat

########################################################################################
# Start Tomcat
########################################################################################

systemctl enable --now tomcat

########################################################################################
# Log Rotation
########################################################################################

cat << 'EOF' > /etc/logrotate.d/tomcat
/opt/apache-tomcat-9.0.27/logs/catalina.out {
copytruncate
daily
notifempty
rotate 7
compress
missingok
}
/opt/apache-tomcat-9.0.27/logs/dummy {
rotate 0
daily
create
ifempty
missingok
lastaction
/usr/bin/find /opt/apache-tomcat-9.0.27/logs/ -maxdepth 1 -daystart -mtime +1 \( -name "*.log" -o -name "*.txt" \) -exec gzip -f "{}" \;
/usr/bin/find /opt/apache-tomcat-9.0.27/logs/ -maxdepth 1 -daystart -mtime +7 -type f -name "*.gz" -print -delete
endscript
}
EOF

# ensure proper ownership and permissions are applied to the logrotation script or it won't execute.
chown root:root /etc/logrotate.d/tomcat
chmod 644 /etc/logrotate.d/tomcat

touch /opt/app/apache-tomcat-9.0.27/logs/dummy

########################################################################################
# SeLinux Context
########################################################################################

# var_log_t context is required for logrotation to work.

semanage fcontext -a -t var_log_t -s system_u '/opt/apache-tomcat-9.0.27/logs(/.*)?'
restorecon -Fr /opt/apache-tomcat-9.0.27/logs

########################################################################################
# BONUS: Not recommended for production.
########################################################################################

# Allow access from remote servers to the manager and other "useful" links on the Tomcat page.

sed -i.bak '/allow=/ s/"/"10\\.\\d+\\.\\d+\\.\\d+|/1' /opt/tomcat/webapps/host-manager/META-INF/context.xml
sed -i '/allow=/ s/"/"10\\.\\d+\\.\\d+\\.\\d+|/1' /opt/tomcat/webapps/manager/META-INF/context.xml
sed -i '/allow=/ s/"/"192\\.\\d+\\.\\d+\\.\\d+|/1' /opt/tomcat/webapps/host-manager/META-INF/context.xml
sed -i '/allow=/ s/"/"192\\.\\d+\\.\\d+\\.\\d+|/1' /opt/tomcat/webapps/manager/META-INF/context.xml

sed -i.bak '$ d' /opt/tomcat/conf/tomcat-users.xml

cat << 'EOF' >> /opt/tomcat/conf/tomcat-users.xml
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-jmx"/>
<role rolename="manager-status"/>
<role rolename="admin-gui"/>
<role rolename="admin-script"/>
<user username="admin" password="admin" roles="admin-gui,admin-script"/>
<user username="tomcat" password="tomcat" roles="manager-gui,manager-script,manager,jmx,manager-status"/>
</tomcat-users>
EOF

########################################################################################
# Done
########################################################################################

Enjoy Tomcat

Screenshot from an earlier version, but the end result is the same.