<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jesús G. Calderín</title>
    <description>The latest articles on DEV Community by Jesús G. Calderín (@jess_garcacaldern_028).</description>
    <link>https://dev.to/jess_garcacaldern_028</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3517941%2F27f5bf6c-accf-48b9-8e23-e0c31ad244ec.jpg</url>
      <title>DEV Community: Jesús G. Calderín</title>
      <link>https://dev.to/jess_garcacaldern_028</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jess_garcacaldern_028"/>
    <language>en</language>
    <item>
      <title>Install SSL server and client certificates in Apache Web Server</title>
      <dc:creator>Jesús G. Calderín</dc:creator>
      <pubDate>Tue, 30 Sep 2025 09:51:39 +0000</pubDate>
      <link>https://dev.to/jess_garcacaldern_028/install-ssl-server-and-client-certificates-in-apache-web-server-3j25</link>
      <guid>https://dev.to/jess_garcacaldern_028/install-ssl-server-and-client-certificates-in-apache-web-server-3j25</guid>
      <description>&lt;p&gt;SSL (Secure Socket Layer) is the technology behind the &lt;code&gt;https&lt;/code&gt; urls you can see when browsing secure sites (which is nearly all of them). It's a protocol that allows server and browser (or more generally, the "agent" or just the "client") to establish a "handshake" prior to start exchanging request and responses. Its two main purposes are to enable the client to reliably identify the server and allow both to communicate via an encrypted channel.&lt;/p&gt;

&lt;p&gt;During this handshake, the server will present the client with its "certificate", which is a X501-formatted data structure. The way the client will verify that the server is who it claims to be is by checking that this certificate is signed by some organisation it trusts, a list of which it must have available on its side and also checking that the certificate is issued to the same domain we are accessing.&lt;/p&gt;

&lt;p&gt;Additionally, the server can ask the client to provide him with a "client certificate" for identification purposes. The server can then use this information to grant or block the client from visiting certain areas of the site or executing certain functions.&lt;/p&gt;

&lt;p&gt;We will see below how to &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;activate SSL in our Apache Web Server, &lt;/li&gt;
&lt;li&gt;create a server certificate for our site,&lt;/li&gt;
&lt;li&gt;instruct the server to ask the client to provide a certificate,&lt;/li&gt;
&lt;li&gt;create and install a client certificate in our browser&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;1) Verify Linux's builtin Apache Web Server is installed and running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status apache2
● apache2.service - The Apache HTTP Server
     Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/lib/systemd/system/apache2.service&lt;span class="p"&gt;;&lt;/span&gt; 
     enabled&lt;span class="p"&gt;;&lt;/span&gt; vendor preset: enabled&lt;span class="o"&gt;)&lt;/span&gt;
     Active: active &lt;span class="o"&gt;(&lt;/span&gt;running&lt;span class="o"&gt;)&lt;/span&gt; since Sun 2025-09-21 12:43:12 CEST&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) Although not mandatory, I find convenient to map the ip address of the Linux box containing our Apache server to a DNS name of our choosing, for example I will use:&lt;br&gt;
&lt;code&gt;test-980.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In Windows, you can do this mapping by editing the file&lt;/p&gt;

&lt;p&gt;&lt;code&gt;C:\Windows\System32\drivers\etc\hosts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and adding your &amp;lt;Apache server ip&amp;gt; + blank-space + &amp;lt;domain name&amp;gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Added by me
172.31.36.52 test-980.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when I call that domain from my Windows host, I will get the home page of my Apache Web Server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;#Before changing C:\Windows\System32\drivers\etc\hosts file:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;PS&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;curl.exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http://test-980.com/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Could&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;host:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;test-980.com&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;shutting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;down&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;connection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;#0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;curl:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Could&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;host:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;test-980.com&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;#After changing C:\Windows\System32\drivers\etc\hosts file:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;PS&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;curl.exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http://test-980.com/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;test-980.com:80&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;was&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resolved.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IPv6:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;none&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IPv4:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;172.31.36.52&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Trying&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;172.31.36.52:80...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Connected&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;test-980.com&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;172.31&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;36&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;52&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;80&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HTTP/1.x&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;GET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;HTTP/1.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Host:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;test-980.com&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User-Agent:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;curl/8.14.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Accept:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;/&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HTTP/1.1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;200&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;OK&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;full&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;home&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;follows&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;here&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3) Create a virtual host for my &lt;code&gt;test-980.com&lt;/code&gt; site, so we don't mess around with default virtual host in apache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/sites/test-980.com/conf
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/sites/test-980.com/www/html
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vi /var/sites/test-980.com/www/html/index.html
&lt;span class="c"&gt;#add the content shown in the cat command below&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /var/sites/test-980.com/www/html/index.html
&amp;lt;html &lt;span class="nv"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://www.w3.org/1999/xhtml"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &amp;lt;&lt;span class="nb"&gt;head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &amp;lt;meta http-equiv&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Content-Type"&lt;/span&gt; &lt;span class="nv"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"text/html; charset=UTF-8"&lt;/span&gt; /&amp;gt;
    &amp;lt;title&amp;gt;test-980.com: It works&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
        Welcome to test-980.com
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; /etc/apache2/sites-available/000-default.conf &lt;span class="se"&gt;\&lt;/span&gt;
/var/sites/test-980.com/conf/localhost.conf

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vi /var/sites/test-980.com/conf/localhost.conf
&lt;span class="c"&gt;#add the content shown in the cat command below&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /var/sites/test-980.com/conf/localhost.conf
&amp;lt;VirtualHost &lt;span class="k"&gt;*&lt;/span&gt;:80&amp;gt;
        ServerName test-980.com

        ServerAdmin webmaster@test-980.com
        DocumentRoot /var/sites/test-980.com/www/html

        &amp;lt;Directory /var/sites/test-980.com/www/&amp;gt;
          Options Indexes FollowSymLinks
          AllowOverride None
          Require all granted
        &amp;lt;/Directory&amp;gt;

        ErrorLog &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;APACHE_LOG_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/error.log
        CustomLog &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;APACHE_LOG_DIR&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/access.log combined

&amp;lt;/VirtualHost&amp;gt;

&lt;span class="c"&gt;#Make our site available&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /var/sites/test-980.com/conf/localhost.conf &lt;span class="se"&gt;\&lt;/span&gt;
/etc/apache2/sites-available/local-test-980.com.conf

&lt;span class="c"&gt;#Maker our site enabled:&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;a2ensite local-test-980.com
Enabling site local-test-980.com.
To activate the new configuration, you need to run:
  systemctl reload apache2

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo  &lt;/span&gt;systemctl reload apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, &lt;code&gt;curl&lt;/code&gt; will return our new page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;PS&amp;gt; curl.exe http://test-980.com/
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/1999/xhtml"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"text/html; charset=UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;test-980.com: It works&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        Welcome to test-980.com
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, we cannnot access our site via &lt;code&gt;https&lt;/code&gt; for the moment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;PS&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;curl.exe&lt;/span&gt; &lt;span class="kd"&gt;https&lt;/span&gt;://test&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com/
&lt;span class="nb"&gt;curl&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;35&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;schannel&lt;/span&gt;: &lt;span class="kd"&gt;next&lt;/span&gt; &lt;span class="kd"&gt;InitializeSecurityContext&lt;/span&gt; &lt;span class="kd"&gt;failed&lt;/span&gt;:
&lt;span class="kd"&gt;SEC_E_INVALID_TOKEN&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x80090308&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; 
&lt;span class="kd"&gt;El&lt;/span&gt; &lt;span class="kd"&gt;token&lt;/span&gt; &lt;span class="kd"&gt;proporcionado&lt;/span&gt; &lt;span class="kd"&gt;a&lt;/span&gt; &lt;span class="kd"&gt;la&lt;/span&gt; &lt;span class="kd"&gt;funci&lt;/span&gt;ón &lt;span class="kd"&gt;no&lt;/span&gt; &lt;span class="kd"&gt;es&lt;/span&gt; &lt;span class="kd"&gt;v&lt;/span&gt;álido
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll see next how to secure our site via SSL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable SSL on Apache
&lt;/h2&gt;

&lt;p&gt;Run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;a2ensite default-ssl.conf
Enabling site default-ssl.
To activate the new configuration, you need to run:
  systemctl reload apache2
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we look at the content of &lt;code&gt;/etc/apache2/sites-enabled/default-ssl.conf&lt;/code&gt;, we will see that we have done the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;listen on port 443:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;VirtualHost _default_:443&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;serve the pages under &lt;code&gt;/var/www/html&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;DocumentRoot /var/www/html&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use SSL protocol on this virtual host:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;SSLEngine on&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;send the client the following server certificate:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So, if we now test &lt;code&gt;https&lt;/code&gt;, we will get a warning that the certificate is not trusted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;PS&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;curl.exe&lt;/span&gt; &lt;span class="kd"&gt;https&lt;/span&gt;://test&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com/
&lt;span class="nb"&gt;curl&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;schannel&lt;/span&gt;: &lt;span class="kd"&gt;SEC_E_UNTRUSTED_ROOT&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x80090325&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; 
&lt;span class="kd"&gt;La&lt;/span&gt; &lt;span class="kd"&gt;cadena&lt;/span&gt; &lt;span class="kd"&gt;de&lt;/span&gt; &lt;span class="kd"&gt;certificaci&lt;/span&gt;ón &lt;span class="kd"&gt;fue&lt;/span&gt; &lt;span class="kd"&gt;emitida&lt;/span&gt; &lt;span class="kd"&gt;por&lt;/span&gt; &lt;span class="kd"&gt;una&lt;/span&gt; &lt;span class="kd"&gt;entidad&lt;/span&gt; &lt;span class="kd"&gt;en&lt;/span&gt; &lt;span class="kd"&gt;la&lt;/span&gt; &lt;span class="kd"&gt;que&lt;/span&gt; &lt;span class="kd"&gt;no&lt;/span&gt; &lt;span class="kd"&gt;se&lt;/span&gt; &lt;span class="kd"&gt;conf&lt;/span&gt;ía.
&lt;span class="kd"&gt;More&lt;/span&gt; &lt;span class="kd"&gt;details&lt;/span&gt; &lt;span class="kd"&gt;here&lt;/span&gt;: &lt;span class="kd"&gt;https&lt;/span&gt;://curl.se/docs/sslcerts.html

&lt;span class="nb"&gt;curl&lt;/span&gt; &lt;span class="kd"&gt;failed&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;verify&lt;/span&gt; &lt;span class="kd"&gt;the&lt;/span&gt; &lt;span class="kd"&gt;legitimacy&lt;/span&gt; &lt;span class="kd"&gt;of&lt;/span&gt; &lt;span class="kd"&gt;the&lt;/span&gt; &lt;span class="kd"&gt;server&lt;/span&gt; &lt;span class="kd"&gt;and&lt;/span&gt; &lt;span class="kd"&gt;therefore&lt;/span&gt; &lt;span class="kd"&gt;could&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt;
&lt;span class="kd"&gt;establish&lt;/span&gt; &lt;span class="kd"&gt;a&lt;/span&gt; &lt;span class="kd"&gt;secure&lt;/span&gt; &lt;span class="kd"&gt;connection&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;it&lt;/span&gt;. &lt;span class="kd"&gt;To&lt;/span&gt; &lt;span class="kd"&gt;learn&lt;/span&gt; &lt;span class="nb"&gt;more&lt;/span&gt; &lt;span class="kd"&gt;about&lt;/span&gt; &lt;span class="kd"&gt;this&lt;/span&gt; &lt;span class="kd"&gt;situation&lt;/span&gt; &lt;span class="kd"&gt;and&lt;/span&gt;
&lt;span class="kd"&gt;how&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;fix&lt;/span&gt; &lt;span class="kd"&gt;it&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;please&lt;/span&gt; &lt;span class="kd"&gt;visit&lt;/span&gt; &lt;span class="kd"&gt;the&lt;/span&gt; &lt;span class="kd"&gt;webpage&lt;/span&gt; &lt;span class="kd"&gt;mentioned&lt;/span&gt; &lt;span class="kd"&gt;above&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, we can force &lt;code&gt;curl&lt;/code&gt; to trust the certificate via the &lt;code&gt;-k&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;PS&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;curl.exe&lt;/span&gt; &lt;span class="na"&gt;-k &lt;/span&gt;&lt;span class="kd"&gt;https&lt;/span&gt;://test&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com/
   ... &lt;span class="kd"&gt;full&lt;/span&gt; &lt;span class="kd"&gt;content&lt;/span&gt; &lt;span class="kd"&gt;of&lt;/span&gt; &lt;span class="kd"&gt;page&lt;/span&gt; &lt;span class="na"&gt;/var/www/html/index&lt;/span&gt;.html &lt;span class="kd"&gt;will&lt;/span&gt; &lt;span class="kd"&gt;follow&lt;/span&gt; ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we don't want the default page in &lt;code&gt;/var/www/html/index.html&lt;/code&gt; to be served, but the page in our &lt;code&gt;test-980.com&lt;/code&gt; site, so we have to create a virtual host for our site that speaks &lt;code&gt;https&lt;/code&gt;. &lt;br&gt;
We do it as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;copy default ssl conf:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; /etc/apache2/sites-available/default-ssl.conf &lt;span class="se"&gt;\&lt;/span&gt;
/var/sites/test-980.com/conf/localhost-ssl.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;adapt it to our site by adding our domain name in &lt;code&gt;ServerName&lt;/code&gt; and our html folder in &lt;code&gt;DocumentRoot&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /var/sites/test-980.com/conf/localhost-ssl.conf
...
ServerName test-980.com
...
DocumentRoot /var/sites/test-980.com/www/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We set our site available, enable it and reload Apache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /var/sites/test-980.com/conf/localhost-ssl.conf &lt;span class="se"&gt;\&lt;/span&gt;
/etc/apache2/sites-available/local-test-980.com-ssl.conf
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;a2ensite local-test-980.com-ssl.conf
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we try again we will get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;PS&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;curl.exe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-k&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;https://test-980.com/&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;DOCTYPE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;HTML&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PUBLIC&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"-//IETF//DTD HTML 2.0//EN"&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;head&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;403&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Forbidden&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;/title&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;/head&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Forbidden&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;You&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;don&lt;/span&gt;&lt;span class="s1"&gt;'t have permission to access this resource.&amp;lt;/p&amp;gt;
&amp;lt;hr&amp;gt;
&amp;lt;address&amp;gt;Apache/2.4.52 (Ubuntu) Server at test-980.com Port 443&amp;lt;/address&amp;gt;
&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's because we have to grant access to our home folder in our new ssl conf, in the same way we did in &lt;code&gt;/var/sites/test-980.com/conf/localhost.conf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, we have to modify &lt;code&gt;localhost-ssl.conf&lt;/code&gt; to add the following &lt;code&gt;Directory&lt;/code&gt; element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;$ more /var/sites/test-980.com/conf/localhost-ssl.conf
    ...
    DocumentRoot /var/sites/test-980.com/www/html
    &lt;span class="nt"&gt;&amp;lt;Directory&lt;/span&gt; &lt;span class="err"&gt;/var/sites/test-980.com/www&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      Options Indexes FollowSymLinks
      AllowOverride None
      Require all granted
    &lt;span class="nt"&gt;&amp;lt;/Directory&amp;gt;&lt;/span&gt;
    ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and reload:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo systemctl reload apache2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, we can get our home page via &lt;code&gt;https&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;PS&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;curl.exe&lt;/span&gt; &lt;span class="na"&gt;-k &lt;/span&gt;&lt;span class="kd"&gt;https&lt;/span&gt;://test&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com/
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;html&lt;/span&gt; &lt;span class="kd"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://www.w3.org/1999/xhtml"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;meta&lt;/span&gt; &lt;span class="kd"&gt;http&lt;/span&gt;&lt;span class="na"&gt;-equiv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Content-Type"&lt;/span&gt; &lt;span class="kd"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"text/html; charset=UTF-8"&lt;/span&gt; /&amp;gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="kd"&gt;test&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com: &lt;span class="kd"&gt;It&lt;/span&gt; &lt;span class="kd"&gt;works&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;/title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;/head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;body&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kd"&gt;Welcome&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;test&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;/body&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;/html&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember we are able to retrieve the page only because we have instructed &lt;code&gt;curl&lt;/code&gt; to ignore (via option &lt;code&gt;k&lt;/code&gt;) the fact that the certificate presented (or more precisely, the signer of the certificate) is not trusted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;PS&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;curl.exe&lt;/span&gt; &lt;span class="na"&gt;-k &lt;/span&gt;&lt;span class="kd"&gt;https&lt;/span&gt;://test&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com/
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;html&lt;/span&gt; &lt;span class="kd"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://www.w3.org/1999/xhtml"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;meta&lt;/span&gt; &lt;span class="kd"&gt;http&lt;/span&gt;&lt;span class="na"&gt;-equiv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Content-Type"&lt;/span&gt; &lt;span class="kd"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"text/html; charset=UTF-8"&lt;/span&gt; /&amp;gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="kd"&gt;test&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com: &lt;span class="kd"&gt;It&lt;/span&gt; &lt;span class="kd"&gt;works&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;/title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;/head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;body&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kd"&gt;Welcome&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;test&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;/body&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;/html&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

#Removing &lt;span class="kd"&gt;the&lt;/span&gt; &lt;span class="na"&gt;-k
&lt;/span&gt;&lt;span class="kd"&gt;PS&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;curl.exe&lt;/span&gt; &lt;span class="kd"&gt;https&lt;/span&gt;://test&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com/
&lt;span class="nb"&gt;curl&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;schannel&lt;/span&gt;: &lt;span class="kd"&gt;SEC_E_UNTRUSTED_ROOT&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x80090325&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="kd"&gt;La&lt;/span&gt; &lt;span class="kd"&gt;cadena&lt;/span&gt; &lt;span class="kd"&gt;de&lt;/span&gt; &lt;span class="kd"&gt;certificaci&lt;/span&gt;ón &lt;span class="kd"&gt;fue&lt;/span&gt; &lt;span class="kd"&gt;emitida&lt;/span&gt; &lt;span class="kd"&gt;por&lt;/span&gt; &lt;span class="kd"&gt;una&lt;/span&gt; &lt;span class="kd"&gt;entidad&lt;/span&gt; &lt;span class="kd"&gt;en&lt;/span&gt; &lt;span class="kd"&gt;la&lt;/span&gt; &lt;span class="kd"&gt;que&lt;/span&gt; &lt;span class="kd"&gt;no&lt;/span&gt; &lt;span class="kd"&gt;se&lt;/span&gt; &lt;span class="kd"&gt;conf&lt;/span&gt;ía.
&lt;span class="kd"&gt;More&lt;/span&gt; &lt;span class="kd"&gt;details&lt;/span&gt; &lt;span class="kd"&gt;here&lt;/span&gt;: &lt;span class="kd"&gt;https&lt;/span&gt;://curl.se/docs/sslcerts.html

&lt;span class="nb"&gt;curl&lt;/span&gt; &lt;span class="kd"&gt;failed&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;verify&lt;/span&gt; &lt;span class="kd"&gt;the&lt;/span&gt; &lt;span class="kd"&gt;legitimacy&lt;/span&gt; &lt;span class="kd"&gt;of&lt;/span&gt; &lt;span class="kd"&gt;the&lt;/span&gt; &lt;span class="kd"&gt;server&lt;/span&gt; &lt;span class="kd"&gt;and&lt;/span&gt; &lt;span class="kd"&gt;therefore&lt;/span&gt; &lt;span class="kd"&gt;could&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt;
&lt;span class="kd"&gt;establish&lt;/span&gt; &lt;span class="kd"&gt;a&lt;/span&gt; &lt;span class="kd"&gt;secure&lt;/span&gt; &lt;span class="kd"&gt;connection&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;it&lt;/span&gt;. &lt;span class="kd"&gt;To&lt;/span&gt; &lt;span class="kd"&gt;learn&lt;/span&gt; &lt;span class="nb"&gt;more&lt;/span&gt; &lt;span class="kd"&gt;about&lt;/span&gt; &lt;span class="kd"&gt;this&lt;/span&gt; &lt;span class="kd"&gt;situation&lt;/span&gt; &lt;span class="kd"&gt;and&lt;/span&gt;
&lt;span class="kd"&gt;how&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;fix&lt;/span&gt; &lt;span class="kd"&gt;it&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;please&lt;/span&gt; &lt;span class="kd"&gt;visit&lt;/span&gt; &lt;span class="kd"&gt;the&lt;/span&gt; &lt;span class="kd"&gt;webpage&lt;/span&gt; &lt;span class="kd"&gt;mentioned&lt;/span&gt; &lt;span class="kd"&gt;above&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can tell &lt;code&gt;curl&lt;/code&gt; to trust the certificate with the option &lt;code&gt;cacert&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;PS&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;curl.exe&lt;/span&gt; &lt;span class="kd"&gt;https&lt;/span&gt;://test&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com &lt;span class="na"&gt;--cacert &lt;/span&gt;&lt;span class="se"&gt;^
&lt;/span&gt;\\wsl.localhost\Ubuntu&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;.04\etc\ssl\certs\ssl&lt;span class="na"&gt;-cert-snakeoil&lt;/span&gt;.pem

&lt;span class="nb"&gt;curl&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;schannel&lt;/span&gt;: &lt;span class="kd"&gt;CertGetNameString&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;failed&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;match&lt;/span&gt; &lt;span class="kd"&gt;connection&lt;/span&gt; &lt;span class="nb"&gt;hostname&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;test&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;against&lt;/span&gt; &lt;span class="kd"&gt;server&lt;/span&gt; &lt;span class="kd"&gt;certificate&lt;/span&gt; &lt;span class="kd"&gt;names&lt;/span&gt;
&lt;span class="kd"&gt;More&lt;/span&gt; &lt;span class="kd"&gt;details&lt;/span&gt; &lt;span class="kd"&gt;here&lt;/span&gt;: &lt;span class="kd"&gt;https&lt;/span&gt;://curl.se/docs/sslcerts.html

&lt;span class="nb"&gt;curl&lt;/span&gt; &lt;span class="kd"&gt;failed&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="nb"&gt;verify&lt;/span&gt; &lt;span class="kd"&gt;the&lt;/span&gt; &lt;span class="kd"&gt;legitimacy&lt;/span&gt; &lt;span class="kd"&gt;of&lt;/span&gt; &lt;span class="kd"&gt;the&lt;/span&gt; &lt;span class="kd"&gt;server&lt;/span&gt; &lt;span class="kd"&gt;and&lt;/span&gt; &lt;span class="kd"&gt;therefore&lt;/span&gt; &lt;span class="kd"&gt;could&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt;
&lt;span class="kd"&gt;establish&lt;/span&gt; &lt;span class="kd"&gt;a&lt;/span&gt; &lt;span class="kd"&gt;secure&lt;/span&gt; &lt;span class="kd"&gt;connection&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;it&lt;/span&gt;. &lt;span class="kd"&gt;To&lt;/span&gt; &lt;span class="kd"&gt;learn&lt;/span&gt; &lt;span class="nb"&gt;more&lt;/span&gt; &lt;span class="kd"&gt;about&lt;/span&gt; &lt;span class="kd"&gt;this&lt;/span&gt; &lt;span class="kd"&gt;situation&lt;/span&gt; &lt;span class="kd"&gt;and&lt;/span&gt;
&lt;span class="kd"&gt;how&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;fix&lt;/span&gt; &lt;span class="kd"&gt;it&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;please&lt;/span&gt; &lt;span class="kd"&gt;visit&lt;/span&gt; &lt;span class="kd"&gt;the&lt;/span&gt; &lt;span class="kd"&gt;webpage&lt;/span&gt; &lt;span class="kd"&gt;mentioned&lt;/span&gt; &lt;span class="kd"&gt;above&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're not there yet. The reason is that the certificate is issued for a domaine named "DESKTOP-IUMEIDO", which is my computer's name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;openssl x509 &lt;span class="nt"&gt;-in&lt;/span&gt; /etc/ssl/certs/ssl-cert-snakeoil.pem &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-text&lt;/span&gt;|&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"Subject:"&lt;/span&gt;
        Subject: CN &lt;span class="o"&gt;=&lt;/span&gt; DESKTOP-IUMEID0.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;, whereas our request is sent to a different domain (&lt;code&gt;test-980.com&lt;/code&gt;). The client is being presented a certificate signed by someone he now trusts, but that is issued to a domain different that the one we are trying to connect to. This is deemed dangerous, hence the message and the refusal to connect.&lt;/p&gt;

&lt;p&gt;In next section, we'll see how to create a server certificate for our domain &lt;code&gt;test-980&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create SSL server certificate
&lt;/h2&gt;

&lt;p&gt;First, let's generate a key of length 2048:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ openssl genrsa -out test-980.com.key 2048&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now we need to create a &lt;code&gt;certificate sign request&lt;/code&gt; or &lt;code&gt;csr&lt;/code&gt;. We will be asked to provide information about the owner of the certificate such as it's company name, it's country, etc... Only &lt;code&gt;Common Name&lt;/code&gt; is mandatory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-key&lt;/span&gt; test-980.com.key &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-out&lt;/span&gt; test-980.com.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter &lt;span class="s1"&gt;'.'&lt;/span&gt;, the field will be left blank.
&lt;span class="nt"&gt;-----&lt;/span&gt;
Country Name &lt;span class="o"&gt;(&lt;/span&gt;2 letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU]:.
State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State]:.
Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:.
Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd]:.
Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:.
Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:test-980.com
Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:.

Please enter the following &lt;span class="s1"&gt;'extra'&lt;/span&gt; attributes
to be sent with your certificate request
A challenge password &lt;span class="o"&gt;[]&lt;/span&gt;:.
An optional company name &lt;span class="o"&gt;[]&lt;/span&gt;:.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we sign the request with the key generated above. This will generate our certificate and place it in the file specified in &lt;code&gt;out&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;openssl x509 &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-in&lt;/span&gt; test-980.com.csr &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-signkey&lt;/span&gt; test-980.com.key &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-out&lt;/span&gt; test-980.com.crt
Certificate request self-signature ok
&lt;span class="nv"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;CN &lt;span class="o"&gt;=&lt;/span&gt; test-980.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we list our current folder, we will see the 3 files that we have just generated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;test-980&lt;span class="k"&gt;*&lt;/span&gt;
test-980.com.crt  test-980.com.csr  test-980.com.key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our certificate is the &lt;code&gt;crt&lt;/code&gt; file.&lt;br&gt;
We will now copy the &lt;code&gt;crt&lt;/code&gt; and the &lt;code&gt;key&lt;/code&gt; files inside our &lt;code&gt;test-980.com&lt;/code&gt;'s site configuration folder and reference them in our ssl conf file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cp &lt;/span&gt;test-980.com.crt /var/sites/test-980.com/conf
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cp &lt;/span&gt;test-980.com.key /var/sites/test-980.com/conf

&lt;span class="c"&gt;#Modify localhost-ssl.conf to point to our new files:&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /var/sites/test-980.com/conf/localhost-ssl.conf|grep SSLCertificate
SSLCertificateFile      /var/sites/test-980.com/conf/test-980.com.crt
SSLCertificateKeyFile   /var/sites/test-980.com/conf/test-980.com.key

&lt;span class="c"&gt;#restart:&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl stop apache2.service
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start apache2.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's now copy the server certificate in our windows home folder (notice I've been using all this time my &lt;code&gt;curl&lt;/code&gt; tool in Windows) for the sake of legibility:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;PS&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;cp&lt;/span&gt; \\wsl.localhost\Ubuntu&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;.04\var\sites\test&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com\conf\test&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com.crt .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we try again, it should work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;PS&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;curl.exe&lt;/span&gt; &lt;span class="kd"&gt;https&lt;/span&gt;://test&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com &lt;span class="na"&gt;--cacert &lt;/span&gt;&lt;span class="kd"&gt;test&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com.crt
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;html&lt;/span&gt; &lt;span class="kd"&gt;xmlns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://www.w3.org/1999/xhtml"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;meta&lt;/span&gt; &lt;span class="kd"&gt;http&lt;/span&gt;&lt;span class="na"&gt;-equiv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Content-Type"&lt;/span&gt; &lt;span class="kd"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"text/html; charset=UTF-8"&lt;/span&gt; /&amp;gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="kd"&gt;test&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com: &lt;span class="kd"&gt;It&lt;/span&gt; &lt;span class="kd"&gt;works&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;/title&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;/head&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;body&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="kd"&gt;Welcome&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;test&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;/body&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="na"&gt;/html&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create SSL client certificate
&lt;/h2&gt;

&lt;p&gt;We can instruct our server to require a certificate to the client by editing &lt;code&gt;localhost-ssl.conf&lt;/code&gt; as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;uncomment the following line:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;SSLVerifyClient require&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;indicate where our signer certificate is with:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;SSLCACertificateFile /var/sites/test-980.com/conf/test-980.com.crt&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After restarting the server, we can't access our page anymore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;PS&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;curl.exe&lt;/span&gt; &lt;span class="kd"&gt;https&lt;/span&gt;://test&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com &lt;span class="na"&gt;--cacert &lt;/span&gt;&lt;span class="kd"&gt;test&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com.crt
&lt;span class="nb"&gt;curl&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;56&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;schannel&lt;/span&gt;: &lt;span class="kd"&gt;failed&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;read&lt;/span&gt; &lt;span class="kd"&gt;data&lt;/span&gt; &lt;span class="kd"&gt;from&lt;/span&gt; &lt;span class="kd"&gt;server&lt;/span&gt;: &lt;span class="kd"&gt;SEC_E_ILLEGAL_MESSAGE&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x80090326&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="kd"&gt;This&lt;/span&gt; &lt;span class="kd"&gt;error&lt;/span&gt; &lt;span class="kd"&gt;usually&lt;/span&gt; &lt;span class="kd"&gt;occurs&lt;/span&gt; &lt;span class="kd"&gt;when&lt;/span&gt; &lt;span class="kd"&gt;a&lt;/span&gt; &lt;span class="kd"&gt;fatal&lt;/span&gt; &lt;span class="kd"&gt;SSL&lt;/span&gt;&lt;span class="na"&gt;/TLS &lt;/span&gt;&lt;span class="kd"&gt;alert&lt;/span&gt; &lt;span class="kd"&gt;is&lt;/span&gt; &lt;span class="kd"&gt;received&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;e&lt;/span&gt;.g. &lt;span class="kd"&gt;handshake&lt;/span&gt; &lt;span class="kd"&gt;failed&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;. &lt;span class="kd"&gt;More&lt;/span&gt; &lt;span class="kd"&gt;detail&lt;/span&gt; &lt;span class="kd"&gt;may&lt;/span&gt; &lt;span class="kd"&gt;be&lt;/span&gt; &lt;span class="kd"&gt;available&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kd"&gt;the&lt;/span&gt; &lt;span class="kd"&gt;Windows&lt;/span&gt; &lt;span class="kd"&gt;System&lt;/span&gt; &lt;span class="kd"&gt;event&lt;/span&gt; &lt;span class="kd"&gt;log&lt;/span&gt;.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The message is quite cryptic but it is due to our &lt;code&gt;curl&lt;/code&gt; client not providing a certificate.&lt;/p&gt;

&lt;p&gt;Let's then create a client certificate for &lt;code&gt;James Bond&lt;/code&gt; and sign it with our &lt;code&gt;test-980.com&lt;/code&gt; server certificate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#Step 1: generate key&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;openssl genpkey &lt;span class="nt"&gt;-algorithm&lt;/span&gt; RSA &lt;span class="nt"&gt;-out&lt;/span&gt; james.bond.key

&lt;span class="c"&gt;#Step 2: generate request&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;openssl req &lt;span class="nt"&gt;-new&lt;/span&gt; &lt;span class="nt"&gt;-key&lt;/span&gt; james.bond.key &lt;span class="nt"&gt;-out&lt;/span&gt; james.bond.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter &lt;span class="s1"&gt;'.'&lt;/span&gt;, the field will be left blank.
&lt;span class="nt"&gt;-----&lt;/span&gt;
Country Name &lt;span class="o"&gt;(&lt;/span&gt;2 letter code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;AU]:.
State or Province Name &lt;span class="o"&gt;(&lt;/span&gt;full name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Some-State]:.
Locality Name &lt;span class="o"&gt;(&lt;/span&gt;eg, city&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:.
Organization Name &lt;span class="o"&gt;(&lt;/span&gt;eg, company&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Internet Widgits Pty Ltd]:.
Organizational Unit Name &lt;span class="o"&gt;(&lt;/span&gt;eg, section&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:.
Common Name &lt;span class="o"&gt;(&lt;/span&gt;e.g. server FQDN or YOUR name&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;:BOND.James
Email Address &lt;span class="o"&gt;[]&lt;/span&gt;:.

Please enter the following &lt;span class="s1"&gt;'extra'&lt;/span&gt; attributes
to be sent with your certificate request
A challenge password &lt;span class="o"&gt;[]&lt;/span&gt;:.
An optional company name &lt;span class="o"&gt;[]&lt;/span&gt;:.

&lt;span class="c"&gt;#Step 3: generate the certificate and sign it with our test-980.com server &lt;/span&gt;
&lt;span class="c"&gt;#certificate (notice that all files in the command are assumed to be in &lt;/span&gt;
&lt;span class="c"&gt;#current folder):&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;openssl x509 &lt;span class="nt"&gt;-req&lt;/span&gt; &lt;span class="nt"&gt;-in&lt;/span&gt; james.bond.csr &lt;span class="nt"&gt;-CA&lt;/span&gt; test-980.com.crt &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-CAkey&lt;/span&gt; test-980.com.key &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-CAcreateserial&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-out&lt;/span&gt; james.bond.crt &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-days&lt;/span&gt; 365 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-sha256&lt;/span&gt;
Certificate request self-signature ok
&lt;span class="nv"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;CN &lt;span class="o"&gt;=&lt;/span&gt; BOND.James

&lt;span class="c"&gt;#Step 4: optional&lt;/span&gt;
&lt;span class="c"&gt;#If we want to import it in our browser or test it via curl in Windows, &lt;/span&gt;
&lt;span class="c"&gt;#we might need to convert it to .pfx format:&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;openssl pkcs12 &lt;span class="nt"&gt;-export&lt;/span&gt; &lt;span class="nt"&gt;-out&lt;/span&gt; james.bond.pfx &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-inkey&lt;/span&gt; james.bond.key &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-in&lt;/span&gt; james.bond.crt
Enter Export Password: mypwd
Verifying - Enter Export Password: mypwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's copy the &lt;code&gt;.pfx&lt;/code&gt; in our Windows machine and try again by providing our client certificate and the password wiht the &lt;code&gt;--cert&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;PS&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;curl.exe&lt;/span&gt; &lt;span class="kd"&gt;https&lt;/span&gt;://test&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com/ &lt;span class="se"&gt;^
&lt;/span&gt;&lt;span class="na"&gt;--cacert &lt;/span&gt;./test&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;980&lt;/span&gt;.com.crt &lt;span class="se"&gt;^
&lt;/span&gt;&lt;span class="na"&gt;--cert &lt;/span&gt;&lt;span class="kd"&gt;james&lt;/span&gt;.bond.pfx:mypwd
&lt;span class="nb"&gt;curl&lt;/span&gt;: &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;35&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;schannel&lt;/span&gt;: &lt;span class="kd"&gt;next&lt;/span&gt; &lt;span class="kd"&gt;InitializeSecurityContext&lt;/span&gt; &lt;span class="kd"&gt;failed&lt;/span&gt;: &lt;span class="kd"&gt;SEC_E_INTERNAL_ERROR&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x80090304&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="kd"&gt;No&lt;/span&gt; &lt;span class="kd"&gt;es&lt;/span&gt; &lt;span class="kd"&gt;posible&lt;/span&gt; &lt;span class="kd"&gt;ponerse&lt;/span&gt; &lt;span class="kd"&gt;en&lt;/span&gt; &lt;span class="kd"&gt;contacto&lt;/span&gt; &lt;span class="kr"&gt;con&lt;/span&gt; &lt;span class="kd"&gt;la&lt;/span&gt; &lt;span class="kd"&gt;autoridad&lt;/span&gt; &lt;span class="kd"&gt;de&lt;/span&gt; &lt;span class="kd"&gt;seguridad&lt;/span&gt; &lt;span class="kd"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's not working but it should :( . You might want to check &lt;a href="https://learn.microsoft.com/en-au/answers/questions/2138549/curl-(35)-schannel-acquirecredentialshandle-failed" rel="noopener noreferrer"&gt;this article&lt;/a&gt; for the reasons behind and try your luck, but I rather have my balls torched than messing around with my Windows registry. I will use my Chrome browser instead.&lt;/p&gt;

&lt;p&gt;To import the client certificate in Chrome, go to &lt;code&gt;chrome://certificate-manager/clientcerts&lt;/code&gt; and from there I'm sure you'll manage.&lt;/p&gt;

&lt;p&gt;Now, when accessing our site via https, we will be asked to select a client certificate:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82ykhyxwed8u0rzifkd8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82ykhyxwed8u0rzifkd8.png" alt=" " width="784" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you select it and click OK, you'll be granted access to the site:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0tw86sgiss887e2pghuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0tw86sgiss887e2pghuy.png" alt=" " width="657" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>security</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Set up a reverse proxy in Linux</title>
      <dc:creator>Jesús G. Calderín</dc:creator>
      <pubDate>Tue, 23 Sep 2025 21:23:29 +0000</pubDate>
      <link>https://dev.to/jess_garcacaldern_028/set-up-a-reverse-proxy-in-linux-4ce9</link>
      <guid>https://dev.to/jess_garcacaldern_028/set-up-a-reverse-proxy-in-linux-4ce9</guid>
      <description>&lt;p&gt;A "reverse proxy" is just a web server that is placed in-between one or more application servers (the "back-end") and their clients, so that the back-end is only accessible via requests sent to the proxy. The latter will in turn decide whether to forward the request to the backend, to which server it should send it and many other considerations. The proxy is not only isolating the servers from the clients but providing added value like caching static content, load-balancing, etc...&lt;/p&gt;

&lt;p&gt;It's called "reverse" in contrast with "forward proxies", that are placed in front of clients to provide them as well with different functionalities.&lt;/p&gt;

&lt;p&gt;The distinction is blurry but overall, we can say that a reverse-proxy is intended to serve servers and a forward-proxy to serve clients.&lt;/p&gt;

&lt;p&gt;This little guide refers to a reverse-proxy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;1) Install and configure a &lt;a href="https://dev.to/jess_garcacaldern_028/setup-tomcat-cluster-in-linux-407k"&gt;Tomcat cluster&lt;/a&gt;, and set the following environment variables in ~/.bashrc:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$TOMCAT1_HOME=&amp;lt;your tomcat1 home folder&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;$TOMCAT2_HOME=&amp;lt;your tomcat2 home folder&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;2) Verify Linux's builtin apache is installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status apache2
● apache2.service - The Apache HTTP Server
     Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/lib/systemd/system/apache2.service&lt;span class="p"&gt;;&lt;/span&gt; 
     enabled&lt;span class="p"&gt;;&lt;/span&gt; vendor preset: enabled&lt;span class="o"&gt;)&lt;/span&gt;
     Active: active &lt;span class="o"&gt;(&lt;/span&gt;running&lt;span class="o"&gt;)&lt;/span&gt; since Sun 2025-09-21 12:43:12 CEST&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create a new website
&lt;/h2&gt;

&lt;p&gt;Specify in .bashrc the home folder of our new website:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 3 ~/.bashrc
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TOMCAT1_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/apps/myapp/clus1/tomcat1"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TOMCAT2_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/apps/myapp/clus1/tomcat2"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MYSITE_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/var/sites/mysite"&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;, and also set it in &lt;em&gt;/etc/apache2/envvars&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; 1 /etc/apache2/envvars
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MYSITE_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/var/sites/mysite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create our new website's &lt;em&gt;conf&lt;/em&gt; and &lt;em&gt;www/html&lt;/em&gt; folders:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$MYSITE_HOME&lt;/span&gt;/conf
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;$MYSITE_HOME&lt;/span&gt;/www/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an &lt;em&gt;index.html&lt;/em&gt; inside &lt;em&gt;$MYSITE_HOME/www/html&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;$ cat $MYSITE_HOME/www/html/index.html
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/1999/xhtml"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"text/html; charset=UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;MySite Default Page: It works&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        Welcome to MySite
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a virtual host for our site
&lt;/h3&gt;

&lt;p&gt;We copy the default conf from built-in apache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; /etc/apache2/sites-available/000-default.conf &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nv"&gt;$MYSITE_HOME&lt;/span&gt;/conf/localhost.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;, and add the following lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;$ cat $MYSITE_HOME/conf/localhost.conf
&lt;span class="nt"&gt;&amp;lt;VirtualHost&lt;/span&gt; &lt;span class="err"&gt;*:80&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        ServerName localhost
        ServerAdmin webmaster@localhost

        DocumentRoot ${MYSITE_HOME}/www/html
        &lt;span class="nt"&gt;&amp;lt;Directory&lt;/span&gt; &lt;span class="err"&gt;${MYSITE_HOME}/www&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
          Options Indexes FollowSymLinks
          AllowOverride None
          Require all granted
        &lt;span class="nt"&gt;&amp;lt;/Directory&amp;gt;&lt;/span&gt;

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

&lt;span class="nt"&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enable our site
&lt;/h3&gt;

&lt;p&gt;We first make our site available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;$MYSITE_HOME&lt;/span&gt;/conf/localhost.conf &lt;span class="se"&gt;\&lt;/span&gt;
/etc/apache2/sites-available/local-localhost.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;, and then we enable it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;a2ensite local-localhost
Enabling site local-localhost.
To activate the new configuration, you need to run:
  systemctl reload apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, stop and restart apache:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo systemctl stop apache2&lt;/code&gt;&lt;br&gt;
&lt;code&gt;$ sudo systemctl start apache2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;, and test that our new site works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;$ curl http://localhost
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/1999/xhtml"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"text/html; charset=UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;MySite Default Page: It works&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
        Welcome to MySite
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Set up mod_jk
&lt;/h2&gt;

&lt;p&gt;There are two modules that I know for our apache web server to communicate with our backend Tomcat servers: &lt;em&gt;mod_proxy&lt;/em&gt; and &lt;em&gt;mod_jk&lt;/em&gt;.&lt;br&gt;
I'm going to use the &lt;em&gt;mod_jk&lt;/em&gt; plugin, which will communicate via the AJP protocol.&lt;/p&gt;
&lt;h3&gt;
  
  
  Enable AJP
&lt;/h3&gt;

&lt;p&gt;First thing is to enable the AJP connectors in our Tomcats, which are disabled by default.&lt;br&gt;
For that, we need to go to &lt;em&gt;server.xml&lt;/em&gt; and uncomment the AJP connector element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;$ cat $TOMCAT1_HOME/conf/server.xml
    &lt;span class="c"&gt;&amp;lt;!-- Define an AJP 1.3 Connector on port 8009 --&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;Connector&lt;/span&gt; &lt;span class="na"&gt;protocol=&lt;/span&gt;&lt;span class="s"&gt;"AJP/1.3"&lt;/span&gt;
               &lt;span class="na"&gt;address=&lt;/span&gt;&lt;span class="s"&gt;"localhost"&lt;/span&gt;
               &lt;span class="na"&gt;port=&lt;/span&gt;&lt;span class="s"&gt;"8009"&lt;/span&gt;
               &lt;span class="na"&gt;redirectPort=&lt;/span&gt;&lt;span class="s"&gt;"8443"&lt;/span&gt;
               &lt;span class="na"&gt;maxParameterCount=&lt;/span&gt;&lt;span class="s"&gt;"1000"&lt;/span&gt;
               &lt;span class="na"&gt;secretRequired=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
               &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;N.B:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I had to add &lt;em&gt;secretRequired="false"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;The defaul value in &lt;em&gt;address&lt;/em&gt; is "::1", but that doesn't work for me, so I set it to "localhost", although "127.0.0.1" will also do.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do the same for tomcat2 but don't forget to use a different port, cause both tomcats are on the same machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Define an AJP 1.3 Connector on port 9009 --&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;Connector&lt;/span&gt; &lt;span class="na"&gt;protocol=&lt;/span&gt;&lt;span class="s"&gt;"AJP/1.3"&lt;/span&gt;
               &lt;span class="na"&gt;address=&lt;/span&gt;&lt;span class="s"&gt;"127.0.0.1"&lt;/span&gt;
               &lt;span class="na"&gt;port=&lt;/span&gt;&lt;span class="s"&gt;"9009"&lt;/span&gt;
               &lt;span class="na"&gt;redirectPort=&lt;/span&gt;&lt;span class="s"&gt;"8443"&lt;/span&gt;
               &lt;span class="na"&gt;maxParameterCount=&lt;/span&gt;&lt;span class="s"&gt;"1000"&lt;/span&gt;
               &lt;span class="na"&gt;secretRequired=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt;
               &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After restarting the tomcats, we should see both AJP ports in use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;netstat &lt;span class="nt"&gt;-nlp&lt;/span&gt;|grep &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"8009|9009"&lt;/span&gt;
tcp6       0      0 127.0.0.1:8009  :::&lt;span class="k"&gt;*&lt;/span&gt;  LISTEN      60789/java
tcp6       0      0 127.0.0.1:9009  :::&lt;span class="k"&gt;*&lt;/span&gt;  LISTEN      120768/java
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So our situation is that our &lt;em&gt;examples&lt;/em&gt; application is available via our tomcats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; http://localhost:8080/examples/
200
&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; http://localhost:9080/examples/
200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but not yet via our apache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"%{http_code}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; http://localhost/examples/
404
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's what we will try to achieve with mod_jk: that requests for &lt;em&gt;examples&lt;/em&gt; app are forwarded to the tomcats.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure and enable mod_jk
&lt;/h3&gt;

&lt;p&gt;First we copy the default mod_jk conf:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; /etc/apache2/mods-available/jk.conf &lt;span class="nv"&gt;$MYSITE_HOME&lt;/span&gt;/conf/jk.conf
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; /etc/apache2/mods-available/jk.load &lt;span class="nv"&gt;$MYSITE_HOME&lt;/span&gt;/conf/jk.load
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we create 2 files inside $MYSITE_HOME/conf:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;workers.properties&lt;/strong&gt;: will contain pointers to our tomcat AJP connectors and will define a load-balancer type worker.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;uriworkermap.properties&lt;/strong&gt;: will contain the mapping from &lt;em&gt;/examples&lt;/em&gt; uri to our load-balancer.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="err"&gt;cat&lt;/span&gt; &lt;span class="err"&gt;$MYSITE_HOME/conf/workers.properties&lt;/span&gt;
&lt;span class="py"&gt;worker.list&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;worker1, worker2, lb&lt;/span&gt;

&lt;span class="c"&gt;# Set properties for worker1 (our tomcat1 server)
&lt;/span&gt;&lt;span class="py"&gt;worker.worker1.type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ajp13&lt;/span&gt;
&lt;span class="py"&gt;worker.worker1.host&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;
&lt;span class="py"&gt;worker.worker1.port&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;8009&lt;/span&gt;

&lt;span class="c"&gt;# Set properties for worker2 (our tomcat2 server)
&lt;/span&gt;&lt;span class="py"&gt;worker.worker2.type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ajp13&lt;/span&gt;
&lt;span class="py"&gt;worker.worker2.host&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;
&lt;span class="py"&gt;worker.worker2.port&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;9009&lt;/span&gt;

&lt;span class="py"&gt;worker.lb.type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;lb&lt;/span&gt;
&lt;span class="py"&gt;worker.lb.balance_workers&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;worker1, worker2&lt;/span&gt;

&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="err"&gt;cat&lt;/span&gt; &lt;span class="err"&gt;$MYSITE_HOME/conf/uriworkermap.properties&lt;/span&gt;
&lt;span class="c"&gt;# Send everything for context /examples to load-balancer worker
&lt;/span&gt;&lt;span class="err"&gt;/examples/*=lb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we point to these 2 files in our &lt;em&gt;jk.conf&lt;/em&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$MYSITE_HOME&lt;/span&gt;/conf/jk.conf
...
JkWorkersFile &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MYSITE_HOME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/conf/workers.properties
...
JkMountFile &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MYSITE_HOME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/conf/uriworkermap.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The configuration is finished.&lt;/p&gt;

&lt;p&gt;Next, we make our module available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;$MYSITE_HOME&lt;/span&gt;/conf/jk.conf &lt;span class="se"&gt;\&lt;/span&gt;
/etc/apache2/mods-available/local-jk.conf
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;$MYSITE_HOME&lt;/span&gt;/conf/jk.load &lt;span class="se"&gt;\&lt;/span&gt;
/etc/apache2/mods-available/local-jk.load
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now have to disable the default mod_jk cause only one &lt;em&gt;JkWorkersFile&lt;/em&gt; is permitted:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ sudo a2dismod jk&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, enable our custom jk and reload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;a2enmod local-jk
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload apache2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the forwarding should work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;$ curl http://localhost/examples/
&lt;span class="cp"&gt;&amp;lt;!DOCTYPE HTML&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Apache Tomcat Examples&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt;Apache Tomcat Examples&lt;span class="nt"&gt;&amp;lt;/H3&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"servlets"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Servlets examples&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"jsp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;JSP Examples&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"websocket/index.xhtml"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;WebSocket Examples&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we will test that load-balancing, sticky sessions and fail-over are all working as expected:&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing load-balancing
&lt;/h3&gt;

&lt;p&gt;To test that sessions are balanced, we can use servlet &lt;em&gt;SessionExample&lt;/em&gt; in the &lt;em&gt;examples&lt;/em&gt; app.&lt;/p&gt;

&lt;p&gt;I have modified the following file&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$TOMCAT_HOME/webapps/examples/WEB-INF/classes/LocalStrings.properties&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;in both tomcats to include the literal "1" and "2" respectively at the end of the following property:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sessions.title=Sessions Example Tomcat&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;, so I can easily identify to which tomcat requests are being forwarded.&lt;/p&gt;

&lt;p&gt;Running different requests should bounce alternatively (or nearly) between tomcat1 and tomcat2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://localhost/examples/servlets/servlet/SessionExample|&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;title&amp;gt;Sessions Example"&lt;/span&gt;
&amp;lt;title&amp;gt;Sessions Example Tomcat 1&amp;lt;/title&amp;gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://localhost/examples/servlets/servlet/SessionExample|&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;title&amp;gt;Sessions Example"&lt;/span&gt;
&amp;lt;title&amp;gt;Sessions Example Tomcat 2&amp;lt;/title&amp;gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://localhost/examples/servlets/servlet/SessionExample|&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;title&amp;gt;Sessions Example"&lt;/span&gt;
&amp;lt;title&amp;gt;Sessions Example Tomcat 1&amp;lt;/title&amp;gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://localhost/examples/servlets/servlet/SessionExample|&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;title&amp;gt;Sessions Example"&lt;/span&gt;
&amp;lt;title&amp;gt;Sessions Example Tomcat 2&amp;lt;/title&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing sticky sessions
&lt;/h3&gt;

&lt;p&gt;For sticky sessions to work, we have to set the &lt;em&gt;jvmRoute&lt;/em&gt; attribute in the engine element in tomcat's &lt;em&gt;server.xml&lt;/em&gt; to the name of the respective node from &lt;em&gt;workers.properties&lt;/em&gt; file (worker1 and worker2 in our case):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;Engine jvmRoute="worker1" name="Catalina" ...&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;&amp;lt;Engine jvmRoute="worker2" name="Catalina" ...&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;--include&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"server.xml"&lt;/span&gt; &lt;span class="s2"&gt;"jvmRoute="&lt;/span&gt; /apps/myapp/clus1
/tomcat2/conf/server.xml:    &amp;lt;Engine &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Catalina"&lt;/span&gt; &lt;span class="nv"&gt;defaultHost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt; &lt;span class="nv"&gt;jvmRoute&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"worker2"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
/tomcat1/conf/server.xml:    &amp;lt;Engine &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Catalina"&lt;/span&gt; &lt;span class="nv"&gt;defaultHost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt; &lt;span class="nv"&gt;jvmRoute&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"worker1"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To test that requests belonging to the same session "stick" to the same server, we can send the cookie JSESSIONID filled with the ID returned by the first request and check both that ID returned is the same and receiving tomcat too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://localhost/examples/servlets/servlet/SessionExample|&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"Session ID"&lt;/span&gt; &lt;span class="nt"&gt;-B&lt;/span&gt; 1
&amp;lt;h3&amp;gt;Sessions Example Tomcat 1&amp;lt;/h3&amp;gt;
Session ID: 160ECEE2FE688B6649DC109F03EA1C7B.worker1

&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;--cookie&lt;/span&gt; &lt;span class="s2"&gt;"JSESSIONID=160ECEE2FE688B6649DC109F03EA1C7B.worker1"&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
http://localhost/examples/servlets/servlet/SessionExample|&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"Session ID"&lt;/span&gt; &lt;span class="nt"&gt;-B&lt;/span&gt; 1
&amp;lt;h3&amp;gt;Sessions Example Tomcat 1&amp;lt;/h3&amp;gt;
Session ID: 160ECEE2FE688B6649DC109F03EA1C7B.worker1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing fail-over
&lt;/h3&gt;

&lt;p&gt;We will proceed with the following sequence&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;send a request&lt;/li&gt;
&lt;li&gt;note which tomcat served it and which session ID is returned&lt;/li&gt;
&lt;li&gt;stop that tomcat&lt;/li&gt;
&lt;li&gt;send another request for the same session via JESSIONID cookie&lt;/li&gt;
&lt;li&gt;verify that the other tomcat has served it and the JESSSIONID returned is the same
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://localhost/examples/servlets/servlet/SessionExample|&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;h3&amp;gt;Sessions Example"&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; 1
&amp;lt;h3&amp;gt;Sessions Example Tomcat 1&amp;lt;/h3&amp;gt;
Session ID: 2D3B488194BBC78479370196455D4384.worker1

&lt;span class="nv"&gt;$ &lt;/span&gt;/apps/myapp/clus1/tomcat1/shutdown.sh
Using CATALINA_BASE:   /apps/myapp/clus1/tomcat1
Using CATALINA_HOME:   /opt/apache-tomcat-9.0.109
Using CATALINA_TMPDIR: /apps/myapp/clus1/tomcat1/temp
Using JRE_HOME:        /opt/jdk1.8.0_451
Using CLASSPATH:       /opt/apache-tomcat-9.0.109/bin/bootstrap.jar:
/opt/apache-tomcat-9.0.109/bin/tomcat-juli.jar
Using CATALINA_OPTS:

&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;--cookie&lt;/span&gt; &lt;span class="s2"&gt;"JSESSIONID=2D3B488194BBC78479370196455D4384.worker1"&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
http://localhost/examples/servlets/servlet/SessionExample|&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;h3&amp;gt;Sessions Example"&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt; 1
&amp;lt;h3&amp;gt;Sessions Example Tomcat 2&amp;lt;/h3&amp;gt;
Session ID: 2D3B488194BBC78479370196455D4384.worker2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>networking</category>
      <category>tutorial</category>
      <category>devops</category>
      <category>linux</category>
    </item>
    <item>
      <title>Setup Tomcat cluster in Linux</title>
      <dc:creator>Jesús G. Calderín</dc:creator>
      <pubDate>Sat, 20 Sep 2025 17:45:29 +0000</pubDate>
      <link>https://dev.to/jess_garcacaldern_028/setup-tomcat-cluster-in-linux-407k</link>
      <guid>https://dev.to/jess_garcacaldern_028/setup-tomcat-cluster-in-linux-407k</guid>
      <description>&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install Java
&lt;/h3&gt;

&lt;p&gt;And set JAVA_HOME variable accordingly in &lt;em&gt;~/.bashrc&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;JAVA_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/jdk1.8.0_451
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install Tomcat
&lt;/h3&gt;

&lt;p&gt;And set CATALINA_HOME accordingly in &lt;em&gt;~/.bashrc&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CATALINA_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/opt/apache-tomcat-9.0.109
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create two instances of our Tomcat
&lt;/h2&gt;

&lt;p&gt;(Kudos to &lt;a href="https://stackoverflow.com/users/2617995/goran-vasic" rel="noopener noreferrer"&gt;Goran Vasic&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;They will be the two nodes of our cluster.&lt;/p&gt;

&lt;p&gt;First, we create one empty directory for our first tomcat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /apps/myapp/clus1/tomcat1/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we copy inside the following folders from CATALINA_HOME:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;/conf&lt;/li&gt;
&lt;li&gt;/webapps
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="nv"&gt;$CATALINA_HOME&lt;/span&gt;/conf    /apps/myapp/clus1/tomcat1/
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="nv"&gt;$CATALINA_HOME&lt;/span&gt;/webapps /apps/myapp/clus1/tomcat1/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will also need to create an empty &lt;em&gt;logs&lt;/em&gt; folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /apps/myapp/clus1/tomcat1/logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we create start and stop scripts that set our CATALINA_BASE accordingly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /apps/myapp/clus1/tomcat1/startup.sh
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CATALINA_BASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/apps/myapp/clus1/tomcat1"&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$CATALINA_HOME&lt;/span&gt;/bin
&lt;span class="nv"&gt;TITLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tomcat1
./startup.sh &lt;span class="nv"&gt;$TITLE&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /apps/myapp/clus1/tomcat1/shutdown.sh
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CATALINA_BASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/apps/myapp/clus1/tomcat1"&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;$CATALINA_HOME&lt;/span&gt;/bin
./shutdown.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now turn the files executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;u+x /apps/myapp/clus1/tomcat1/startup.sh
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;u+x /apps/myapp/clus1/tomcat1/shutdown.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And test them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;/apps/myapp/clus1/tomcat1/startup.sh
Using CATALINA_BASE:   /apps/myapp/clus1/tomcat1
Using CATALINA_HOME:   /opt/apache-tomcat-9.0.109
Using CATALINA_TMPDIR: /apps/myapp/clus1/tomcat1/temp
Using JRE_HOME:        /opt/jdk1.8.0_451
Using CLASSPATH:       /opt/apache-tomcat-9.0.109/bin/bootstrap.jar:/opt/apache-tomcat-9.0.109/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Tomcat started.

&lt;span class="nv"&gt;$ &lt;/span&gt;/apps/myapp/clus1/tomcat1/shutdown.sh
Using CATALINA_BASE:   /apps/myapp/clus1/tomcat1
Using CATALINA_HOME:   /opt/apache-tomcat-9.0.109
Using CATALINA_TMPDIR: /apps/myapp/clus1/tomcat1/temp
Using JRE_HOME:        /opt/jdk1.8.0_451
Using CLASSPATH:       /opt/apache-tomcat-9.0.109/bin/bootstrap.jar:/opt/apache-tomcat-9.0.109/bin/tomcat-juli.jar
Using CATALINA_OPTS:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now need to create the same start/shutdown scripts for &lt;strong&gt;tomcat2&lt;/strong&gt;, but bear in mind that since we are running our tomcats on the same machine, we need to use different listening and shutdown ports in each of them, otherwise the start and stop will fail. In my case, I'm going to replace default 8080 by 9080 in tomcat2's &lt;em&gt;$CATALINA_BASE/conf/server.xml&lt;/em&gt; listening port:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;Connector port="9080" protocol="HTTP/1.1"&lt;br&gt;
               connectionTimeout="20000"&lt;br&gt;
               redirectPort="8443"&lt;br&gt;
               maxParameterCount="1000"&lt;br&gt;
               /&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;, and replace 8005 by 9005 in shutdown's port:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;Server port="9005" shutdown="SHUTDOWN"&amp;gt;&lt;br&gt;
  &amp;lt;Listener className="org.apache.catalina.startup.VersionLoggerListener" /&amp;gt;...&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After starting both tomcats, we can see the ports they are using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;netstat &lt;span class="nt"&gt;-nlp&lt;/span&gt;|grep &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'8080|9080'&lt;/span&gt;
tcp6       0      0 :::8080  :::&lt;span class="k"&gt;*&lt;/span&gt;   LISTEN      20941/java
tcp6       0      0 :::9080  :::&lt;span class="k"&gt;*&lt;/span&gt;   LISTEN      21014/java

&lt;span class="nv"&gt;$ &lt;/span&gt;lsof &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; |grep 20941
java    20941 TCP &lt;span class="k"&gt;*&lt;/span&gt;:8080 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java    20941 TCP localhost:8005 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;lsof &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; |grep 21014
java    21014  TCP &lt;span class="k"&gt;*&lt;/span&gt;:9080 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java    21014  TCP localhost:9005 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Activate the cluster
&lt;/h2&gt;

&lt;p&gt;We just need to uncomment the &lt;em&gt;Cluster&lt;/em&gt; element under &lt;em&gt;Engine&lt;/em&gt; in both tomcat's &lt;em&gt;$CATALINA_BASE/conf/server.xml&lt;/em&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;, and restart.&lt;br&gt;
This will make them multicast their membership to default 228.0.0.4 and port 45564, and will listen on the first port available between 4000-4100:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;netstat &lt;span class="nt"&gt;-nlp&lt;/span&gt;|grep 45564
udp6       0      0 :::45564    :::&lt;span class="k"&gt;*&lt;/span&gt;  13411/java
udp6       0      0 :::45564    :::&lt;span class="k"&gt;*&lt;/span&gt;  13273/java
&lt;span class="nv"&gt;$ &lt;/span&gt;lsof &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; |grep 13411
java    13411 TCP &lt;span class="k"&gt;*&lt;/span&gt;:9080 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java    13411 TCP DESKTOP-IUMEID0.:4001 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java    13411 UDP &lt;span class="k"&gt;*&lt;/span&gt;:45564
java    13411 TCP localhost:42728-&amp;gt;DESKTOP-IUMEID0.:4000 &lt;span class="o"&gt;(&lt;/span&gt;ESTABLISHED&lt;span class="o"&gt;)&lt;/span&gt;
java    13411 TCP DESKTOP-IUMEID0.:4001-&amp;gt;localhost:36104 &lt;span class="o"&gt;(&lt;/span&gt;ESTABLISHED&lt;span class="o"&gt;)&lt;/span&gt;
java    13411 TCP localhost:9005 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;lsof &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; |grep 13273
java    13273  TCP &lt;span class="k"&gt;*&lt;/span&gt;:8080 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java    13273  TCP DESKTOP-IUMEID0.:4000 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java    13273  UDP &lt;span class="k"&gt;*&lt;/span&gt;:45564
java    13273  TCP localhost:8005 &lt;span class="o"&gt;(&lt;/span&gt;LISTEN&lt;span class="o"&gt;)&lt;/span&gt;
java    13273  TCP DESKTOP-IUMEID0.:4000-&amp;gt;localhost:42728 &lt;span class="o"&gt;(&lt;/span&gt;ESTABLISHED&lt;span class="o"&gt;)&lt;/span&gt;
java    13273  TCP localhost:36104-&amp;gt;DESKTOP-IUMEID0.:4001 &lt;span class="o"&gt;(&lt;/span&gt;ESTABLISHED&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the output above, we can see that both tomcats are communicating with each other via the ports 4000 and 4001 respectively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;java    13411 TCP localhost:42728-&amp;gt;DESKTOP-IUMEID0.:4000 &lt;span class="o"&gt;(&lt;/span&gt;ESTABLISHED&lt;span class="o"&gt;)&lt;/span&gt;
java    13411 TCP DESKTOP-IUMEID0.:4001-&amp;gt;localhost:36104 &lt;span class="o"&gt;(&lt;/span&gt;ESTABLISHED&lt;span class="o"&gt;)&lt;/span&gt;
java    13273  TCP DESKTOP-IUMEID0.:4000-&amp;gt;localhost:42728 &lt;span class="o"&gt;(&lt;/span&gt;ESTABLISHED&lt;span class="o"&gt;)&lt;/span&gt;
java    13273  TCP localhost:36104-&amp;gt;DESKTOP-IUMEID0.:4001 &lt;span class="o"&gt;(&lt;/span&gt;ESTABLISHED&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;N.B: &lt;em&gt;DESKTOP-IUMEID0&lt;/em&gt; is just the name of my computer.&lt;/p&gt;

&lt;p&gt;So that's it. Both tomcats now belong to the same cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable session replication
&lt;/h2&gt;

&lt;p&gt;The cluster is not very useful unless its nodes can replicate sessions between them. This would allow a session that was established in one node to be recoverable on the other node when the former dies out.&lt;br&gt;
To test session replication, I will use the &lt;em&gt;examples&lt;/em&gt; webapp that comes with out-of-the-box tomcat.&lt;/p&gt;

&lt;p&gt;The session replication is enabled by simply adding&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;distributable/&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;under element &lt;em&gt;web-app&lt;/em&gt; of &lt;em&gt;$CATALINA_BASE/webapps/examples/WEB-INF/web.xml&lt;/em&gt; in both tomcats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;web-app&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://xmln..."&lt;/span&gt;
  &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3...."&lt;/span&gt;
  &lt;span class="na"&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span class="s"&gt;"http:..."&lt;/span&gt;

  &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"4.0"&lt;/span&gt;
  &lt;span class="na"&gt;metadata-complete=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;distributable/&amp;gt;&lt;/span&gt;
    ......
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test session replication
&lt;/h3&gt;

&lt;p&gt;After restarting we can use &lt;em&gt;curl&lt;/em&gt; to establish a session in tomcat1 by sending a request to servlet &lt;em&gt;SessionExample&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl http://localhost:8080/examples/servlets/servlet/SessionExample

&amp;lt;&lt;span class="o"&gt;!&lt;/span&gt;DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
....
&amp;lt;h3&amp;gt;Sessions Example&amp;lt;/h3&amp;gt;
Session ID: 104F520BB401ED856048700D302D255A
...
The following data is &lt;span class="k"&gt;in &lt;/span&gt;your session:&amp;lt;br&amp;gt;
....
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now use the cookie JESSIONID to verify that the session also exists in tomcat2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;--cookie&lt;/span&gt; &lt;span class="s2"&gt;"JSESSIONID=104F520BB401ED856048700D302D255A"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
http://localhost:9080/examples/servlets/servlet/SessionExample

&amp;lt;&lt;span class="o"&gt;!&lt;/span&gt;DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
....
&amp;lt;h3&amp;gt;Sessions Example&amp;lt;/h3&amp;gt;
Session ID: 104F520BB401ED856048700D302D255A
...
The following data is &lt;span class="k"&gt;in &lt;/span&gt;your session:&amp;lt;br&amp;gt;
....
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will now put some data into the session via tomcat2 and verify if it is replicated in tomcat1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#update the session via TOMCAT 2 (note that port=9080)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s2"&gt;"dataname=james&amp;amp;datavalue=bond"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--cookie&lt;/span&gt; &lt;span class="s2"&gt;"JSESSIONID=104F520BB401ED856048700D302D255A"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
http://localhost:9080/examples/servlets/servlet/SessionExample

&amp;lt;&lt;span class="o"&gt;!&lt;/span&gt;DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
....
&amp;lt;h3&amp;gt;Sessions Example&amp;lt;/h3&amp;gt;
Session ID: 104F520BB401ED856048700D302D255A
...
The following data is &lt;span class="k"&gt;in &lt;/span&gt;your session:&amp;lt;br&amp;gt;
james &lt;span class="o"&gt;=&lt;/span&gt; bond
...
&amp;lt;/html&amp;gt;

&lt;span class="c"&gt;#recover the updated session via TOMCAT 1 (note that port=8080)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;--cookie&lt;/span&gt; &lt;span class="s2"&gt;"JSESSIONID=104F520BB401ED856048700D302D255A"&lt;/span&gt; &lt;span class="se"&gt;\ &lt;/span&gt;
http://localhost:8080/examples/servlets/servlet/SessionExample

&amp;lt;&lt;span class="o"&gt;!&lt;/span&gt;DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
....
&amp;lt;h3&amp;gt;Sessions Example&amp;lt;/h3&amp;gt;
Session ID: 104F520BB401ED856048700D302D255A
...
The following data is &lt;span class="k"&gt;in &lt;/span&gt;your session:&amp;lt;br&amp;gt;
james &lt;span class="o"&gt;=&lt;/span&gt; bond
...
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;So now we have a cluster of 2 tomcats that can replicate sessions between them. Not very useful, though, if we have to manually change the URL's and the JESSIONID cookie whenever one tomcat dies out or is responding slowly.&lt;/p&gt;

&lt;p&gt;I'll soon cover how to front these tomcats with a web server that will provide us with new important functionalities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;u&gt;request forwarding&lt;/u&gt;: web server will act as a reverse-proxy&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;load balancing&lt;/u&gt;: it will distribute the requests between the tomcats according, for example, to how busy they are&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;sticky sessions&lt;/u&gt;: it will always forward the requests pertaining to the same server session to the node that initiated it&lt;/li&gt;
&lt;li&gt;
&lt;u&gt;fail-over&lt;/u&gt;: it will detect when one tomcat is down and refrain from sending it any requests until it is up again&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>tutorial</category>
      <category>linux</category>
      <category>java</category>
    </item>
  </channel>
</rss>
