Skip to content

Instantly share code, notes, and snippets.

@mhoad
Forked from adilinden/guac_build.md
Created November 20, 2018 07:00
Show Gist options
  • Save mhoad/4988e83c1d454f53fcc9fb898d348701 to your computer and use it in GitHub Desktop.
Save mhoad/4988e83c1d454f53fcc9fb898d348701 to your computer and use it in GitHub Desktop.

Revisions

  1. @adilinden adilinden revised this gist Oct 15, 2018. 2 changed files with 16 additions and 21 deletions.
    36 changes: 16 additions & 20 deletions guac_build.md
    Original file line number Diff line number Diff line change
    @@ -65,13 +65,12 @@ https://github.com/MysticRyuujin/guac-install

    For reference here are some locations we are working with. Note that there are install paths to which symlinks are created during isntallation.

    | Directory | Purpose | Variable |
    |-------------------------------|-----------------------------|-----------------|
    | /var/lib/tomcat8/webapps | place to link .war into | |
    | /var/lib/tomcat8/.guacamole | symlink to /etc/guacamole | GUACAMOLE_HOME |
    | /etc/guacamole | configuration files install | |
    | /var/lib/guacamole | jar & war install | |
    | /usr/local/src | Sources build directory | |
    | Directory | Purpose | Variable |
    |-------------------------------------------|-----------------------------|-----------------|
    | /var/lib/tomcat8/webapps | place to link .war into | |
    | /etc/guacamole | configuration files install | GUACAMOLE_HOME |
    | /usr/local/share/guacamole/extensions/ | jar & war install | |
    | /usr/local/src | Sources build directory | |

    ### Prerequisites

    @@ -180,23 +179,21 @@ Download and build the client sources.

    Installation

    mkdir -p /var/lib/guacamole
    cp guacamole/target/guacamole-0.9.14.war /var/lib/guacamole/
    find extensions -type f -name *.jar -exec cp {} /var/lib/guacamole/ \;
    mkdir -p /usr/local/share/guacamole/extensions
    cp guacamole/target/guacamole-0.9.14.war /usr/local/share/guacamole/
    find extensions -type f -name *.jar -exec cp {} /usr/local/share/guacamole/extensions/ \;

    ### Basic Deployment

    Create directories and deploy webapp

    mkdir -p /etc/guacamole/{lib,extensions}
    ln -s /etc/guacamole/ /var/lib/tomcat8/.guacamole
    ln -s /var/lib/guacamole/guacamole-0.9.14.war /var/lib/tomcat8/webapps/guacamole.war
    ln -sf /usr/local/share/guacamole/guacamole-0.9.14.war /var/lib/tomcat8/webapps/guacamole.war

    File `/etc/guacamole/guacamole.properties`

    guacd-hostname: localhost
    guacd-port: 4822
    user-mapping: /etc/guacamole/user-mapping.xml

    File `/etc/guacamole/user-mapping.xml`

    @@ -285,15 +282,14 @@ Add to the contents of `/etc/guacamole/guacamole.properties`.
    mysql-username: guac_user
    mysql-password: somesecret

    Replace the contents of `/etc/guacamole/user-mapping.xml` with
    Remove `/etc/guacamole/user-mapping.xml`.

    <user-mapping>
    </user-mapping>
    rm /etc/guacamole/user-mapping.xml

    Install the MySQL extension and JDBC driver

    ln -s /var/lib/guacamole/guacamole-auth-jdbc-mysql-0.9.14.jar /etc/guacamole/extensions/guacamole-auth-jdbc-mysql.jar
    ln -s /usr/share/java/mysql-connector-java.jar /etc/guacamole/lib/
    ln -sf /usr/local/share/guacamole/extensions/guacamole-auth-jdbc-mysql-0.9.14.jar /etc/guacamole/extensions/guacamole-auth-jdbc-mysql.jar
    ln -sf /usr/share/java/mysql-connector-java.jar /etc/guacamole/lib/

    Restart services

    @@ -312,7 +308,7 @@ Guacamole supports authentication via HTTP header. This is *NOT* real authentica
    Install the guacamole extension.

    ln -s /var/lib/guacamole/guacamole-auth-header-0.9.14.jar /etc/guacamole/extensions/guacamole-auth-header.jar
    ln -sf /usr/local/share/guacamole/extensions/guacamole-auth-header-0.9.14.jar /etc/guacamole/extensions/guacamole-auth-header.jar

    Optionally, add `http-auth-header` to the `/etc/guacamole/guacamole.properties` file for a header other than `REMOTE_USER` to pull username from.

    @@ -350,4 +346,4 @@ This a config fragment with path changed to `new-path`.
    proxy_set_header Connection $http_connection;
    proxy_cookie_path /guacamole/ /new-path/;
    access_log off;
    }
    }
    1 change: 0 additions & 1 deletion guacamole.properties
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,5 @@
    guacd-hostname: localhost
    guacd-port: 4822
    user-mapping: /etc/guacamole/user-mapping.xml

    http-auth-header: X-Guacamole-User

  2. @adilinden adilinden revised this gist Oct 13, 2018. 1 changed file with 0 additions and 62 deletions.
    62 changes: 0 additions & 62 deletions proxy.nginx.conf
    Original file line number Diff line number Diff line change
    @@ -101,68 +101,6 @@ server {
    auth_basic "proxy.example.ca - SSO";
    auth_basic_user_file /etc/htpasswd/default-read;

    # Our git server
    location /cgit {
    access_log /var/log/nginx/proxy.log proxylog;

    # Set different authentication file cgit and git clone/pull
    # to allow for access to git only, not all SSO resources.
    auth_basic_user_file /etc/htpasswd/cgit-read;

    # Default is 1024m, but it acts weird for large git transfers.
    # It works fine if set to 0 or a smaller amount, such as 128m.
    proxy_max_temp_file_size 128m;

    proxy_intercept_errors on;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $remote_addr;

    # Username: tecmint
    # Password: tecmint01
    proxy_set_header Authorization "Basic dGVjbWludDp0ZWNobWludDAx";

    proxy_pass https://10.53.79.56:8443;

    location ~ ^/cgitrepos(/.*/git-receive-pack)$ {
    # Set different authentication file for write/push to git backend
    auth_basic_user_file /etc/htpasswd/cgit-write;

    proxy_pass https://10.53.79.56:8443;
    }
    }

    # Our cacti server
    location /cacti/ {
    access_log /var/log/nginx/proxy.log proxylog;

    proxy_intercept_errors on;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $remote_addr;

    proxy_pass http://10.53.79.57;
    }

    # Access pfsense GUI - tricky...
    location /pfsense/ {
    access_log /var/log/nginx/proxy.log proxylog;

    proxy_set_header Accept-Encoding "";
    proxy_redirect / /pfsense/;
    sub_filter 'href="/' 'href="/pfsense/';
    sub_filter 'src="/' 'src="/pfsense/';
    sub_filter 'url("/' 'url("/pfsense/';
    sub_filter_types text/xml text/css text/javascript;
    sub_filter_once off;

    proxy_pass https://10.53.79.1/;
    }

    location /guacamole/ {
    access_log /var/log/nginx/proxy.log proxylog;

  3. @adilinden adilinden revised this gist Oct 13, 2018. 1 changed file with 6 additions and 3 deletions.
    9 changes: 6 additions & 3 deletions guac_build.md
    Original file line number Diff line number Diff line change
    @@ -302,9 +302,13 @@ Restart services

    ### Optional HTTP header authentication

    *Note:* This isn't working for me. I cannot associate the username in `user-mapping.xml` nor in database when using MySQL.
    Guacamole supports authentication via HTTP header. This is *NOT* real authentication but just passing the username to guacamole. SOme initial troubles resolved via mailing-list [thread](http://apache-guacamole-general-user-mailing-list.2363388.n4.nabble.com/No-connections-for-header-authenticated-user-td4088.html)

    Guacamole supports authentication via HTTP header. This is *NOT* real authentication but just passing the username to guacamole.
    > Without any connections defined for the user, the user has access to create connections when directly connected and authenticated to the SQL database. However, the same user “authenticated” via header cannot access the connections tab nor create connections.
    >
    > Once connections are defined for the user, the user sees the connections tab in settings and can access existing and create new connections no matter whether authenticated directly or whether accessing via proxy and headers.
    >
    > Any connections defined in user-mappings.xml are seen when connected direct (authenticated against SQL) but ignored when accessing via proxy and headers.
    Install the guacamole extension.

    @@ -347,4 +351,3 @@ This a config fragment with path changed to `new-path`.
    proxy_cookie_path /guacamole/ /new-path/;
    access_log off;
    }

  4. @adilinden adilinden revised this gist Oct 13, 2018. 2 changed files with 37 additions and 0 deletions.
    11 changes: 11 additions & 0 deletions guacamole.properties
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,11 @@
    guacd-hostname: localhost
    guacd-port: 4822
    user-mapping: /etc/guacamole/user-mapping.xml

    http-auth-header: X-Guacamole-User

    mysql-hostname: localhost
    mysql-port: 3306
    mysql-database: guacdb
    mysql-username: guac_user
    mysql-password: somesecret
    26 changes: 26 additions & 0 deletions user-mapping.xml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,26 @@
    <user-mapping>
    <authorize
    username="tecmint"
    password="8383339b9c90775ac14693d8e620981f"
    encoding="md5">
    <connection name="RHEL 7">
    <protocol>ssh</protocol>
    <param name="hostname">10.53.79.18</param>
    <param name="port">22</param>
    <param name="username">gacanepa</param>
    </connection>
    <connection name="Windows 10">
    <protocol>rdp</protocol>
    <param name="hostname">10.53.79.19</param>
    <param name="port">3389</param>
    <param name="security">tls</param>
    <param name="ignore-cert">true</param>
    <param name="enable-printing">true</param>
    </connection>
    <connection name="VNC Host">
    <protocol>vnc</protocol>
    <param name="hostname">10.53.79.21</param>
    <param name="port">5900</param>
    </connection>
    </authorize>
    </user-mapping>
  5. @adilinden adilinden revised this gist Oct 13, 2018. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions proxy.nginx.conf
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # proxy.example.com
    # proxy.example.ca

    # =====================================================
    #
    @@ -64,7 +64,7 @@ server {
    listen 80;
    listen [::]:80;

    server_name proxy.example.com;
    server_name proxy.example.ca;
    root /var/www/html;

    access_log /var/log/nginx/access.log mainlog;
    @@ -83,7 +83,7 @@ server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name proxy.example.com;
    server_name proxy.example.ca;
    root /var/www/html;

    access_log /var/log/nginx/access.log mainlog;
    @@ -94,11 +94,11 @@ server {
    # - pre-production
    #include snippets/snakeoil.conf;
    # - production
    ssl_certificate /etc/letsencrypt/live/proxy.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/proxy.example.com/privkey.pem;
    ssl_certificate /etc/letsencrypt/live/proxy.example.ca/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/proxy.example.ca/privkey.pem;

    # Require authentication to access any services!
    auth_basic "proxy.example.com - SSO";
    auth_basic "proxy.example.ca - SSO";
    auth_basic_user_file /etc/htpasswd/default-read;

    # Our git server
  6. @adilinden adilinden revised this gist Oct 13, 2018. 1 changed file with 189 additions and 0 deletions.
    189 changes: 189 additions & 0 deletions proxy.nginx.conf
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,189 @@
    # proxy.example.com

    # =====================================================
    #
    # Creating web basic authentication users and passwords
    #
    # Generate password for htpasswd using:
    # echo -n "Username: "; read user; printf "$user:`openssl passwd -apr1`\n"
    #
    # Generate base64 for header using:
    # echo -n 'user:password' | openssl base64
    #
    # =====================================================

    # For reference when defining logging directives, this is the default
    # log format.
    #
    # log_format combined '$remote_addr - $remote_user [$time_local] '
    # '"$request" $status $body_bytes_sent '
    # '"$http_referer" "$http_user_agent"';

    log_format mainlog '$remote_addr $host $remote_user [$time_local] '
    '"$request" $status $body_bytes_sent '
    '"$http_referer" "$http_user_agent"';

    log_format proxylog '$remote_addr $host $remote_user [$time_local] '
    '"$request" $status $body_bytes_sent '
    '"$http_referer" "$http_user_agent" '
    'to: $upstream_addr urt=upstream_response_time '
    'rt=$request_time';

    error_page 400 402 405 406 407 408 /4xx.html;
    error_page 500 501 505 506 507 508 509 /5xx.html;
    error_page 401 /401.html;
    error_page 403 /403.html;
    error_page 404 /404.html;
    error_page 502 /502.html;
    error_page 503 /503.html;
    error_page 504 /504.html;

    index index.html;

    server {
    listen 80 default_server;
    listen [::]:80 default_server;
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;

    server_name _;
    root /var/www/html;

    access_log /var/log/nginx/access.log mainlog;

    # SSL certificates
    # - pre-production
    include snippets/snakeoil.conf;

    location / {
    try_files $uri $uri/ =404;
    }
    }

    server {
    listen 80;
    listen [::]:80;

    server_name proxy.example.com;
    root /var/www/html;

    access_log /var/log/nginx/access.log mainlog;

    # No redirect for certbot
    location /.well-known/acme-challenge/ {
    try_files $uri $uri/ =404;
    }

    location / {
    return 302 https://$host$request_uri;
    }
    }

    server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name proxy.example.com;
    root /var/www/html;

    access_log /var/log/nginx/access.log mainlog;

    # SSL
    ssl on;
    ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
    # - pre-production
    #include snippets/snakeoil.conf;
    # - production
    ssl_certificate /etc/letsencrypt/live/proxy.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/proxy.example.com/privkey.pem;

    # Require authentication to access any services!
    auth_basic "proxy.example.com - SSO";
    auth_basic_user_file /etc/htpasswd/default-read;

    # Our git server
    location /cgit {
    access_log /var/log/nginx/proxy.log proxylog;

    # Set different authentication file cgit and git clone/pull
    # to allow for access to git only, not all SSO resources.
    auth_basic_user_file /etc/htpasswd/cgit-read;

    # Default is 1024m, but it acts weird for large git transfers.
    # It works fine if set to 0 or a smaller amount, such as 128m.
    proxy_max_temp_file_size 128m;

    proxy_intercept_errors on;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $remote_addr;

    # Username: tecmint
    # Password: tecmint01
    proxy_set_header Authorization "Basic dGVjbWludDp0ZWNobWludDAx";

    proxy_pass https://10.53.79.56:8443;

    location ~ ^/cgitrepos(/.*/git-receive-pack)$ {
    # Set different authentication file for write/push to git backend
    auth_basic_user_file /etc/htpasswd/cgit-write;

    proxy_pass https://10.53.79.56:8443;
    }
    }

    # Our cacti server
    location /cacti/ {
    access_log /var/log/nginx/proxy.log proxylog;

    proxy_intercept_errors on;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $remote_addr;

    proxy_pass http://10.53.79.57;
    }

    # Access pfsense GUI - tricky...
    location /pfsense/ {
    access_log /var/log/nginx/proxy.log proxylog;

    proxy_set_header Accept-Encoding "";
    proxy_redirect / /pfsense/;
    sub_filter 'href="/' 'href="/pfsense/';
    sub_filter 'src="/' 'src="/pfsense/';
    sub_filter 'url("/' 'url("/pfsense/';
    sub_filter_types text/xml text/css text/javascript;
    sub_filter_once off;

    proxy_pass https://10.53.79.1/;
    }

    location /guacamole/ {
    access_log /var/log/nginx/proxy.log proxylog;

    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/ /guacamole/;
    proxy_set_header Authorization "";
    proxy_set_header X-Guacamole-User $remote_user;

    proxy_pass https://10.53.79.59:8443/guacamole/;
    }

    location / {
    # No authentication for static files and certbot
    auth_basic off;

    try_files $uri $uri/ =404;
    }
    }

    # End
  7. @adilinden adilinden revised this gist Oct 13, 2018. 1 changed file with 35 additions and 0 deletions.
    35 changes: 35 additions & 0 deletions ubuntu-18.04-amd64-20181012.patch
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,35 @@
    diff -Naur guacamole-server-0.9.14-orig/src/terminal/typescript.c guacamole-server-0.9.14/src/terminal/typescript.c
    --- guacamole-server-0.9.14-orig/src/terminal/typescript.c 2017-09-22 15:21:12.000000000 -0500
    +++ guacamole-server-0.9.14/src/terminal/typescript.c 2018-10-12 10:22:41.406958491 -0500
    @@ -129,9 +129,29 @@
    return NULL;
    }

    + /*
    + * Patch for compile time error on Ubuntu 18.04
    + *
    + * Discussed here: http://apache-guacamole-general-user-mailing-list.2363388.n4.nabble.com/Error-quot-make-quot-guacamole-quot-please-help-me-quot-td3831.html
    + * Patch here: https://github.com/apache/guacamole-server/pull/150
    + */
    +
    + /* Append suffix to basename */
    + //sprintf(typescript->timing_filename, "%s.%s", typescript->data_filename,
    + // GUAC_TERMINAL_TYPESCRIPT_TIMING_SUFFIX);
    +
    /* Append suffix to basename */
    - sprintf(typescript->timing_filename, "%s.%s", typescript->data_filename,
    - GUAC_TERMINAL_TYPESCRIPT_TIMING_SUFFIX);
    + if (snprintf(typescript->timing_filename, sizeof(typescript->timing_filename),
    + "%s.%s", typescript->data_filename, GUAC_TERMINAL_TYPESCRIPT_TIMING_SUFFIX)
    + >= sizeof(typescript->timing_filename)) {
    + close(typescript->data_fd);
    + free(typescript);
    + return NULL;
    + }
    +
    + /*
    + * End patch
    + */

    /* Attempt to open typescript timing file */
    typescript->timing_fd = open(typescript->timing_filename,
  8. @adilinden adilinden created this gist Oct 13, 2018.
    350 changes: 350 additions & 0 deletions guac_build.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,350 @@
    # Guacamole

    This is a HTML5 to RDP gateway

    ## Base System

    Ubuntu 18.04 installed from my template.

    ## First Login

    ### Passwords

    Configure the passwords by changing both `bingo` and `root` to something more sensible.

    ### Networking

    Configure `/etc/netplan/01-netcfg.yaml` for the static IP.

    network:
    version: 2
    renderer: networkd
    ethernets:
    ens160:
    dhcp4: no
    addresses:
    - 10.53.79.59/24
    gateway4: 10.53.79.1
    nameservers:
    search: [example.ca]
    addresses: [10.53.79.1]

    ### Hostname

    Edit the following files to change hostname from `ubuntu-18.04-amd64-tpl` to `guac`.

    sed -i 's/ubuntu-18\|ubuntu-18.04-amd64-tpl/guac/g' /etc/hosts && \
    sed -i 's/ubuntu-18\|ubuntu-18.04-amd64-tpl/guac/g' /etc/hostname && \
    sed -i 's/ubuntu-18\|ubuntu-18.04-amd64-tpl/guac/g' /etc/mailname && \
    sed -i 's/ubuntu-18\|ubuntu-18.04-amd64-tpl/guac/g' /etc/postfix/main.cf && \
    hostname guac

    ### ssh Host Keys

    Refresh the ssh host keys by removing them, then recreating them.

    rm -v /etc/ssh/ssh_host*{key,pub}
    dpkg-reconfigure openssh-server

    ### Update

    Update the system using apt.

    apt update
    apt upgrade

    ## Guacamole

    ### Instructions

    https://www.tecmint.com/guacamole-access-remote-linux-windows-machines-via-web-browser/
    https://guacamole.apache.org/doc/0.9.14/gug/installing-guacamole.html#guacamole-server-installation
    https://github.com/MysticRyuujin/guac-install

    ### File locations

    For reference here are some locations we are working with. Note that there are install paths to which symlinks are created during isntallation.

    | Directory | Purpose | Variable |
    |-------------------------------|-----------------------------|-----------------|
    | /var/lib/tomcat8/webapps | place to link .war into | |
    | /var/lib/tomcat8/.guacamole | symlink to /etc/guacamole | GUACAMOLE_HOME |
    | /etc/guacamole | configuration files install | |
    | /var/lib/guacamole | jar & war install | |
    | /usr/local/src | Sources build directory | |

    ### Prerequisites

    Install Oracle Java 8

    apt install --no-install-recommends software-properties-common
    add-apt-repository ppa:webupd8team/java # For Java 8
    add-apt-repository ppa:linuxuprising/java # For Java 10/11
    apt update
    apt search oracle-java # Show available installable Oracle Java versions
    apt install default-jdk # Install latest OpenJDK from Ubuntu
    apt install oracle-java8-installer # Install Java 8
    update-alternatives --config java # Select the default java

    Make sure the last command shows Oracle Java 8 as default, as Guacamole 0.9.14 didn't build for me using the OpenJDK versions.

    Install the prerequisites for the guacamole-server, guacamole-client, the tomcat server and build tools.

    apt install libcairo2-dev libjpeg-turbo8-dev libjpeg-dev libpng-dev libossp-uuid-dev \
    libavcodec-dev libavutil-dev libswscale-dev libfreerdp-dev libpango1.0-dev libssh2-1-dev \
    libtelnet-dev libvncserver-dev libpulse-dev libssl-dev libvorbis-dev libwebp-dev \
    ghostscript tomcat8 tomcat8-admin tomcat8-user \
    git build-essential autoconf maven

    ### Building guacamole-server from source

    #### Ubuntu 18.08 build error

    This error occurs on Ubuntu 18.04:

    Makefile:566: recipe for target 'libguac_terminal_la-typescript.lo' failed
    make[2]: *** [libguac_terminal_la-typescript.lo] Error 1
    make[2]: Leaving directory '/usr/local/src/guacamole-server-0.9.14/src/terminal'
    Makefile:503: recipe for target 'all-recursive' failed
    make[1]: *** [all-recursive] Error 1
    make[1]: Leaving directory '/usr/local/src/guacamole-server-0.9.14'
    Makefile:427: recipe for target 'all' failed
    make: *** [all] Error 2

    It has been discussed [here](http://apache-guacamole-general-user-mailing-list.2363388.n4.nabble.com/Error-quot-make-quot-guacamole-quot-please-help-me-quot-td3831.html) and fixed [here](https://github.com/apache/guacamole-server/commit/cd0e48234a079813664052b56c501e854753303a).

    Place `ubuntu-18.04-amd64-20181012.patch` into `/usr/local/src` and apply at the appropriate stage.

    #### From git

    Create a convenient location to build, then download and build the server sources.

    mkdir -p /usr/local/src
    cd /usr/local/src
    git clone git://github.com/apache/guacamole-server.git
    cd guacamole-server
    git checkout tags/0.9.14 -b tag-0.9.14
    patch -p1 < ../ubuntu-18.04-amd64-20181012.patch # Apply patch for <1.0.0
    autoreconf -fi
    ./configure --with-init-dir=/etc/init.d
    make
    make install

    #### From tarball

    Create a convenient location to build, then download and build the server sources.

    mkdir -p /usr/local/src
    cd /usr/local/src
    wget http://apache.mirror.iweb.ca/guacamole/0.9.14/source/guacamole-server-0.9.14.tar.gz
    tar -xzf guacamole-server-0.9.14.tar.gz
    patch -p0 < ../ubuntu-18.04-amd64-20181012.patch # Apply patch for <1.0.0
    cd guacamole-server-0.9.14/
    ./configure --with-init-dir=/etc/init.d
    make
    make install

    #### Common tasks

    Link the libraries.

    mkdir -p /usr/lib/$(dpkg-architecture -qDEB_BUILD_GNU_TYPE)/freerdp
    ln -s /usr/local/lib/freerdp/guac*.so /usr/lib/$(dpkg-architecture -qDEB_BUILD_GNU_TYPE)/freerdp/
    ldconfig

    ### Building guacamole-client from source

    #### From git

    Download and build the client sources.

    cd /usr/local/src
    git clone https://github.com/apache/guacamole-client.git
    cd guacamole-client
    git checkout tags/0.9.14 -b tag-0.9.14
    mvn package

    *Note:* Use `mvn clean` to cleanup sources before rebuilding. Important when checking out a different release.

    #### From tarball

    Download and build the client sources.

    cd /usr/local/src
    wget http://apache.mirror.iweb.ca/guacamole/0.9.14/source/guacamole-client-0.9.14.tar.gz
    tar xzf guacamole-client-0.9.14.tar.gz
    cd guacamole-client-0.9.14
    mvn package

    #### Common tasks

    Installation

    mkdir -p /var/lib/guacamole
    cp guacamole/target/guacamole-0.9.14.war /var/lib/guacamole/
    find extensions -type f -name *.jar -exec cp {} /var/lib/guacamole/ \;

    ### Basic Deployment

    Create directories and deploy webapp

    mkdir -p /etc/guacamole/{lib,extensions}
    ln -s /etc/guacamole/ /var/lib/tomcat8/.guacamole
    ln -s /var/lib/guacamole/guacamole-0.9.14.war /var/lib/tomcat8/webapps/guacamole.war

    File `/etc/guacamole/guacamole.properties`

    guacd-hostname: localhost
    guacd-port: 4822
    user-mapping: /etc/guacamole/user-mapping.xml

    File `/etc/guacamole/user-mapping.xml`

    <user-mapping>
    <authorize
    username="tecmint"
    password="8383339b9c90775ac14693d8e620981f"
    encoding="md5">
    <connection name="RHEL 7">
    <protocol>ssh</protocol>
    <param name="hostname">10.53.79.18</param>
    <param name="port">22</param>
    <param name="username">gacanepa</param>
    </connection>
    <connection name="Windows 10">
    <protocol>rdp</protocol>
    <param name="hostname">10.53.79.19</param>
    <param name="port">3389</param>
    <param name="security">tls</param>
    <param name="ignore-cert">true</param>
    <param name="enable-printing">true</param>
    </connection>
    <connection name="VNC Host">
    <protocol>vnc</protocol>
    <param name="hostname">10.53.79.21</param>
    <param name="port">5900</param>
    </connection>
    </authorize>
    </user-mapping>

    Passwords are MD5 and can be generated with

    printf '%s' "tecmint01" | md5sum

    Restart services.

    systemctl enable guacd
    service guacd start
    service tomcat8 restart

    ### Optional SSL for tomcat

    Create a keystore with a single self-signed certificate.

    keytool -genkey -alias Guacamole -keyalg RSA -keystore /etc/tomcat8/guac.jks -storepass cookedBeaver \
    -keypass cookedBeaver -noprompt -dname "CN=guac.example.ca,OU=,O=,L=,S=,C="

    Add the port `8443` connector to `/etc/tomcat8/server.xml`.

    <Connector port="8443" protocol="HTTP/1.1"
    SSLEnabled="true"
    maxThreads="150"
    scheme="https"
    secure="true"
    clientAuth="false"
    sslProtocol="TLS"
    keystoreFile="conf/guac.jks"
    keystorePass="cookedBeaver"
    URIEncoding="UTF-8" />

    Comment out the `<Connector port="8443"` in `/etc/tomcat8/server.xml` if only SSL traffic is desired.

    ### Optional SQL authentication

    Install MariaDB packages

    apt install --no-install-recommends mariadb-client mariadb-server mariadb-common libmysql-java

    Create the database and database user

    mysql -u root
    create database guacdb;
    create user 'guac_user'@'localhost' identified by 'somesecret';
    GRANT SELECT,INSERT,UPDATE,DELETE ON guacdb.* TO 'guac_user'@'localhost';
    flush privileges;

    Deploy the database schema and create the default administrative user (guacadmin/guacadmin)

    cat /usr/local/src/guacamole-client/extensions/guacamole-auth-jdbc/modules/guacamole-auth-jdbc-mysql/schema/*.sql | mysql -u root guacdb

    Add to the contents of `/etc/guacamole/guacamole.properties`.

    mysql-hostname: localhost
    mysql-port: 3306
    mysql-database: guacdb
    mysql-username: guac_user
    mysql-password: somesecret

    Replace the contents of `/etc/guacamole/user-mapping.xml` with

    <user-mapping>
    </user-mapping>

    Install the MySQL extension and JDBC driver

    ln -s /var/lib/guacamole/guacamole-auth-jdbc-mysql-0.9.14.jar /etc/guacamole/extensions/guacamole-auth-jdbc-mysql.jar
    ln -s /usr/share/java/mysql-connector-java.jar /etc/guacamole/lib/

    Restart services

    service guacd restart
    service tomcat8 restart

    ### Optional HTTP header authentication

    *Note:* This isn't working for me. I cannot associate the username in `user-mapping.xml` nor in database when using MySQL.

    Guacamole supports authentication via HTTP header. This is *NOT* real authentication but just passing the username to guacamole.

    Install the guacamole extension.

    ln -s /var/lib/guacamole/guacamole-auth-header-0.9.14.jar /etc/guacamole/extensions/guacamole-auth-header.jar

    Optionally, add `http-auth-header` to the `/etc/guacamole/guacamole.properties` file for a header other than `REMOTE_USER` to pull username from.

    http-auth-header: X-Guacamole-User

    This would require the following additional statements in an nginx proxy.

    proxy_set_header Authorization "";
    proxy_set_header X-Guacamole-User $remote_user;

    ### Proxying guacamole with nginx reverse proxy

    Official doc: https://guacamole.apache.org/doc/gug/proxying-guacamole.html#proxying-with-nginx

    This is the standard nginx config fragment.

    location /guacamole/ {
    proxy_pass http://HOSTNAME:8080/guacamole/;
    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;
    access_log off;
    }

    This a config fragment with path changed to `new-path`.

    location /new-path/ {
    proxy_pass http://HOSTNAME:8080/guacamole/;
    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/ /new-path/;
    access_log off;
    }