#!/bin/bash # This script installs the Apache Guacamole server/client, Apache Tomcat, MariaDB, and the Guacamole TOTP 2FA extension on Debian 12. # It also enables each to start automatically. # It's intended to be run as root on a fresh Debian 12 system. # # This script acts as a very quick method to set up a Guacamole server which is only suitable for personal use or testing. # It's intended to be changed for anyone's specific use case, and should only be treated as a starting point. # Please read the entirety of this script before using it. # # # Tomcat is installed to the /opt/tomcatX directory, where X is the main version number. # Tomcat Logs are in /opt/tomcatX/logs. # Guacamole configuration files are located in /etc/guacamole. # # The web interface can be accessed at http://:8080/guacamole # The default credentials are "guacadmin" for username and password. # Versions other than the defaults have not been tested. # Guacamole 1.5.5 is incompatible with Tomcat 10. # Older versions may require downloading from the Apache archive. GUAC=1.5.5 TOMCAT=9 TOMCATVER=9.0.93 # Java installation uses the OpenJDK JRE Headless package. # Older Java versions may not be available from system repositories. JAVA=17 # Remove delays after messages by setting these to zero. WAITLONG=2 WAIT=1 WAITSHORT=0.5 # You can set passwords in advance here if you don't want to be prompted. # These passwords are for internal use only, and do not affect the default guacadmin user. MARIADBPASS='' GUACUSERPASS='' timer() { sleep 0.5 for time in 4 . . . 3 . . . 2 . . . 1 . . . ; do printf "$time"; sleep 0.25; done } skipSection() { while true; do IFS= printf "$@" read -rs -t 4.5 -n 1 key || key=Y kill $! 2>/dev/null case $key in 'Y'|'y'|' '|'' ) printf " starting.\n"; return 0;; 'N'|'n'|$'\t' ) printf " skipping.\n"; sleep $WAITSHORT return 1;; 'Q'|'q'|$'\e' ) printf " exiting.\n"; sleep $WAITSHORT exit 0;; * ) printf " invalid input.\n"; sleep $WAITSHORT timer &;; esac done } downloadError() { printf " -> [ERROR] Error downloading.\n"; $WAITSHORT printf " -> Exiting.\n"; exit 1; } installError() { printf " -> [ERROR] Error installing packages.\n"; $WAITSHORT printf " -> Exiting.\n"; exit 1; } updateError() { printf " -> [ERROR] Error updating.\n"; $WAITSHORT printf " -> Exiting.\n"; exit 1; } printf "\n=> [INFO] The following keys can be pressed during timers.\n" printf " -> SPACE, ENTER, or Y starts immediately.\n" printf " -> TAB or N skips that step.\n" printf " -> ESC or Q exits the script.\n" sleep $WAITLONG printf "\n"; timer & skipSection "=> Starting in: " sleep $WAITSHORT printf "\n"; timer & skipSection "=> Running system updates in: " && { printf " -> Updating repositories.\n"; sleep $WAITSHORT apt update -y || updateError printf " -> Upgrading system.\n"; sleep $WAITSHORT apt full-upgrade -y || updateError printf " -> Finished running system updates.\n" sleep $WAIT } printf "\n"; timer & skipSection "=> Installing Guacamole $GUAC server in: " && { printf " -> Installing dependencies.\n"; sleep $WAITSHORT apt install -y libcairo2-dev libjpeg62-turbo-dev libpng-dev libtool-bin uuid-dev freerdp2-dev libpango1.0-dev libssh2-1-dev libvncserver-dev libpulse-dev libssl-dev libvorbis-dev libwebp-dev build-essential || installError # Add 'libavcodec-dev libavformat-dev libavutil-dev libswscale-dev' to record guacamole sessions. # Add 'libtelnet-dev' for Telnet support. # Add 'libwebsockets-dev' for Kubernetes support. printf " -> Downloading Guacamole $GUAC server.\n"; sleep $WAITSHORT wget https://dlcdn.apache.org/guacamole/$GUAC/source/guacamole-server-$GUAC.tar.gz -O guacamole-server-$GUAC.tar.gz || downloadError # Note that the Guacamole server downloader uses the dlcdn.apache.org mirror, which doesn't include older releases. # Older releases can be found from archive.apache.org: # https://archive.apache.org/dist/guacamole/$GUAC/source/guacamole-server-$GUAC.tar.gz printf " -> Setting up server.\n"; sleep $WAITSHORT tar -xzf guacamole-server-$GUAC.tar.gz cd guacamole-server-$GUAC/ printf " -> Configuring.\n"; sleep $WAITSHORT ./configure --with-systemd-dir=/etc/systemd/system/ printf " -> Installing server.\n"; sleep $WAITSHORT make make install printf " -> Updating installed libraries cache.\n"; sleep $WAITSHORT ldconfig cd .. printf " -> Enabling systemd unit.\n"; sleep $WAITSHORT systemctl daemon-reload systemctl enable guacd.service timer & skipSection " -> Starting server in: " && { systemctl start guacd.service } printf " -> Finished installing Guacamole $GUAC server.\n" sleep $WAIT } printf "\n"; timer & skipSection "=> Installing Tomcat $TOMCAT in: " && { printf " -> Installing dependencies.\n"; sleep $WAITSHORT apt install -y openjdk-$JAVA-jdk-headless || installError printf " -> Downloading Tomcat $TOMCAT.\n"; sleep $WAITSHORT wget https://dlcdn.apache.org/tomcat/tomcat-$TOMCAT/v$TOMCATVER/bin/apache-tomcat-$TOMCATVER.tar.gz -O apache-tomcat-$TOMCATVER.tar.gz || downloadError # Note that the Tomcat downloader uses the dlcdn.apache.org mirror, which doesn't include older releases. # Older releases can be found from archive.apache.org: # https://archive.apache.org/dist/tomcat/tomcat-$TOMCAT/v$TOMCATVER/bin/apache-tomcat-$TOMCATVER.tar.gz printf " -> Setting up.\n"; sleep $WAITSHORT tar -xzf apache-tomcat-$TOMCATVER.tar.gz mv apache-tomcat-$TOMCATVER /opt/tomcat$TOMCAT printf " -> Creating tomcat user.\n"; sleep $WAITSHORT useradd -r -m -s /bin/bash tomcat chown -R tomcat:tomcat /opt/tomcat$TOMCAT printf " -> Creating systemd unit files.\n"; sleep $WAITSHORT cat > /etc/systemd/system/tomcat$TOMCAT.service << EOF [Unit] Description=Apache Tomcat $TOMCAT After=network.target [Service] Type=forking User=tomcat Group=tomcat Environment="CATALINA_HOME=/opt/tomcat$TOMCAT" ExecStart=/opt/tomcat$TOMCAT/bin/startup.sh ExecStop=/opt/tomcat$TOMCAT/bin/shutdown.sh Restart=on-failure [Install] WantedBy=multi-user.target EOF printf " -> Enabling systemd unit.\n"; sleep $WAITSHORT systemctl daemon-reload systemctl enable tomcat$TOMCAT.service timer & skipSection " -> Starting server in: " && { systemctl start tomcat$TOMCAT.service } printf " -> Finished installing Tomcat $TOMCAT.\n" sleep $WAIT } printf "\n"; timer & skipSection "=> Installing Guacamole $GUAC client in: " && { printf " -> Downloading Guacamole $GUAC client.\n"; sleep $WAITSHORT wget https://dlcdn.apache.org/guacamole/$GUAC/binary/guacamole-$GUAC.war -O guacamole-$GUAC.war || downloadError # Note that the Guacamole client downloader uses the dlcdn.apache.org mirror, which doesn't include older releases. # Older releases can be found from archive.apache.org: # https://archive.apache.org/dist/guacamole/$GUAC/binary/guacamole-$GUAC.war printf " -> Setting up client.\n"; sleep $WAITSHORT cp guacamole-$GUAC.war /opt/tomcat$TOMCAT/webapps/guacamole.war printf " -> Creating configuration directories.\n"; sleep $WAITSHORT mkdir /etc/guacamole ln -s /etc/guacamole/ /opt/tomcat$TOMCAT/.guacamole mkdir /etc/guacamole/{extensions,lib} printf " -> Finished installing Guacamole $GUAC client.\n" sleep $WAIT } printf "\n"; timer & skipSection "=> Setting up Guacamole configuration files in: " && { printf " -> Creating guacamole.properties.\n"; sleep $WAITSHORT cat > /etc/guacamole/guacamole.properties << EOF # Hostname and port of guacamole proxy guacd-hostname: localhost guacd-port: 4822 # MariaDB properties mysql-hostname: localhost mysql-database: guacamole_db mysql-username: guacdb_admin EOF # mysql-driver and mysql-password is appended during database setup printf " -> Creating guacd.conf.\n"; sleep $WAITSHORT cat > /etc/guacamole/guacd.conf << EOF [server] bind_host = 127.0.0.1 bind_port = 4822 EOF # printf " -> Creating user-mapping.xml.\n"; sleep $WAITSHORT # #cat > /etc/guacamole/user-mapping.xml << EOF # # # # # ssh # 192.168.4.87 # 22 # # # # ssh # 10.1.0.8 # 22 # # # # #EOF printf " -> Finished setting up Guacamole configuration files.\n" sleep $WAIT } printf "\n"; timer & skipSection "=> Setting up authentication database in: " && { printf " -> Installing MariaDB.\n"; sleep $WAITSHORT apt install -y mariadb-server || installError printf " -> Downloading database authentication extension.\n"; sleep $WAITSHORT wget https://dlcdn.apache.org/guacamole/$GUAC/binary/guacamole-auth-jdbc-$GUAC.tar.gz -O guacamole-auth-jdbc-$GUAC.tar.gz || downloadError # Note that the Guacamole extension downloader uses the dlcdn.apache.org mirror, which doesn't include older releases. # Older releases can be found from archive.apache.org: # https://archive.apache.org/dist/guacamole/$GUAC/binary/guacamole-auth-jdbc-$GUAC.tar.gz printf " -> Installing extension.\n"; sleep $WAITSHORT tar -xzf guacamole-auth-jdbc-$GUAC.tar.gz cp guacamole-auth-jdbc-$GUAC/mysql/guacamole-auth-jdbc-mysql-$GUAC.jar /etc/guacamole/extensions/ printf " -> Downloading MySQL JDBC driver.\n"; sleep $WAITSHORT wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-j-9.0.0.tar.gz -O mysql-connector-j-9.0.0.tar.gz || downloadError # This may need to be changed for other versions. # 'No suitable driver found' error when using MariaDB connector. printf " -> Installing JDBC driver.\n"; sleep $WAITSHORT tar -xzf mysql-connector-j-9.0.0.tar.gz cp mysql-connector-j-9.0.0/mysql-connector-j-9.0.0.jar /etc/guacamole/lib/ printf " -> Appending driver to guacamole.properties.\n"; sleep $WAITSHORT printf "mysql-driver: mysql\n" >> /etc/guacamole/guacamole.properties printf " -> Setting up database.\n"; sleep $WAITSHORT if [ "$MARIADBPASS" = '' ]; then read -rs -p " -> Enter database guacamole_db password: " MARIADBPASS printf "\n" fi mariadb -u root -p"$MARIADBPASS" -e "CREATE DATABASE guacamole_db;" printf " -> Copying data.\n"; sleep $WAITSHORT cat guacamole-auth-jdbc-$GUAC/mysql/schema/*.sql | mariadb -u root -p"$MARIADBPASS" guacamole_db if [ "$GUACUSERPASS" = '' ]; then read -rs -p " -> Enter guacdb_admin password: " GUACUSERPASS printf "\n" fi mariadb -u root -p"$MARIADBPASS" -e " CREATE USER 'guacdb_admin'@'localhost' IDENTIFIED BY '$GUACUSERPASS'; GRANT SELECT,INSERT,UPDATE,DELETE ON guacamole_db.* TO 'guacdb_admin'@'localhost'; FLUSH PRIVILEGES;" printf " -> Appending database password to guacamole.properties.\n"; sleep $WAITSHORT printf "mysql-password: $MARIADBPASS\n" >> /etc/guacamole/guacamole.properties printf " -> Finished setting up authentication database.\n" sleep $WAIT } printf "\n"; timer & skipSection "=> Installing TOTP 2FA extension in: " && { printf " -> Downloading TOTP 2FA extension.\n"; sleep $WAITSHORT wget https://dlcdn.apache.org/guacamole/$GUAC/binary/guacamole-auth-totp-$GUAC.tar.gz -O guacamole-auth-totp-$GUAC.tar.gz || downloadError # Note that the Guacamole extension downloader uses the dlcdn.apache.org mirror, which doesn't include older releases. # Older releases can be found from archive.apache.org: # https://archive.apache.org/dist/guacamole/$GUAC/binary/guacamole-auth-totp-$GUAC.tar.gz printf " -> Installing extension.\n"; sleep $WAITSHORT tar -xzf guacamole-auth-totp-$GUAC.tar.gz cp guacamole-auth-totp-$GUAC/guacamole-auth-totp-$GUAC.jar /etc/guacamole/extensions/ printf " -> Finished installing TOTP 2FA extension.\n" sleep $WAIT } printf "\n"; timer & skipSection "=> Restarting services in: " && { printf " -> Restarting.\n"; sleep $WAITSHORT systemctl restart tomcat$TOMCAT.service guacd.service } printf "=> Installation complete.\n"; sleep $WAITSHORT