Why use Guacamole?

I needed a way to get to my computers without when there where times I was unable to use a VPN or I didn’t have my computer with me. Guacamole has given me the ability to do this. I absolutely love it. I will share in quotes below the general reason provided by the guacamole site.

“The principle reason to use Guacamole is constant, world-wide, unfettered access to your computers.

Guacamole allows access one or more desktops from anywhere remotely, without having to install a client, particularly when installing a client is not possible. By setting up a Guacamole server, you can provide access to any other computer on the network from virtually any other computer on the internet, anywhere in the world. Even mobile phones or tablets can be used, without having to install anything.

As a true web application whose communication is over HTTP or HTTPS only, Guacamole allows you to access your machines from anywhere without violating the policy of your workplace, and without requiring the installation of special clients. The presence of a proxy or corporate firewall does not prevent Guacamole use.”

Useful Websites That you will need during the Process

I will list the websites upfront that I used and then as we go through this guide, you will see the explanation as to why these sites were used to get a good and clean working setup. I have used this method so many times and just have been to lazy to document so all I have to do is use just 1 page. But it is good to have the  references

The Installation Process

Getting the script ready to run

I am installing this on ubuntu 20.04 server (barebones) with openssh-server installed during setup. You might want to consider install net-tools if you care, but I like using ifconfig so I choose to install it.

1. It is always good to run sudo apt-get update && sudo apt-get upgrade -y just to make sure everything is up to date and the repos are reachable.



2. I will start by doing a git clone of the repo and storing it in a folder like /opt/guacamole. Is that necessary? No, it isn’t, I just like it that way

a. sudo -i
b. cd /opt
c. git clone https://github.com/MysticRyuujin/guac-install.git



3. Navigate to the path where you just cloned the repo. In my case, this is /opt/guac-install and make the installation script executable.

chmod +x guac-install.sh

Executing the guac-install script

I am going to choose the non-interactive so it creates mysql database with the credentials I supply it and removes the two factor authentication in a one liner. Adjust the one liner to fit your installation needs.

./guac-install.sh --mysqlpwd password --guacpwd password --nomfa --installmysql

The interactive way to give you the custom options you want to use is below

./guac-install.sh

This script is going to run for a good bit, so let it do it’s thing while you grab a drink or a snack. When you come back, it will be working (as long as nothing goes wrong), but you will be able to login and make sure everything is working before we move on to setting up NGINX as a reverse proxy and on our way to getting SSL / HTTPS working.



Once complete, it should like below

Verify Guacamole is Working

You will want to navigate to the url and make sure guacamole works. If you want to stop here, you can, but I would not advise it unless you have barebones minimal needs. This stage would be no where near ready for outside access. Navigate to https://ipaddressofguac:8080/guacamole/ and it should load the login page.



Default Login should be guacadmin/guacadmin

Installing NGINX Reverse Proxy

Below is an example nginx configuration that we will use. Before we go ahead and copy and paste that all in, we need to do some prep work such as create variables. This will be for the purposes

EXTERNALFQDN=guac.yourdomain.com
INTERNALFQDN=guac01.yourdomain.local


Double Check this by running echo to make sure it is correct

echo $EXTERNALFQDN
echo $INTERNALFQDN


EXTERNALFQDN is the external fully qualified domains name that you will try to reach from the internet.

INTERNALFQDN is the internal host name of your Guacamole server of your locally hosted domain.

Install NGINX and Let’s Encrypt

apt-get -y install nginx letsencrypt openssl

Make the directories for your SSL Certs

mkdir -p /etc/nginx/ssl/$EXTERNALFQDN

Create your self-signed cert to get SSL working

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/$EXTERNALFQDN/guacserver.key -out /etc/nginx/ssl/$EXTERNALFQDN/guacserver.crt

Fill in the information it prompts you for, it is interactive and self-explanatory.

Create strong Diffie-Hellman group for negotiation of Perfect Forward Secrecy

sudo openssl dhparam -dsaparam -out /etc/nginx/ssl/$EXTERNALFQDN/dhparam.pem 4096

Once all that is completed, you should have your certificates and dhparam file all in the same path under /etc/nginx/ssl/EXTERNALFQDN/

Now that we have everything installed, prepared and in the proper locations, we will create the nginx.conf by copying the code below and pasting it. After we do this, we will need to doublecheck and make sure that we compare this code snippet with outs and make sure everything is correct. Once we do that, we will test the configuration by running

sudo nginx -t

If the test passes then you are good to go and all you need to do is restart nginx and you should be able to go straight to guacamole from the internal IP or Internal domain name.



sudo systemctl restart nginx



You should now be able to navigate to https://yourinternalFQDN/ or https://yourinternalipaddress/

External access will require that you own a domain name and that you choose to set up Let’s Encrypt via Chase Wright’s Guide or you set HA Proxy on pfsense by watching this how to video

Example nginx.conf

cat > /etc/nginx/nginx.conf <<- EOM
user www-data;
worker_processes 4;
pid /run/nginx.pid;

events
{
        worker_connections 768;
}

http
{
        # My Certificates
        ssl_certificate /etc/nginx/ssl/$EXTERNALFQDN/guacserver.crt;
        ssl_certificate_key /etc/nginx/ssl/$EXTERNALFQDN/guacserver.key;

        # SSL Performance Related
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;

        # SSL Protocols and Ciphers
        ssl_prefer_server_ciphers on;
        ssl_protocols TLSv1.2;
        ssl_ciphers "ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:!AES128:!aNULL:!MD5:!eNULL:!EXPORT:!DES:!PSK:!RC4";
        # DHE Key-Exchange
        ssl_dhparam /etc/nginx/ssl/$EXTERNALFQDN/dhparam.pem;

        # Random Security Stuff
        server_tokens off;
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;
        add_header X-XSS-Protection "1; mode=block";
        add_header Strict-Transport-Security max-age=63072000;

        # Common Proxy Settings
        proxy_set_header Host      $host;
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header     X-Forwarded-For $proxy_add_x_forwarded_for;

        ########################
        # Default Config Stuff #
        ########################
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 4096; #Default:2048
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        gzip on;
        gzip_disable "msie6";
        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;

        # REDIRECTS ALL PORT 80/HTTP to 443/HTTPS
        server
        {
                listen 80;
                listen [::]:80;
                server_name $EXTERNALFQDN;
                
                location ~ /.well-known/acme-challenge
                {
                    root /var/www/html/;
                }
                
                return 301 https://$host$request_uri;
        }

        # GUACAMOLE SERVER SETTINGS
        server
        {
                listen 443 ssl;
                listen [::]:443 ssl;
                server_name $EXTERNALFQDN;

                proxy_buffering off;
                proxy_redirect  off;
                proxy_cookie_path /guacamole/ /;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                
                location ~ /.well-known/acme-challenge
                {
                    root /var/www/html/;
                }
                
                location /
                {
                        proxy_pass https://$INTERNALFQDN:8080/guacamole/;
                }
        }
}
EOM