{"id":17,"date":"2026-03-22T01:01:07","date_gmt":"2026-03-22T01:01:07","guid":{"rendered":"https:\/\/nextialab.com\/?p=17"},"modified":"2026-03-22T01:51:14","modified_gmt":"2026-03-22T01:51:14","slug":"installing-tomcat-and-nginx-in-ubuntu-24-04","status":"publish","type":"post","link":"https:\/\/nextialab.com\/index.php\/2026\/03\/22\/installing-tomcat-and-nginx-in-ubuntu-24-04\/","title":{"rendered":"Installing Tomcat and Nginx in Ubuntu 24.04"},"content":{"rendered":"\n<p>Let&#8217;s assume you are running Ubuntu 24.04 in a virtual machine, with a user different from <code>root<\/code> but in the <code>sudo<\/code> group. First, update and upgrade the system with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo apt update\n$ sudo apt upgrade<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Installing the JRE<\/h2>\n\n\n\n<p>For the purpose of this post, we are going to use Tomcat 11, which requires at least a JRE version 17 to run. You are free to install any implementation of the JRE just make sure that the Tomcat version  you are planning to use is supported by that version of Java. For the sake of this post we are going with OpenJDK 21. Install the next dependency:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo apt install openjdk-21-jdk<\/code><\/pre>\n\n\n\n<p>Make sure that it was installed successfully by running:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ java -version<\/code><\/pre>\n\n\n\n<p>which should print the current installed version. Also take note of the installation path <code>JAVA_HOME<\/code>. By default, the JRE is installed in the path <code>\/usr\/lib\/jvm\/java-21-openjdk-amd64<\/code> or similar, depending on your VM. If it is not there then you can locate it by following its path, try running the command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ which java<\/code><\/pre>\n\n\n\n<p>which should print the location of that binary. But this location might be a symlink, so you should continue following it until you reach the folder containing the <code>java<\/code> binary.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installing Tomcat<\/h2>\n\n\n\n<p>Let&#8217;s first create a user that will run the service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo user add -r -m -U -d \/opt\/tomcat -s \/bin\/false tomcat<\/code><\/pre>\n\n\n\n<p>In summary: the <code>useradd<\/code> command will create a new system user <code>tomcat<\/code> with home directory <code>\/opt\/tomcat<\/code> and with no privileges to open <code>bash<\/code>. For more information you can read the <code>man<\/code> page of <code>useradd<\/code>.<\/p>\n\n\n\n<p>Then download the tomcat binaries from the <a href=\"https:\/\/tomcat.apache.org\">Tomcat official page<\/a>, remembering that we are using Tomcat 11:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ wget https:\/\/dlcdn.apache.org\/tomcat\/tomcat-11\/v11.0.18\/bin\/apache-tomcat-11.0.18.tar.gz<\/code><\/pre>\n\n\n\n<p>and extract it to the <code>tomcat<\/code> user home folder, create a symlink and change the ownership:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo tar -xzf apache-tomcat-11.0.18.tar.gz -C \/opt\/tomcat\n$ sudo ln -s \/opt\/tomcat\/apache-tomcat-11.0.18 \/opt\/tomcat\/current\n$ sudo chown -R tomcat:tomcat \/opt\/tomcat<\/code><\/pre>\n\n\n\n<p>The reason behind the <code>current<\/code> symlink is to make upgrading transparent to the system, once we download a new tomcat binary we just need to change where the symlink is pointing to.<\/p>\n\n\n\n<p>A useful mnemonic for the <code>tar<\/code> command is mentioning the phrase &#8216;extract the file&#8217; with a German accent: &#8216;e(x)tract (z)e (f)ile&#8217;.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setting up Tomcat as a service<\/h2>\n\n\n\n<p>Now let&#8217;s install Tomcat as a service using <code>systemd<\/code>. Create the next configuration file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo vim \/etc\/systemd\/system\/tomcat.service<\/code><\/pre>\n\n\n\n<p>with the content:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;Unit]\nDescription=Apache Tomcat Web Server\nAfter=network.target\n\n&#91;Service]\nType=forking\n\nEnvironment=\"JAVA_HOME=\/usr\/lib\/jvm\/java-21-openjdk-amd64\"\nEnvironment=\"CATALINA_PID=\/opt\/tomcat\/current\/temp\/tomcat.pid\"\nEnvironment=\"CATALINA_HOME=\/opt\/tomcat\/current\/\"\nEnvironment=\"CATALINA_BASE=\/opt\/tomcat\/current\/\"\n\nExecStart=\/opt\/tomcat\/current\/bin\/startup.sh\nExecStop=\/opt\/tomcat\/current\/bin\/shutdown.sh\n\nUser=tomcat\nGroup=tomcat\nUMask=0007\nRestartSec=10\nRestart=always\n\n&#91;Install]\nWantedBy=multi-user.target<\/code><\/pre>\n\n\n\n<p>Remember to press <code>i<\/code> to enter the (i)insert mode in vim, and press <code>esc<\/code> to exit it. To save the file press <code>esc<\/code>, write <code>:wq<\/code> and press <code>Enter<\/code>. The enable and start the service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo systemctl enable tomcat\n$ sudo systemctl start tomcat<\/code><\/pre>\n\n\n\n<p>Enabling the service means to let it start automatically when the system reboots. You can check its status at any time without <code>sudo<\/code> permission:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ systemctl status tomcat<\/code><\/pre>\n\n\n\n<p>If you see a green <strong>active<\/strong> message, it means that the service is most probably healthy. Up until now Tomcat is running in localhost in port 8080. Let&#8217;s open it to the Internet.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installing Nginx<\/h2>\n\n\n\n<p>The <code>nginx<\/code> package already includes the binaries and service configuration for Ubuntu, to install and enable it just run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo apt install nginx<\/code><\/pre>\n\n\n\n<p>And same as with Tomcat, you can check the current status of the service by running:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ systemctl status nginx<\/code><\/pre>\n\n\n\n<p>Now let&#8217;s configure nginx as reverse proxy to tomcat. First, let&#8217;s define an upstream block in the main nginx configuration file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo vim \/etc\/nginx\/nginx.conf<\/code><\/pre>\n\n\n\n<p>and add the next content inside the <code>http<\/code> block:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>http {\n    ...\n    upstream tomcat {\n        server 127.0.0.1:8080;\n    }\n    ...\n}<\/code><\/pre>\n\n\n\n<p>Save this file and let&#8217;s add a new server in the folder <code>\/etc\/nginx\/sites-available<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo vim \/etc\/nginx\/sites-available\/example.com<\/code><\/pre>\n\n\n\n<p>Let&#8217;s assume that there is a <code>A<\/code> DNS record that points <code>example.com<\/code> to this VM IP:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>server {\n    listen 80;\n    server_name example.com;\n    location \/ {\n        proxy_pass http:\/\/tomcat\/;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n    }\n}<\/code><\/pre>\n\n\n\n<p>and to enable it just create a symlink to the <code>sites-enabled<\/code> folder:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo ln -s \/etc\/nginx\/sites-available\/example.com \/etc\/nginx\/sites-enabled\/<\/code><\/pre>\n\n\n\n<p>Before restarting nginx and open it to the Internet, let&#8217;s confirm that our configuration has no mistakes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo nginx -t<\/code><\/pre>\n\n\n\n<p>If it returns an <code>ok<\/code> then that means that there is no mistake in any nginx configuration file and that we can safely restart the service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$sudeo systemctl restart nginx<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Managing the firewall<\/h2>\n\n\n\n<p>If you try to access the site from the outside it might get blocked because of the firewall. Ubuntu ships by default with <code>ufw<\/code> (Uncomplicated Firewall) and needs to be configured for HTTP and HTTPS. You can list all possible options for <code>ufw<\/code> with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo ufw app list<\/code><\/pre>\n\n\n\n<p>It should list at lest the next options: <code>Nginx Full<\/code>, <code>Nginx HTTP<\/code> and <code>Nginx HTTPS<\/code>. The first option will cover for both HTTP and HTTPS, so you can select it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ sudo ufw allow 'Nginx Full'<\/code><\/pre>\n\n\n\n<p>Now nginx will receive the request from the outside and should return the Tomcat home page. The system is ready to accept deployments.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">References<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.digitalocean.com\/community\/tutorials\/install-tomcat-on-linux\">A Complete Guide to Install Tomcat on Linux<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/serverfault.com\/a\/1050974\">how to configure nginx reverse proxy for tomcat servers?<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.digitalocean.com\/community\/tutorials\/how-to-install-nginx-on-ubuntu-20-04\">How to Install and Configure Nginx on Ubuntu<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Installing Tomcat as application server for Java apps and serving the content through nginx configured as reverse proxy<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[9,8,7],"class_list":["post-17","post","type-post","status-publish","format-standard","hentry","category-tutorials","tag-linux","tag-nginx","tag-tomcat"],"_links":{"self":[{"href":"https:\/\/nextialab.com\/index.php\/wp-json\/wp\/v2\/posts\/17","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nextialab.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nextialab.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nextialab.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nextialab.com\/index.php\/wp-json\/wp\/v2\/comments?post=17"}],"version-history":[{"count":3,"href":"https:\/\/nextialab.com\/index.php\/wp-json\/wp\/v2\/posts\/17\/revisions"}],"predecessor-version":[{"id":20,"href":"https:\/\/nextialab.com\/index.php\/wp-json\/wp\/v2\/posts\/17\/revisions\/20"}],"wp:attachment":[{"href":"https:\/\/nextialab.com\/index.php\/wp-json\/wp\/v2\/media?parent=17"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nextialab.com\/index.php\/wp-json\/wp\/v2\/categories?post=17"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nextialab.com\/index.php\/wp-json\/wp\/v2\/tags?post=17"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}