diff --git a/kasmvnc/README.md b/kasmvnc/README.md index 9c3b28db..bceef3e0 100644 --- a/kasmvnc/README.md +++ b/kasmvnc/README.md @@ -9,7 +9,8 @@ tags: [helper, vnc, desktop] # KasmVNC -Automatically install [KasmVNC](https://kasmweb.com/kasmvnc) in a workspace, and create an app to access it via the dashboard. +Automatically install [KasmVNC](https://kasmweb.com/kasmvnc) in a workspace, and +create an app to access it via the dashboard. ```tf module "kasmvnc" { @@ -18,7 +19,12 @@ module "kasmvnc" { version = "1.0.23" agent_id = coder_agent.example.id desktop_environment = "xfce" + subdomain = true } ``` -> **Note:** This module only works on workspaces with a pre-installed desktop environment. As an example base image you can use `codercom/enterprise-desktop` image. +> **Note:** This module only works on workspaces with a one of the following +> desktop environments pre-installed: `xfce`, `kde`, `gnome`, `lxde`, `lxqt`. + +> The `codercom/enterprise-desktop` base image contains `xfce` and can be used +> as an example image. diff --git a/kasmvnc/main.tf b/kasmvnc/main.tf index 4265f3c7..c2867323 100644 --- a/kasmvnc/main.tf +++ b/kasmvnc/main.tf @@ -9,51 +9,30 @@ terraform { } } -variable "agent_id" { - type = string - description = "The ID of a Coder agent." -} - -variable "port" { - type = number - description = "The port to run KasmVNC on." - default = 6800 -} - -variable "kasm_version" { - type = string - description = "Version of KasmVNC to install." - default = "1.3.2" -} - -variable "desktop_environment" { - type = string - description = "Specifies the desktop environment of the workspace. This should be pre-installed on the workspace." - validation { - condition = contains(["xfce", "kde", "gnome", "lxde", "lxqt"], var.desktop_environment) - error_message = "Invalid desktop environment. Please specify a valid desktop environment." - } +locals { + template_data = object({ + PORT = var.port, + DESKTOP_ENVIRONMENT = var.desktop_environment, + KASM_VERSION = var.kasm_version + SUBDOMAIN = tostring(var.subdomain) + }) } resource "coder_script" "kasm_vnc" { agent_id = var.agent_id display_name = "KasmVNC" icon = "/icon/kasmvnc.svg" - script = templatefile("${path.module}/run.sh", { - PORT : var.port, - DESKTOP_ENVIRONMENT : var.desktop_environment, - KASM_VERSION : var.kasm_version - }) run_on_start = true + script = templatefile("${path.module}/run.sh.tftpl", locals.template_data) } resource "coder_app" "kasm_vnc" { agent_id = var.agent_id slug = "kasm-vnc" - display_name = "kasmVNC" + display_name = "KasmVNC" url = "http://localhost:${var.port}" icon = "/icon/kasmvnc.svg" - subdomain = true + subdomain = var.subdomain share = "owner" healthcheck { url = "http://localhost:${var.port}/app" diff --git a/kasmvnc/path_vnc.html b/kasmvnc/path_vnc.html new file mode 100644 index 00000000..287bdbfc --- /dev/null +++ b/kasmvnc/path_vnc.html @@ -0,0 +1,73 @@ + + +
++ This application is being served via path sharing. + If you are not redirected, check the + Javascript console in your browser's developer tools + for more information. +
+ + + diff --git a/kasmvnc/run.sh b/kasmvnc/run.tftpl similarity index 55% rename from kasmvnc/run.sh rename to kasmvnc/run.tftpl index c285b050..096003b6 100644 --- a/kasmvnc/run.sh +++ b/kasmvnc/run.tftpl @@ -3,6 +3,14 @@ # Exit on error, undefined variables, and pipe failures set -euo pipefail +info() { printf "💁 INFO: %s\n" "$@"; } +warn() { printf "😱 WARNING: %s\n" "$@" ;} +error() { printf "💀 ERROR: %s\n" "$@"; exit 1; } +debug() { + if [ "${DEBUG}" != "Y" ]; then return; fi + printf "🦺 DEBUG: %s\n" "$@" +} + # Function to check if vncserver is already installed check_installed() { if command -v vncserver &> /dev/null; then @@ -29,14 +37,12 @@ download_file() { # shellcheck disable=SC2034 download_tool=(busybox wget -O-) else - echo "ERROR: No download tool available (curl, wget, or busybox required)" - exit 1 + error "No download tool available (curl, wget, or busybox required)" fi # shellcheck disable=SC2288 "$${download_tool[@]}" "$url" > "$output" || { - echo "ERROR: Failed to download $url" - exit 1 + error "Failed to download $url" } } @@ -79,16 +85,14 @@ install_rpm() { # shellcheck disable=SC2034 package_manager=(rpm -i) else - echo "ERROR: No supported package manager available (dnf, zypper, yum, or rpm required)" - exit 1 + error "No supported package manager available (dnf, zypper, yum, or rpm required)" fi download_file "$url" "$kasmrpm" # shellcheck disable=SC2288 sudo "$${package_manager[@]}" "$kasmrpm" || { - echo "ERROR: Failed to install $kasmrpm" - exit 1 + error "Failed to install $kasmrpm" } rm "$kasmrpm" @@ -107,8 +111,8 @@ install_alpine() { # Detect system information if [[ ! -f /etc/os-release ]]; then - echo "ERROR: Cannot detect OS: /etc/os-release not found" - exit 1 + error "Cannot detect OS: /etc/os-release not found" + fi # shellcheck disable=SC1091 @@ -124,10 +128,11 @@ elif [[ "$ID" == "fedora" ]]; then distro_version="$(grep -oP '\(\K[\w ]+' /etc/fedora-release | tr '[:upper:]' '[:lower:]' | tr -d ' ')" fi -echo "Detected Distribution: $distro" -echo "Detected Version: $distro_version" -echo "Detected Codename: $codename" -echo "Detected Architecture: $arch" +echo "🕵 Detected Operating System Information" +echo " 🔎 Distribution: $distro" +echo " 🔎 Version: $distro_version" +echo " 🔎 Codename: $codename" +echo " 🔎 Architecture: $arch" # Map arch to package arch case "$arch" in @@ -145,8 +150,7 @@ case "$arch" in : # This is effectively a noop ;; *) - echo "ERROR: Unsupported architecture: $arch" - exit 1 + error "Unsupported architecture: $arch" ;; esac @@ -154,8 +158,7 @@ esac if ! check_installed; then # Check for NOPASSWD sudo (required) if ! command -v sudo &> /dev/null || ! sudo -n true 2> /dev/null; then - echo "ERROR: sudo NOPASSWD access required!" - exit 1 + error "sudo NOPASSWD access required!" fi base_url="https://github.com/kasmtech/KasmVNC/releases/download/v${KASM_VERSION}" @@ -190,14 +193,14 @@ else kasm_config_file="$HOME/.vnc/kasmvnc.yaml" SUDO= - echo "WARNING: Sudo access not available, using user config dir!" + warn "Sudo access not available, using user config dir!" if [[ -f "$kasm_config_file" ]]; then - echo "WARNING: Custom user KasmVNC config exists, not overwriting!" - echo "WARNING: Ensure that you manually configure the appropriate settings." + warn "Custom user KasmVNC config exists, not overwriting!" + warm "Ensure that you manually configure the appropriate settings." kasm_config_file="/dev/stderr" else - echo "WARNING: This may prevent custom user KasmVNC settings from applying!" + warn "This may prevent custom user KasmVNC settings from applying!" mkdir -p "$HOME/.vnc" fi fi @@ -213,8 +216,71 @@ network: pem_key: udp: public_ip: 127.0.0.1 +logging: + log_writer_name: all + log_dest: logfile + level: 30 EOF +get_http_dir() { + # determine the served file path + # Start with the default + httpd_directory="/usr/share/kasmvnc/www" + + # Check the system configuration path + if [[ -e /etc/kasmvnc/kasmvnc.yaml ]]; then + d=($(grep -E "^\s*httpd_directory:.*$" /etc/kasmvnc/kasmvnc.yaml)) + # If this grep is successful, it will return: + # httpd_directory: /usr/share/kasmvnc/www + if [[ $${#d[@]} -eq 2 && -d "$${d[1]}" ]]; then + httpd_directory="$${d[1]}" + fi + fi + + # Check the home directory for overriding values + if [[ -e "$HOME/.vnc/kasmvnc.yaml" ]]; then + d=($(grep -E "^\s*httpd_directory:.*$" /etc/kasmvnc/kasmvnc.yaml)) + if [[ $${#d[@]} -eq 2 && -d "$${d[1]}" ]]; then + httpd_directory="$${d[1]}" + fi + fi + echo $httpd_directory +} + +fix_server_index_file(){ + local fname=$${FUNCNAME[0]} # gets current function name + if [[ $# -ne 1 ]]; then + error "$fname requires exactly 1 parameter:\n\tpath to KasmVNC httpd_directory" + fi + local httpdir="$1" + if [[ ! -d "$httpdir" ]]; then + error "$fname: $httpdir is not a directory" + fi + pushd "$httpdir" > /dev/null + + cat <