@ -1,6 +1,7 @@
#!/usr/bin/env bash
#!/bin/bash
# Exit on error, undefined variables, and pipe failures
set -euo pipefail
# Function to check if vncserver is already installed
check_installed( ) {
@ -14,143 +15,167 @@ check_installed() {
# Function to download a file using wget, curl, or busybox as a fallback
download_file( ) {
local url = $1
local output = $2
if command -v wget & > /dev/null; then
wget $url -O $output
elif command -v curl & > /dev/null; then
curl -fsSL $url -o $output
local url = " $1 "
local output = " $2 "
local download_tool
if command -v curl & > /dev/null; then
# shellcheck disable=SC2034
download_tool = ( curl -fsSL)
elif command -v wget & > /dev/null; then
# shellcheck disable=SC2034
download_tool = ( wget -q -O-)
elif command -v busybox & > /dev/null; then
busybox wget -O $output $url
# shellcheck disable=SC2034
download_tool = ( busybox wget -O-)
else
echo "Neither wget, curl, nor busybox is installed. Please install one of them to proceed."
echo " ERROR: No download tool available (curl, wget, or busybox required) "
exit 1
fi
# shellcheck disable=SC2288
" $$ {download_tool[@]} " " $url " > " $output " || {
echo " ERROR: Failed to download $url "
exit 1
}
}
# Function to install kasmvncserver for debian-based distros
install_deb( ) {
local url = $1
download_file $url /tmp/kasmvncserver.deb
sudo apt-get update
DEBIAN_FRONTEND = noninteractive sudo apt-get install --yes -qq --no-install-recommends --no-install-suggests /tmp/kasmvncserver.deb
sudo adduser $USER ssl-cert
rm /tmp/kasmvncserver.deb
}
local kasmdeb = "/tmp/kasmvncserver.deb"
# Function to install kasmvncserver for Oracle 8
install_rpm_oracle8( ) {
local url = $1
download_file $url /tmp/kasmvncserver.rpm
sudo dnf config-manager --set-enabled ol8_codeready_builder
sudo dnf install oracle-epel-release-el8 -y
sudo dnf localinstall /tmp/kasmvncserver.rpm -y
sudo usermod -aG kasmvnc-cert $USER
rm /tmp/kasmvncserver.rpm
}
download_file " $url " " $kasmdeb "
# Function to install kasmvncserver for CentOS 7
install_rpm_centos7( ) {
local url = $1
download_file $url /tmp/kasmvncserver.rpm
sudo yum install epel-release -y
sudo yum install /tmp/kasmvncserver.rpm -y
sudo usermod -aG kasmvnc-cert $USER
rm /tmp/kasmvncserver.rpm
CACHE_DIR = "/var/lib/apt/lists/partial"
# Check if the directory exists and was modified in the last 60 minutes
if [ [ ! -d " $CACHE_DIR " ] ] || ! find " $CACHE_DIR " -mmin -60 -print -quit & > /dev/null; then
echo "Stale package cache, updating..."
# Update package cache with a 300-second timeout for dpkg lock
sudo apt-get -o DPkg::Lock::Timeout= 300 -qq update
fi
DEBIAN_FRONTEND = noninteractive sudo apt-get -o DPkg::Lock::Timeout= 300 install --yes -qq --no-install-recommends --no-install-suggests " $kasmdeb "
rm " $kasmdeb "
}
# Function to install kasmvncserver for rpm-based distros
install_rpm( ) {
local url = $1
download_file $url /tmp/kasmvncserver.rpm
sudo rpm -i /tmp/kasmvncserver.rpm
rm /tmp/kasmvncserver.rpm
local kasmrpm = "/tmp/kasmvncserver.rpm"
local package_manager
if command -v dnf & > /dev/null; then
# shellcheck disable=SC2034
package_manager = ( dnf localinstall -y)
elif command -v zypper & > /dev/null; then
# shellcheck disable=SC2034
package_manager = ( zypper install -y)
elif command -v yum & > /dev/null; then
# shellcheck disable=SC2034
package_manager = ( yum localinstall -y)
elif command -v rpm & > /dev/null; then
# Do we need to manually handle missing dependencies?
# shellcheck disable=SC2034
package_manager = ( rpm -i)
else
echo "ERROR: No supported package manager available (dnf, zypper, yum, or rpm required)"
exit 1
fi
download_file " $url " " $kasmrpm "
# shellcheck disable=SC2288
sudo " $$ {package_manager[@]} " " $kasmrpm " || {
echo " ERROR: Failed to install $kasmrpm "
exit 1
}
rm " $kasmrpm "
}
# Function to install kasmvncserver for Alpine Linux
install_alpine( ) {
local url = $1
download_file $url /tmp/kasmvncserver.tgz
tar -xzf /tmp/kasmvncserver.tgz -C /usr/local/bin/
rm /tmp/kasmvncserver.tgz
local kasmtgz = "/tmp/kasmvncserver.tgz"
download_file " $url " " $kasmtgz "
tar -xzf " $kasmtgz " -C /usr/local/bin/
rm " $kasmtgz "
}
# Detect system information
distro = $( grep "^ID=" /etc/os-release | awk -F= '{print $2}' )
version = $( grep "^VERSION_ID=" /etc/os-release | awk -F= '{print $2}' | tr -d '"' )
arch = $( uname -m)
if [ [ ! -f /etc/os-release ] ] ; then
echo "ERROR: Cannot detect OS: /etc/os-release not found"
exit 1
fi
# shellcheck disable=SC1091
source /etc/os-release
distro = " $ID "
distro_version = " $VERSION_ID "
codename = " $VERSION_CODENAME "
arch = " $( uname -m) "
if [ [ " $ID " = = "ol" ] ] ; then
distro = "oracle"
distro_version = " $$ {distro_version%%.*} "
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: $version "
echo " Detected Version: $distro_version "
echo " Detected Codename: $codename "
echo " Detected Architecture: $arch "
# Map arch to package arch
if [ [ " $arch " = = "x86_64" ] ] ; then
if [ [ " $distro " = = "ubuntu" || " $distro " = = "debian" || " $distro " = = "kali" ] ] ; then
arch = "amd64"
else
arch = "x86_64"
fi
elif [ [ " $arch " = = "aarch64" || " $arch " = = "arm64" ] ] ; then
if [ [ " $distro " = = "ubuntu" || " $distro " = = "debian" || " $distro " = = "kali" ] ] ; then
arch = "arm64"
else
arch = "aarch64"
fi
else
echo " Unsupported architecture: $arch "
exit 1
fi
case " $arch " in
x86_64)
if [ [ " $distro " = ~ ^( ubuntu| debian| kali) $ ] ] ; then
arch = "amd64"
fi
; ;
aarch64)
if [ [ " $distro " = ~ ^( ubuntu| debian| kali) $ ] ] ; then
arch = "arm64"
fi
; ;
arm64)
: # This is effectively a noop
; ;
*)
echo " ERROR: Unsupported architecture: $arch "
exit 1
; ;
esac
# Check if vncserver is installed, and install if not
if ! check_installed; then
echo " Installing KASM version: ${ VERSION } "
# 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
fi
base_url = " https://github.com/kasmtech/KasmVNC/releases/download/v ${ KASM_VERSION } "
echo " Installing KASM version: ${ KASM_VERSION } "
case $distro in
ubuntu | debian | kali)
case $version in
"20.04" )
install_deb " https://github.com/kasmtech/KasmVNC/releases/download/v ${ VERSION } /kasmvncserver_focal_ ${ VERSION } _ $$ {arch}.deb "
; ;
"22.04" )
install_deb " https://github.com/kasmtech/KasmVNC/releases/download/v ${ VERSION } /kasmvncserver_jammy_ ${ VERSION } _ $$ {arch}.deb "
; ;
"24.04" )
install_deb " https://github.com/kasmtech/KasmVNC/releases/download/v ${ VERSION } /kasmvncserver_noble_ ${ VERSION } _ $$ {arch}.deb "
; ;
*)
echo " Unsupported Ubuntu/Debian/Kali version: $$ {version} "
exit 1
; ;
esac
bin_name = " kasmvncserver_ $$ {codename}_ ${ KASM_VERSION } _ $$ {arch}.deb "
install_deb " $base_url / $bin_name "
; ;
oracle)
if [ [ " $version " = = "8" ] ] ; then
install_rpm_oracle8 " https://github.com/kasmtech/KasmVNC/releases/download/v ${ VERSION } /kasmvncserver_oracle_8_ ${ VERSION } _ $$ {arch}.rpm "
else
echo " Unsupported Oracle version: $$ {version} "
exit 1
fi
; ;
centos)
if [ [ " $version " = = "7" ] ] ; then
install_rpm_centos7 " https://github.com/kasmtech/KasmVNC/releases/download/v ${ VERSION } /kasmvncserver_centos_core_ ${ VERSION } _ $$ {arch}.rpm "
else
install_rpm " https://github.com/kasmtech/KasmVNC/releases/download/v ${ VERSION } /kasmvncserver_centos_core_ ${ VERSION } _ $$ {arch}.rpm "
fi
oracle | fedora | opensuse)
bin_name = " kasmvncserver_ $$ {distro}_ $$ {distro_version}_ ${ KASM_VERSION } _ $$ {arch}.rpm "
install_rpm " $base_url / $bin_name "
; ;
alpine)
if [ [ " $version " = = "3.17" || " $version " = = "3.18" || " $version " = = "3.19" || " $version " = = "3.20" ] ] ; then
install_alpine " https://github.com/kasmtech/KasmVNC/releases/download/v ${ VERSION } /kasmvnc.alpine_ $$ {version}_ $$ {arch}.tgz "
else
echo " Unsupported Alpine version: $$ {version} "
exit 1
fi
; ;
fedora | opensuse)
install_rpm " https://github.com/kasmtech/KasmVNC/releases/download/v ${ VERSION } /kasmvncserver_ $$ {distro}_ $$ {version}_ ${ VERSION } _ $$ {arch}.rpm "
bin_name = " kasmvnc.alpine_ $$ {distro_version//./}_ $$ {arch}.tgz "
install_alpine " $base_url / $bin_name "
; ;
*)
echo " Unsupported distribution: $ ${ distro} "
echo " Unsupported distribution: $distro "
exit 1
; ;
esac
@ -158,22 +183,53 @@ else
echo "vncserver already installed. Skipping installation."
fi
# Coder port-forwarding from dashboard only supports HTTP
sudo bash -c " cat > /etc/kasmvnc/kasmvnc.yaml <<EOF
if command -v sudo & > /dev/null && sudo -n true 2> /dev/null; then
kasm_config_file = "/etc/kasmvnc/kasmvnc.yaml"
SUDO = sudo
else
kasm_config_file = " $HOME /.vnc/kasmvnc.yaml "
SUDO =
echo "WARNING: 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."
kasm_config_file = "/dev/stderr"
else
echo "WARNING: This may prevent custom user KasmVNC settings from applying!"
mkdir -p " $HOME /.vnc "
fi
fi
echo " Writing KasmVNC config to $kasm_config_file "
$SUDO tee " $kasm_config_file " > /dev/null << EOF
network:
protocol: http
websocket_port: ${ PORT }
ssl:
require_ssl: false
pem_certificate:
pem_key:
udp:
public_ip: 127.0.0.1
EOF"
EOF
# This password is not used since we start the server without auth.
# The server is protected via the Coder session token / tunnel
# and does not listen publicly
echo -e "password\npassword\n" | vncpasswd -wo -u $USER
echo -e "password\npassword\n" | vncpasswd -wo -u " $USER "
# Start the server
printf "🚀 Starting KasmVNC server...\n"
sudo -u $USER bash -c " vncserver -select-de ${ DESKTOP_ENVIRONMENT } -disableBasicAuth " > /tmp/kasmvncserver.log 2>& 1 &
vncserver -select-de " ${ DESKTOP_ENVIRONMENT } " -disableBasicAuth > /tmp/kasmvncserver.log 2>& 1 &
pid = $!
# Wait for server to start
sleep 5
grep -v '^[[:space:]]*$' /tmp/kasmvncserver.log | tail -n 10
if ps -p $pid | grep -q " ^ $pid " ; then
echo "ERROR: Failed to start KasmVNC server. Check full logs at /tmp/kasmvncserver.log"
exit 1
fi
printf "🚀 KasmVNC server started successfully!\n"