Installing Apache Tomcat
on Linux Mint Xia

Russell Bateman
August 2025

It's not like this topic has changed a lot over time, but this page is very clean, more correct and comparatively recent to all the other Tomcat notes I have made over a very long time.

Prepare for Tomcat by ensuring adequate Java support...

  1. Refresh and ready package manager, then install the default JDK.
    root@tirion:/opt# apt-get update
    Ign:1 http://packages.linuxmint.com xia InRelease
    Hit:2 https://download.docker.com/linux/ubuntu noble InRelease
    ...
    Reading package lists... Done
    root@tirion:/opt# apt-get install default-jdk
    Reading package lists... Done
    Building dependency tree... Done
    Reading state information... Done
    The following additional packages will be installed:
    ...
    Processing triggers for gnome-menus (3.36.0-1.1ubuntu3) ...
    Processing triggers for mate-menus (1.26.1+mint1) ...
    Processing triggers for man-db (2.12.0-4build2) ...
    
  2. Inspect the JDK: You will need to remember where to set environment variable JAVA_HOME to later.
    root@tirion:/opt/tomcat# which java
    /usr/bin/java
    root@tirion:/opt/tomcat# java --version
    openjdk 21.0.8 2025-07-15
    OpenJDK Runtime Environment (build 21.0.8+9-Ubuntu-0ubuntu124.04.1)
    OpenJDK 64-Bit Server VM (build 21.0.8+9-Ubuntu-0ubuntu124.04.1, mixed mode, sharing)
    root@tirion:/opt# ll /usr/bin/java
    lrwxrwxrwx 1 root root 22 Jul 16 15:55 /usr/bin/java -> /etc/alternatives/java*
    root@tirion:/opt# ll /etc/alternatives/java1,2
    lrwxrwxrwx 1 root root 43 Jul 16 15:55 /etc/alternatives/java -> /usr/lib/jvm/java-21-openjdk-amd64/bin/java*
    

Prepare system with group and user support...

  1. Create group tomcat and user tomcat for owning the Tomcat installation.
    russ@tirion:/opt # groupadd tomcat
    russ@tirion:/opt # useradd -s /bin/false -g tomcat -d /opt/tomcat tomcat
    

Download Tomcat 9 and set it up in the filesystem...

  1. Download Tomcat 9 tarball from https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.108/bin/apache-tomcat-9.0.108.tar.gz.
  2. Copy it to /opt and explode; rename to tomcat; remove the tarball.
    root@tirion:/opt# tar -zxf apache-tomcat-9.0.108.tar.gz
    root@tirion:/opt# mv apache-tomcat-9.0.108 tomcat
    root@tirion:/opt# ll
    ...
    drwxr-xr-x  8 root root     4096 Aug 14 11:42 ./
    drwxr-xr-x 22 root root     4096 Jul 29 13:56 ../
    -rw-rw-r--  1 russ russ 13028093 Aug 14 11:41 apache-tomcat-9.0.108.tar.gz
    drwxr-xr-x  9 root tomcat   4096 Aug 14 11:42 tomcat/
    root@tirion:/opt# rm apache-tomcat-9.0.108.tar.gz
    

Fix up ownership and permissions everywhere...

  1. Fix up group ownership.
    root@tirion:/opt# chgrp -R tomcat ./tomcat
    root@tirion:/opt# ll tomcat
    total 160
    drwxr-xr-x 9 root tomcat  4096 Aug 14 11:42 ./
    drwxr-xr-x 8 root root    4096 Aug 14 12:14 ../
    drwxr-x--- 2 root tomcat  4096 Aug 14 11:42 bin/
    -rw-r----- 1 root tomcat 24136 Jul 31 12:19 BUILDING.txt
    drwxr-x--- 2 root tomcat  4096 Jul 31 12:19 conf/
    -rw-r----- 1 root tomcat  6166 Jul 31 12:19 CONTRIBUTING.md
    drwxr-x--- 2 root tomcat  4096 Aug 14 11:42 lib/
    -rw-r----- 1 root tomcat 57092 Jul 31 12:19 LICENSE
    drwxr-x--- 2 root tomcat  4096 Jul 31 12:19 logs/
    -rw-r----- 1 root tomcat  2333 Jul 31 12:19 NOTICE
    -rw-r----- 1 root tomcat  3283 Jul 31 12:19 README.md
    -rw-r----- 1 root tomcat  6902 Jul 31 12:19 RELEASE-NOTES
    -rw-r----- 1 root tomcat 16538 Jul 31 12:19 RUNNING.txt
    drwxr-x--- 2 root tomcat  4096 Aug 14 11:42 temp/
    drwxr-x--- 7 root tomcat  4096 Jul 31 12:19 webapps/
    drwxr-x--- 2 root tomcat  4096 Jul 31 12:19 work/
    
  2. Switch to the tomcat subdirectory.
    root@tirion:/opt# cd tomcat
    
  3. Give ownership of all the important subdirectories to user tomcat.
    root@tirion:/opt/tomcat# chown -R tomcat bin conf lib logs temp webapps work
    root@tirion:/opt/tomcat# ll
    total 160
    drwxr-xr-x 9 root   tomcat  4096 Aug 14 11:42 ./
    drwxr-xr-x 8 root   root    4096 Aug 14 12:14 ../
    drwxr-x--- 2 tomcat tomcat  4096 Aug 14 11:42 bin/
    drwxr-x--- 2 tomcat tomcat  4096 Jul 31 12:19 conf/
    drwxr-x--- 2 tomcat tomcat  4096 Aug 14 11:42 lib/
    drwxr-x--- 2 tomcat tomcat  4096 Jul 31 12:19 logs/
    drwxr-x--- 2 tomcat tomcat  4096 Aug 14 11:42 temp/
    drwxr-x--- 7 tomcat tomcat  4096 Jul 31 12:19 webapps/
    drwxr-x--- 2 tomcat tomcat  4096 Jul 31 12:19 work/
    
  4. Give group tomcat access to Tomcat's conf subdirectory, its contents, give execute access to the subdirectory itself as well as ownership to user tomcat.
    root@tirion:/opt/tomcat# chmod -R3 g+r   conf
    root@tirion:/opt/tomcat# chmod     g+rxw conf
    root@tirion:/opt/tomcat# ll conf
    

Create the systemd service...

  1. Relocate current working directory to where systemd service definitions are kept.
    root@tirion:/opt/tomcat# pushd /etc/systemd/system
    root@tirion:/etc/systemd/system# vim tomcat.service
    
  2. Create and edit /etc/systemd/system/tomcat.service to look like this. Scrape and copy these lines; adjust JAVA_HOME's definition appropriately.
    root@tirion:/etc/systemd/system# vim tomcat.service
    
    [Unit] Description=Apache Tomcat Web Application Container After=network.target [Service] Type=forking Environment=JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd642 Environment=CATALINA_PID=/opt/tomcat/temp/tomcat.pid Environment=CATALINA_HOME=/opt/tomcat Environment=CATALINA_BASE=/opt/tomcat Environment='CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC' Environment='JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom' ExecStart=/opt/tomcat/bin/startup.sh ExecStop=/opt/tomcat/bin/shutdown.sh ExecReload=/opt/tomcat/bin/shutdown.sh && /opt/tomcat/bin/startup.sh User=tomcat Group=tomcat UMask=0007 RestartSec=10 Restart=always [Install] WantedBy=multi-user.target

Load the systemd service and launch Tomcat...

Reload the systemd dæmon so it discovers our new (Tomcat) service, then double-check that it launched without errors.

root@tirion:/opt/tomcat# systemctl daemon-reload          // rediscover systemd services
root@tirion:/opt/tomcat# systemctl start tomcat.service   // launch Tomcat
root@tirion:/opt/tomcat# systemctl status tomcat.service  // show Tomcat's status
root@tirion:/opt/tomcat# systemctl enable tomcat.service  // if you want Tomcat to come up at system boot time

Errors during start-up...

For a while, I was getting an error. To look at errors that break systemd, do:

root@tirion:/etc/systemd/system# journalctl -xeu tomcat.service

The main error I kept getting was:


...
A start job for unit tomcat.service has begun execution.

The job identifier is 557926.
Aug 14 15:24:30 tirion startup.sh[531309]: The JAVA_HOME environment variable is not defined correctly
Aug 14 15:24:30 tirion startup.sh[531309]: JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
Aug 14 15:24:30 tirion startup.sh[531309]: This environment variable is needed to run this program
Aug 14 15:24:30 tirion startup.sh[531309]: NB: JAVA_HOME should point to a JDK not a JRE4
Aug 14 15:24:30 tirion systemd[1]: tomcat.service: Control process exited, code=exited, status=1/FAILURE
Subject: Unit process exited
Defined-By: systemd
Support: http://www.ubuntu.com/support

An ExecStart= process belonging to unit tomcat.service has exited.
...

This was because I originally got JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 wrong (misspelled) in the file tomcat.service.

Notes

1 The JRE is no longer a thing for a while now: all distributions of Java are JDKs.
2 Here is the path to the JDK to put into tomcat.service.
3 Means enact this action recursively to all subdirectories and files.
4 This is Tomcat's way of saying that there is something wrong; it's often nothing to do with the path pointing or not at a JDK, in other words, something's wrong, this is my error message, and I'm sticking with it.