Prerequisites and User Configuration
Before creating the service file, ensure that Tomcat is installed and configured to run under a dedicated non-root user. Running web applications as the root user is a significant security risk. If you have not already created a specific user for Tomcat, create one using the useradd command. For example:
sudo useradd -m -s /bin/bash tomcat
Ensure that this user owns the Tomcat installation directory. Change the ownership of the entire Tomcat directory tree to this new user. This prevents permission errors when the service attempts to write logs or temporary files.
Creating the Unit File
The core of managing Tomcat via systemd is the unit file located in /etc/systemd/system/. Create a new file named tomcat.service using your preferred text editor with root privileges.
sudo nano /etc/systemd/system/tomcat.service
Populate the file with the following configuration. This example assumes a standard Tomcat 9 installation in /opt/tomcat. Adjust the paths if your installation differs.
[Unit]
Description=Apache Tomcat Web Application Container
After=network.target
[Service]
Type=forking
User=tomcat
Group=tomcat
Environment="JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64"
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=-Dfile.encoding=UTF-8 -Djava.net.preferIPv4Stack=true"
ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh
[Install]
WantedBy=multi-user.target
This configuration defines the basic requirements. The After=network.target ensures the service starts only after networking is available. The Type=forking directive tells systemd that the process will fork into the background, which is how Tomcat operates by default.
Configuring Environment Variables
Properly setting environment variables is critical for stability. The JAVA_HOME must point to the exact path where your JDK is installed. You can verify this path by running readlink -f $(which java) or checking your distribution's documentation.
The CATALINA_PID variable is essential for clean shutdowns. It points to a file where Tomcat stores its Process ID. Without this, systemd may struggle to stop the service gracefully. Ensure the directory specified (/opt/tomcat/temp) exists and is writable by the tomcat user.
Memory settings are defined in CATALINA_OPTS. These options control the JVM heap size and garbage collection behavior. The example uses -Xms512m for initial heap and -Xmx1024m for maximum heap. Adjust these values based on your server's available RAM. Do not confuse CATALINA_OPTS with JAVA_OPTS; the former affects only Catalina (the container), while the latter affects all Java applications.
Loading and Enabling the Service
Once the unit file is saved, reload the systemd daemon to recognize the new configuration. This step is mandatory whenever you modify or add service files.
sudo systemctl daemon-reload
To ensure Tomcat starts automatically upon system boot, enable the service. This creates the necessary symlinks in the multi-user target directory.
sudo systemctl enable tomcat
You can now start the service immediately without rebooting. Use the status command to verify that it started correctly and check for any immediate errors.
sudo systemctl start tomcat
sudo systemctl status tomcat
If the service fails to start, check the journal logs for detailed error messages. Common issues include incorrect JAVA_HOME paths or permission denied errors on the log directories. For more complex timing issues during startup, refer to our guide on Controlling Timing of Execution in *.service File with systemd.
Troubleshooting Common Issues
If Tomcat runs from the command line but fails as a systemd service, the issue is often related to environment variables or permissions. Systemd services do not inherit the interactive shell environment. Always define required variables explicitly in the unit file.
Another frequent problem is the service timing out or restarting repeatedly. This usually indicates that the ExecStart command is not properly signaling completion to systemd. Using Type=forking and specifying a PID file resolves most of these cases. See Systemd Service Timing Out/Restarting Every Few Minutes for deeper diagnostics on restart loops.
Ensure that the log directories are writable. Tomcat writes access logs and catalina.out to $CATALINA_BASE/logs. If the tomcat user cannot write to this folder, the service will fail silently or crash immediately.
Frequently Asked Questions
How do I view real-time logs for the Tomcat service?
Use the journalctl command with the -u flag followed by the service name. Run journalctl -u tomcat -f to follow the log output in real-time. This allows you to see startup errors or application exceptions as they occur.
Why does my Tomcat service fail to start with a "Permission denied" error?
This typically means the user specified in the unit file does not have ownership of the Tomcat installation directory or its subdirectories. Ensure you ran chown -R tomcat:tomcat /opt/tomcat (or your equivalent path) before starting the service.
Can I change the port Tomcat listens on through systemd?
No, the listening port is configured in server.xml, not in the systemd unit file. However, you can set environment variables that might influence network binding. Modifying server.xml directly is the correct method for changing ports.
What happens if I remove the CATALINA_PID setting?
Without a PID file, systemd cannot accurately track the main Tomcat process. This often leads to ExecStop failing because systemd cannot send the termination signal to the correct process ID, potentially leaving orphaned processes running.
How do I disable Tomcat from starting at boot?
Run sudo systemctl disable tomcat. This removes the symlinks that cause the service to start during the multi-user boot sequence, but it does not stop the service if it is currently running.