Skip to content

Instantly share code, notes, and snippets.

@HamzaAlayed
Created October 13, 2025 10:07
Show Gist options
  • Select an option

  • Save HamzaAlayed/c56830bfddc82ddc64dd594283421c92 to your computer and use it in GitHub Desktop.

Select an option

Save HamzaAlayed/c56830bfddc82ddc64dd594283421c92 to your computer and use it in GitHub Desktop.
Guacamole Docker Install Script
#!/bin/bash
# ========================================================================================
# Apache Guacamole Docker Installation Script
#
# Description:
# This script automates the installation of Apache Guacamole using Docker and
# Docker Compose. It handles dependency installation, configuration file generation,
# and service startup.
#
# Author: Gemini
# Version: 1.0
# ========================================================================================
# --- Configuration and Boilerplate ---
# Exit immediately if a command exits with a non-zero status.
set -e
# Colors for stylish output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
# Installation directory
INSTALL_DIR="/etc/guacamole"
GUAC_VERSION="1.5.4"
# --- Functions ---
# Function to print a formatted header
print_header() {
echo -e "\n${GREEN}=====================================================${NC}"
echo -e "${GREEN} $1 ${NC}"
echo -e "${GREEN}=====================================================${NC}"
}
# Function to check if running as root
check_root() {
if [ "$(id -u)" -ne 0 ]; then
echo -e "${RED}This script must be run as root. Please use 'sudo'.${NC}"
exit 1
fi
}
# Function to install Docker and Docker Compose
install_docker() {
print_header "Checking for Docker and Docker Compose"
# Check for Docker Compose v2 (the 'compose' plugin)
if docker compose version &>/dev/null; then
echo -e "Docker and Docker Compose v2 are already installed. Skipping."
return
fi
echo -e "${YELLOW}Docker or Docker Compose not found. Installing...${NC}"
apt-get update
apt-get install -y ca-certificates curl gnupg
# Add Docker's official GPG key
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
# Set up the repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
echo -e "${GREEN}Docker and Docker Compose installed successfully.${NC}"
}
# Function to set up the Guacamole directory and configuration files
setup_guacamole_files() {
print_header "Setting up Guacamole configuration files"
# Generate a strong random password for the database
DB_PASSWORD=$(LC_ALL=C tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 24)
if [ -z "$DB_PASSWORD" ]; then
echo -e "${RED}Failed to generate a database password.${NC}"
exit 1
fi
echo "Generated PostgreSQL password."
# Create installation directory
echo "Creating directory: ${INSTALL_DIR}"
mkdir -p "${INSTALL_DIR}"
cd "${INSTALL_DIR}"
# Create docker-compose.yml
echo "Creating docker-compose.yml file..."
cat > docker-compose.yml <<EOF
version: '3.8'
services:
guacd:
image: guacamole/guacd:${GUAC_VERSION}
container_name: guacd
restart: always
volumes:
- ./drive:/drive:rw
- ./record:/record:rw
networks:
- guacamole-net
postgres:
image: postgres:14
container_name: postgres-guacamole
restart: always
environment:
POSTGRES_DB: guacamole_db
POSTGRES_USER: guacamole_user
POSTGRES_PASSWORD: "${DB_PASSWORD}"
volumes:
- postgres-data:/var/lib/postgresql/data
- ./initdb.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- guacamole-net
guacamole:
image: guacamole/guacamole:${GUAC_VERSION}
container_name: guacamole
restart: always
ports:
- "8080:8080"
depends_on:
- guacd
- postgres
environment:
GUACD_HOSTNAME: guacd
POSTGRESQL_HOSTNAME: postgres-guacamole
POSTGRESQL_DATABASE: guacamole_db
POSTGRESQL_USER: guacamole_user
POSTGRESQL_PASSWORD: "${DB_PASSWORD}"
JAVA_OPTS: "-XX:-UseContainerSupport"
networks:
- guacamole-net
networks:
guacamole-net:
driver: bridge
volumes:
postgres-data:
drive:
record:
EOF
# Generate the initdb.sql script
echo "Generating database initialization script (initdb.sql)..."
bash -c "docker run --rm guacamole/guacamole:${GUAC_VERSION} /opt/guacamole/bin/initdb.sh --postgresql > ./initdb.sql"
# Check if the initdb.sql file was created successfully
if [ ! -s "initdb.sql" ]; then
echo -e "${RED}Failed to create initdb.sql. It is empty. Aborting.${NC}"
exit 1
fi
echo -e "${GREEN}Configuration files created successfully.${NC}"
}
# Function to start the Guacamole stack
start_guacamole() {
print_header "Starting Guacamole Services"
cd "${INSTALL_DIR}"
echo "Pulling the latest Docker images..."
docker compose pull
echo "Starting containers..."
docker compose up -d
# Check if containers are running
echo "Waiting for services to start..."
sleep 15
if [ "$(docker compose ps -q | wc -l)" -ne 3 ]; then
echo -e "${RED}Some containers failed to start. Please check the logs with 'docker compose logs'.${NC}"
docker compose logs
exit 1
fi
}
# Function to print a final summary
print_summary() {
SERVER_IP=$(hostname -I | awk '{print $1}')
print_header "Installation Complete!"
echo -e "Your Guacamole instance is now running."
echo -e ""
echo -e "----------------- ${YELLOW}Access Details${NC} -----------------"
echo -e "URL: ${YELLOW}http://${SERVER_IP}:8080${NC}"
echo -e "Default User: ${YELLOW}guacadmin${NC}"
echo -e "Default Password: ${YELLOW}guacadmin${NC}"
echo -e "----------------------------------------------------"
echo -e ""
echo -e "${RED}CRITICAL: Log in immediately and change the default password!${NC}"
echo -e ""
echo -e "The PostgreSQL database password has been randomly generated and is stored"
echo -e "in the ${INSTALL_DIR}/docker-compose.yml file. Keep this safe."
echo -e "Your generated password is: ${YELLOW}${DB_PASSWORD}${NC}"
echo -e ""
echo -e "To manage your Guacamole stack, navigate to ${INSTALL_DIR} and use:"
echo -e " - ${GREEN}docker compose down${NC} (to stop)"
echo -e " - ${GREEN}docker compose up -d${NC} (to start)"
echo -e " - ${GREEN}docker compose logs -f${NC} (to view logs)"
}
# --- Main Execution ---
main() {
check_root
install_docker
setup_guacamole_files
start_guacamole
print_summary
}
# Run the main function
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment