<?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: Chairat Onyaem (Par)</title>
    <description>The latest articles on DEV Community by Chairat Onyaem (Par) (@pacroy).</description>
    <link>https://dev.to/pacroy</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%2F265891%2F6d275fd1-09cc-41e3-bcf4-bfcd7ff9f3da.jpg</url>
      <title>DEV Community: Chairat Onyaem (Par)</title>
      <link>https://dev.to/pacroy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pacroy"/>
    <language>en</language>
    <item>
      <title>Create Your Own Azure Bastion with Guacamole and Save $100+ a month</title>
      <dc:creator>Chairat Onyaem (Par)</dc:creator>
      <pubDate>Fri, 30 Apr 2021 15:18:40 +0000</pubDate>
      <link>https://dev.to/pacroy/create-your-own-azure-bastion-with-guacamole-and-save-100-a-month-3fld</link>
      <guid>https://dev.to/pacroy/create-your-own-azure-bastion-with-guacamole-and-save-100-a-month-3fld</guid>
      <description>&lt;p&gt;Microsoft Azure provides &lt;a href="https://azure.microsoft.com/en-us/services/azure-bastion" rel="noopener noreferrer"&gt;Azure Bastion&lt;/a&gt; service which is a jump server so you can securely access your virtual machines via its Azure Portal web interface without exposing SSH or RDP port. Here is its architecture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fv15wy165uheqdm4ljb6w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fv15wy165uheqdm4ljb6w.jpg" alt="Azure Bastion Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This service is great except &lt;a href="https://azure.microsoft.com/en-us/pricing/details/azure-bastion/" rel="noopener noreferrer"&gt;it costs $0.19 per hour&lt;/a&gt;. Combining with other components then this may costs you almost $150 a month. Bad news is you can't stop it unless you delete it.&lt;/p&gt;

&lt;p&gt;This post, I will show you how I create my own jump server on  Ubuntu VM to replace Azure Bastion using &lt;a href="https://guacamole.apache.org/" rel="noopener noreferrer"&gt;Apache Guacamole&lt;/a&gt; which is an open source tool which provide similar functionalities (I wonder that Azure Bastion may be even built on top of it). The VM can be a small one that may costs only a few tens bucks per month.&lt;/p&gt;




&lt;h1&gt;
  
  
  Apache Guacamole
&lt;/h1&gt;

&lt;p&gt;From &lt;a href="(https://guacamole.apache.org/)"&gt;its website&lt;/a&gt;, Apache Guacamole is a clientless remote desktop gateway that supports standard protocols like VNC, RDP, and SSH. Clientless means your clients don't need to install anything but just use a web browser to remotely access your fleet of VMs.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/116207678" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The Guacamole comprises of two main components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Guacamole Server which provides &lt;code&gt;guacd&lt;/code&gt; which is like a proxy server for the client to connect to the remote server.&lt;/li&gt;
&lt;li&gt;Guacamole Client which is a servelet container that user will log in and via web browser.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ftdmwjtttqn8va262s79b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ftdmwjtttqn8va262s79b.png" alt="Guacamole Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more information about Guacamole, visit its &lt;a href="https://guacamole.apache.org/doc/gug/guacamole-architecture.html" rel="noopener noreferrer"&gt;architecture page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As my disclaimer, installation is not simple as there are several components you need to install and configure before it is &lt;em&gt;good enough&lt;/em&gt; to use. There may be simpler ways to deploy e.g. using &lt;a href="https://guacamole.apache.org/doc/gug/guacamole-docker.html" rel="noopener noreferrer"&gt;Docker image&lt;/a&gt; or using &lt;a href="https://github.com/prabhatsharma/apache-guacamole-helm-chart/blob/master/values.yaml" rel="noopener noreferrer"&gt;this Helm chart&lt;/a&gt; but I haven't tried them yet. Because of cost is my concern so I'd like to deploy on a small VM that may not run a Kubernetes cluster (and may be I just prefer to learn it in hard way :P).&lt;/p&gt;

&lt;h1&gt;
  
  
  Network Topology
&lt;/h1&gt;

&lt;p&gt;You use Azure Bastion or a jump server because you want to secure your VMs behind so having the right network design is needed. Here it mine:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F0ve1uz4kmxg65ox3gikj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F0ve1uz4kmxg65ox3gikj.png" alt="Network Topology"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my virtual network (VNet), I split into two subnets:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;snet-gateway&lt;/code&gt; where I will deploy Guacamole on a Ubuntu VM which has a public IP so its web interface can be reached from the Internet.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;snet-default&lt;/code&gt; where I will deploy my backend pool of VM and enable remote access via Guacamole only.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the sake of security, you should configure Network Security Group (NSG) of your &lt;code&gt;snet-gateway&lt;/code&gt; to limit inbound and outbound connections to/from Ubuntu VM in the same way as you do for &lt;a href="https://docs.microsoft.com/en-us/azure/bastion/bastion-nsg#apply" rel="noopener noreferrer"&gt;AzureBastionSubnet&lt;/a&gt;. But in this example, I just associate NSG to the VM directly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fd9jmik21jh988vk99jwo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fd9jmik21jh988vk99jwo.png" alt="NSG Inbound Rules"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fgkncp6amdvvjar3ita6q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fgkncp6amdvvjar3ita6q.png" alt="NSG Outbound Rules"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you setup your network then create the VMs. In this example, I create the following two VMs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;vm-win10&lt;/code&gt; in the &lt;code&gt;snet-default&lt;/code&gt; which is the machine I will remote access to.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vm-ubuntu1804&lt;/code&gt; in the &lt;code&gt;snet-gateway&lt;/code&gt; where I will install Guacamole and use it as a jump server. I choose &lt;code&gt;B2s&lt;/code&gt; size which cost around $39 per month but, of course, you can change its size later.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Install Guacamole Server
&lt;/h1&gt;

&lt;p&gt;Once your Ubuntu Server 18.04 is created then log in via SSH. You may need to expose SSH port publicly for now. You can change SSH port to something than 22 to make it more secure. See how to do it in my previous blog.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="https://pacroy.medium.com/setting-up-your-own-vpn-server-with-just-5-a-month-c934cf073ea1" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A88%3A88%2F1%2AsP-A6cCxQ_-Z5QxHUdmdqg.jpeg" alt="Chairat Onyaem (Par)"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://pacroy.medium.com/setting-up-your-own-vpn-server-with-just-5-a-month-c934cf073ea1" class="ltag__link__link" rel="noopener noreferrer"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Setting Up Your Own VPN Server with just $5 a month | by Chairat Onyaem (Par) | Medium&lt;/h2&gt;
      &lt;h3&gt;Chairat Onyaem (Par) ・ &lt;time&gt;Mar 13, 2021&lt;/time&gt; ・ 
      &lt;div class="ltag__link__servicename"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fmedium-f709f79cf29704f9f4c2a83f950b2964e95007a3e311b77f686915c71574fef2.svg" alt="Medium Logo"&gt;
        pacroy.Medium
      &lt;/div&gt;
    &lt;/h3&gt;
&lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;From &lt;a href="https://guacamole.apache.org/doc/gug/installing-guacamole.html" rel="noopener noreferrer"&gt;its documentation&lt;/a&gt;, there's no executable binary available for Guacamole server and you need to build it from source (unless you deploy from Docker image).&lt;/p&gt;

&lt;p&gt;First you need to install build tools and all required dependencies for the build process. Missing some of them may result in missing features or build failure.&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 &amp;amp; upgrade system&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nt"&gt;--yes&lt;/span&gt; upgrade

&lt;span class="c"&gt;# Install build tools&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--yes&lt;/span&gt; build-essential

&lt;span class="c"&gt;# Install build dependencies&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--yes&lt;/span&gt; libcairo2-dev libjpeg-turbo8-dev libpng-dev libtool-bin libossp-uuid-dev

&lt;span class="c"&gt;# Install optional dependencies&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--yes&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    libavcodec-dev libavformat-dev libavutil-dev libswscale-dev &lt;span class="se"&gt;\&lt;/span&gt;
    freerdp2-dev &lt;span class="se"&gt;\&lt;/span&gt;
    libpango1.0-dev &lt;span class="se"&gt;\&lt;/span&gt;
    libssh2-1-dev &lt;span class="se"&gt;\&lt;/span&gt;
    libtelnet-dev &lt;span class="se"&gt;\&lt;/span&gt;
    libvncserver-dev &lt;span class="se"&gt;\&lt;/span&gt;
    libwebsockets-dev &lt;span class="se"&gt;\&lt;/span&gt;
    libpulse-dev &lt;span class="se"&gt;\&lt;/span&gt;
    libssl-dev &lt;span class="se"&gt;\&lt;/span&gt;
    libvorbis-dev &lt;span class="se"&gt;\&lt;/span&gt;
    libwebp-dev

&lt;span class="c"&gt;# Install runtime dependencies&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--yes&lt;/span&gt; &lt;span class="nt"&gt;--no-install-recommends&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    netcat-openbsd                &lt;span class="se"&gt;\&lt;/span&gt;
    ca-certificates               &lt;span class="se"&gt;\&lt;/span&gt;
    ghostscript                   &lt;span class="se"&gt;\&lt;/span&gt;
    fonts-liberation              &lt;span class="se"&gt;\&lt;/span&gt;
    fonts-dejavu                  &lt;span class="se"&gt;\&lt;/span&gt;
    xfonts-terminus


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Next, download source codes and extract.&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;GUAC_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1.3.0"&lt;/span&gt;
curl &lt;span class="nt"&gt;-fLO&lt;/span&gt; &lt;span class="s2"&gt;"https://downloads.apache.org/guacamole/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/source/guacamole-server-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz"&lt;/span&gt;
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; &lt;span class="s2"&gt;"guacamole-server-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Configure the build and start the build.&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;cd&lt;/span&gt; &lt;span class="s2"&gt;"guacamole-server-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
./configure &lt;span class="nt"&gt;--with-init-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/init.d
make


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Once done, install and start the service.&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;sudo &lt;/span&gt;make &lt;span class="nb"&gt;install
sudo &lt;/span&gt;ldconfig
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start guacd
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;guacd


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;At this point, the Guacamole server (guacd) service should be up and running. Inspect by executing &lt;code&gt;systemctl status guacd --no-pager&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F8absf4ibgp8z964tli9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F8absf4ibgp8z964tli9w.png" alt="Guacamole Server Service Status"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Install Guacamole Client
&lt;/h1&gt;

&lt;p&gt;Unlike the server, we don't need to build it (but you can if you want). So we will download the WAR file and install on Tomcat server then expose it through nginx via HTTPS.&lt;/p&gt;
&lt;h2&gt;
  
  
  Install Tomcat
&lt;/h2&gt;

&lt;p&gt;First, we need Tomcat to run the WAR file. Use this script to install it.&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;TOMCAT_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"8.5.65"&lt;/span&gt;
&lt;span class="nv"&gt;TOMCAT_MAJOR_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TOMCAT_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'{print $1}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--yes&lt;/span&gt; default-jdk
&lt;span class="nb"&gt;sudo &lt;/span&gt;groupadd tomcat
&lt;span class="nb"&gt;sudo &lt;/span&gt;useradd &lt;span class="nt"&gt;-s&lt;/span&gt; /bin/false &lt;span class="nt"&gt;-g&lt;/span&gt; tomcat &lt;span class="nt"&gt;-d&lt;/span&gt; /opt/tomcat tomcat
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-G&lt;/span&gt; tomcat &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$USER&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
curl &lt;span class="nt"&gt;-LO&lt;/span&gt; &lt;span class="s2"&gt;"https://downloads.apache.org/tomcat/tomcat-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TOMCAT_MAJOR_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/v&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TOMCAT_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/bin/apache-tomcat-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TOMCAT_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz"&lt;/span&gt;
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /opt/tomcat
&lt;span class="nb"&gt;sudo tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; &lt;span class="s2"&gt;"apache-tomcat-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;TOMCAT_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz"&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; /opt/tomcat &lt;span class="nt"&gt;--strip-components&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="nb"&gt;sudo chgrp&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; tomcat /opt/tomcat
&lt;span class="nb"&gt;cd&lt;/span&gt; /opt/tomcat
&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; g+r conf
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;g+x conf
&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; tomcat webapps/ work/ temp/ logs/


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Configure Tomcat and start the service.&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;JAVA_ALT_TEXT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;update-java-alternatives &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;JAVA_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JAVA_ALT_TEXT&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $3}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"[Unit]
Description=Apache Tomcat Web Application Container
After=network.target

[Service]
Type=forking

Environment=JAVA_HOME=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JAVA_HOME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
Environment=CATALINA_PID=/opt/tomcat/temp/tomcat.pid
Environment=CATALINA_HOME=/opt/tomcat
Environment=CATALINA_BASE=/opt/tomcat
Environment='CATALINA_OPTS=-Xms512M -Xmx1024M -server -XX:+UseParallelGC'
Environment='JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom'

ExecStart=/opt/tomcat/bin/startup.sh
ExecStop=/opt/tomcat/bin/shutdown.sh

User=tomcat
Group=tomcat
UMask=0007
RestartSec=10
Restart=always

[Install]
WantedBy=multi-user.target"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/systemd/system/tomcat.service &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start tomcat
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;tomcat


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Now the Tomcat service should be up and running. Inspect by executing &lt;code&gt;systemctl status tomcat.service --no-pager&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fh8c1a8tbd591h0wgbsrt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fh8c1a8tbd591h0wgbsrt.png" alt="Tomcat Service Status"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Add Guacamole Client Servlet
&lt;/h2&gt;

&lt;p&gt;Download and add the WAR file to the Tomcat.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

curl &lt;span class="nt"&gt;-LO&lt;/span&gt; &lt;span class="s2"&gt;"https://downloads.apache.org/guacamole/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/binary/guacamole-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.war"&lt;/span&gt;
&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="s2"&gt;"guacamole-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.war"&lt;/span&gt; &lt;span class="s2"&gt;"/opt/tomcat/webapps/ROOT.war"&lt;/span&gt;
&lt;span class="nb"&gt;sudo chown &lt;/span&gt;tomcat:tomcat &lt;span class="s2"&gt;"/opt/tomcat/webapps/ROOT.war"&lt;/span&gt;
&lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /opt/tomcat/webapps/ROOT


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;You may try to access the client at &lt;code&gt;http://&amp;lt;your-server&amp;gt;:8080/&lt;/code&gt; by either open or forward the port and you should see the Guacamole's login screen (but you can't login now).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fokirc2h7agxiq27qaste.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fokirc2h7agxiq27qaste.png" alt="Guacamole Login"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In case you see Tomcat instead of Guacamole, restart Tomcat using command &lt;code&gt;sudo systemctl restart tomcat&lt;/code&gt; and try again.&lt;/p&gt;
&lt;h2&gt;
  
  
  Install nginx and certbot
&lt;/h2&gt;

&lt;p&gt;We will use &lt;a href="https://www.nginx.com/" rel="noopener noreferrer"&gt;nginx&lt;/a&gt; as a proxy and &lt;a href="https://certbot.eff.org/" rel="noopener noreferrer"&gt;certbot&lt;/a&gt; to get a certificate from Let's Encrypt.&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;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--yes&lt;/span&gt; nginx-core
&lt;span class="nb"&gt;sudo &lt;/span&gt;snap &lt;span class="nb"&gt;install &lt;/span&gt;core&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;snap refresh core
&lt;span class="nb"&gt;sudo &lt;/span&gt;snap &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--classic&lt;/span&gt; certbot


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Configure certbot with a domain and an email address and integrate with nginx.&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;DOMAIN_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;Your VM FQDN&amp;gt;"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;EMAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;Your Email Address&amp;gt;"&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot &lt;span class="nt"&gt;--nginx&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;DOMAIN_NAME&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;EMAIL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--agree-tos&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Edit the file &lt;code&gt;/etc/nginx/sites-enabled/default&lt;/code&gt; and replace the following section:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    server_name your.server.fqdn; # managed by Certbot

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;with this one:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    server_name your.server.fqdn; # managed by Certbot

        location / {


                proxy_pass http://localhost:8080/;
                proxy_buffering off;
                proxy_http_version 1.1;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $http_connection;
                proxy_cookie_path /guacamole/ /;
                access_log off;
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This will set nginx as a proxy to your servlet. You don't need to configure to redirect HTTP to HTTPS as that is already done by certbot.&lt;/p&gt;

&lt;p&gt;Test the configuration and restart nginx.&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;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Now you should be able to access Guacamole ay &lt;code&gt;https://&amp;lt;your-server&amp;gt;/&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Configure User and Connections
&lt;/h2&gt;

&lt;p&gt;We will create a user with two connections in the &lt;code&gt;user-mapping.xml&lt;/code&gt; file so we can test logging on.&lt;/p&gt;

&lt;p&gt;Create the file &lt;code&gt;/etc/guacamole/user-mapping.xml&lt;/code&gt; an put below content. Create the directory &lt;code&gt;/etc/guacamole&lt;/code&gt; first if it does not exist.&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;user-mapping&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;authorize&lt;/span&gt; &lt;span class="na"&gt;username=&lt;/span&gt;&lt;span class="s"&gt;"guacadmin"&lt;/span&gt; &lt;span class="na"&gt;password=&lt;/span&gt;&lt;span class="s"&gt;"guacadmin"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;connection&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"this-server-ssh"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
             &lt;span class="nt"&gt;&amp;lt;protocol&amp;gt;&lt;/span&gt;ssh&lt;span class="nt"&gt;&amp;lt;/protocol&amp;gt;&lt;/span&gt;
             &lt;span class="nt"&gt;&amp;lt;param&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"hostname"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;localhost&lt;span class="nt"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
             &lt;span class="nt"&gt;&amp;lt;param&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"port"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;22&lt;span class="nt"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/connection&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;connection&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"some-win10-rdp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
             &lt;span class="nt"&gt;&amp;lt;protocol&amp;gt;&lt;/span&gt;rdp&lt;span class="nt"&gt;&amp;lt;/protocol&amp;gt;&lt;/span&gt;
             &lt;span class="nt"&gt;&amp;lt;param&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"hostname"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;vm-win10&lt;span class="nt"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
             &lt;span class="nt"&gt;&amp;lt;param&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"port"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;3389&lt;span class="nt"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
             &lt;span class="nt"&gt;&amp;lt;param&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;username&lt;span class="nt"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
             &lt;span class="nt"&gt;&amp;lt;param&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;thisisyourpassword&lt;span class="nt"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
             &lt;span class="nt"&gt;&amp;lt;param&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"ignore-cert"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/param&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/connection&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/authorize&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/user-mapping&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The first connection is SSH to local server itself while the second one is RDP to Windows 10 VM. Don't forget to update the username and password.&lt;/p&gt;

&lt;p&gt;Restart Tomcat and test logging in and making the connections.&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;sudo &lt;/span&gt;systemctl restart tomcat


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://media.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%2Fwzthl1qgsbhacb59oc0p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fwzthl1qgsbhacb59oc0p.png" alt="Guacamole with Dummy Connections"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;If everything is configured properly, you should be able to connect to your VMs via either SSH and RDP. However, you cannot change anything on the web GUI the configuration is static in the file &lt;code&gt;user-mapping.xml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fud6bvfeo2qw0ij2dgost.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fud6bvfeo2qw0ij2dgost.png" alt="Guacamole Static Settings"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;To make it editable via the web GUI, we need to install a database. In this example, I will use MySQL but Guacamole also supports other databases e.g. MariaDB, PostgreSQL. You can check for more information in &lt;a href="https://guacamole.apache.org/doc/gug/jdbc-auth.html" rel="noopener noreferrer"&gt;this documentation page&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Install MySQL
&lt;/h1&gt;

&lt;p&gt;Let's install MySQL.&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;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--yes&lt;/span&gt; mysql-server


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Check MySQL service status by executing &lt;code&gt;systemctl status mysql --no-pager&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fwhmmn8kqfsr7xx8gn5se.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fwhmmn8kqfsr7xx8gn5se.png" alt="MySQL Service Status"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After install the MySQL, we also need to install the Guacamole extension and library so it knows how to talk to the database.&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;# Download and install JDBC extensions&lt;/span&gt;
curl &lt;span class="nt"&gt;-fLO&lt;/span&gt; &lt;span class="s2"&gt;"https://downloads.apache.org/guacamole/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/binary/guacamole-auth-jdbc-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz"&lt;/span&gt;
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; &lt;span class="s2"&gt;"guacamole-auth-jdbc-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz"&lt;/span&gt;
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /etc/guacamole/extensions
&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="s2"&gt;"guacamole-auth-jdbc-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/mysql/guacamole-auth-jdbc-mysql-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.jar"&lt;/span&gt; &lt;span class="s2"&gt;"/etc/guacamole/extensions/"&lt;/span&gt;

&lt;span class="c"&gt;# Download and install MySQL Connector/J&lt;/span&gt;
&lt;span class="nv"&gt;CONNECTORJ_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"8.0.24"&lt;/span&gt;
curl &lt;span class="nt"&gt;-fLO&lt;/span&gt; &lt;span class="s2"&gt;"https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONNECTORJ_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz"&lt;/span&gt;
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xvf&lt;/span&gt; &lt;span class="s2"&gt;"mysql-connector-java-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONNECTORJ_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz"&lt;/span&gt;
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /etc/guacamole/lib
&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="s2"&gt;"mysql-connector-java-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONNECTORJ_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/mysql-connector-java-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONNECTORJ_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.jar"&lt;/span&gt; &lt;span class="s2"&gt;"/etc/guacamole/lib/"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Configure Database
&lt;/h2&gt;

&lt;p&gt;Next, we need to create a database and a user. In this example, I will create the database named &lt;code&gt;guacamole_db&lt;/code&gt; and the user named &lt;code&gt;guacamole_user&lt;/code&gt;. Please note the password must meet complexity criteria.&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;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;YourPasswordHere&amp;gt;"&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;mysql &lt;span class="nt"&gt;--execute&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'CREATE DATABASE guacamole_db;'&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;mysql &lt;span class="nt"&gt;--execute&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"CREATE USER 'guacamole_user'@'localhost' IDENTIFIED BY '&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;';"&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;mysql &lt;span class="nt"&gt;--execute&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"GRANT SELECT,INSERT,UPDATE,DELETE ON guacamole_db.* TO 'guacamole_user'@'localhost';"&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;mysql &lt;span class="nt"&gt;--execute&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'FLUSH PRIVILEGES;'&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Then run the provides scripts to create schema and the Guacamole default user &lt;code&gt;guacadmin&lt;/code&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;cat &lt;/span&gt;guacamole-auth-jdbc-1.3.0/mysql/schema/&lt;span class="k"&gt;*&lt;/span&gt;.sql | &lt;span class="nb"&gt;sudo &lt;/span&gt;mysql guacamole_db


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Lastly, you need to configure Guacamole client so it can connect to the database by creating file &lt;code&gt;/etc/guacamole/guacamole.properties&lt;/code&gt; and put the following content.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# MySQL properties&lt;/span&gt;
&lt;span class="na"&gt;mysql-hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;
&lt;span class="na"&gt;mysql-port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
&lt;span class="na"&gt;mysql-database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;guacamole_db&lt;/span&gt;
&lt;span class="na"&gt;mysql-username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;guacamole_user&lt;/span&gt;
&lt;span class="na"&gt;mysql-password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;YourPasswordHere&amp;gt;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;If you configure the &lt;code&gt;user-mapping.xml&lt;/code&gt; file before then you may no longer need that so remove it.&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;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /etc/guacamole/user-mapping.xml


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Restart Tomcat and test logging in again using default username and password i.e. &lt;code&gt;guacadmin&lt;/code&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;sudo &lt;/span&gt;systemctl restart tomcat


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Now, you should be able to make changes in the Settings. It is recommended you create a new user and then remove the &lt;code&gt;guacadmin&lt;/code&gt; as soon as possible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ful497mrr8pedfsel6r6v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ful497mrr8pedfsel6r6v.png" alt="Guacamole Dynamic Settings"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Enable Two-Factor Authentication
&lt;/h1&gt;

&lt;p&gt;If you want you can optionally install TOTP module to enable two-factor authentication to add more security to your VM pool. Just download the extension and restart Tomcat.&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;# Download and install TOTP extension&lt;/span&gt;
curl &lt;span class="nt"&gt;-fLO&lt;/span&gt; &lt;span class="s2"&gt;"https://downloads.apache.org/guacamole/&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/binary/guacamole-auth-totp-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz"&lt;/span&gt;
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; &lt;span class="s2"&gt;"guacamole-auth-totp-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz"&lt;/span&gt;
&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /etc/guacamole/extensions
&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="s2"&gt;"guacamole-auth-totp-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/guacamole-auth-totp-&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GUAC_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.jar"&lt;/span&gt; &lt;span class="s2"&gt;"/etc/guacamole/extensions/"&lt;/span&gt;

&lt;span class="c"&gt;# Restart tomcat&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart tomcat


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Now, when you try logging in again, it will ask you to setup an authenticator and require you to input in every time you log in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fogujgoikwc4m2wwp1m99.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fogujgoikwc4m2wwp1m99.png" alt="Multi-factor Authentication Setup"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Scripts
&lt;/h1&gt;

&lt;p&gt;If you don't want to perform all above steps one by one, you may leverage bash scripts I created in this repository.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/pacroy" rel="noopener noreferrer"&gt;
        pacroy
      &lt;/a&gt; / &lt;a href="https://github.com/pacroy/guacamole-setup-script" rel="noopener noreferrer"&gt;
        guacamole-setup-script
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Guacamole Setup Script for Ubuntu Linux Server
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Use at your own risk!&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Cover Image by &lt;a href="https://unsplash.com/@footluz?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Footluz Blog&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/bastion?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>azure</category>
      <category>bastion</category>
      <category>guacamole</category>
      <category>ubuntu</category>
    </item>
  </channel>
</rss>
