11#! /usr/bin/env bash
22
3- #! /bin/bash
3+ # Exit on error, undefined variables, and pipe failures
4+ set -euo pipefail
45
56# Function to check if vncserver is already installed
67check_installed () {
@@ -14,166 +15,221 @@ check_installed() {
1415
1516# Function to download a file using wget, curl, or busybox as a fallback
1617download_file () {
17- local url=$1
18- local output=$2
19- if command -v wget & > /dev/null; then
20- wget $url -O $output
21- elif command -v curl & > /dev/null; then
22- curl -fsSL $url -o $output
18+ local url=" $1 "
19+ local output=" $2 "
20+ local download_tool
21+
22+ if command -v curl & > /dev/null; then
23+ # shellcheck disable=SC2034
24+ download_tool=(curl -fsSL)
25+ elif command -v wget & > /dev/null; then
26+ # shellcheck disable=SC2034
27+ download_tool=(wget -q -O-)
2328 elif command -v busybox & > /dev/null; then
24- busybox wget -O $output $url
29+ # shellcheck disable=SC2034
30+ download_tool=(busybox wget -O-)
2531 else
26- echo " Neither wget, curl, nor busybox is installed. Please install one of them to proceed. "
32+ echo " ERROR: No download tool available (curl, wget, or busybox required) "
2733 exit 1
2834 fi
35+
36+ # shellcheck disable=SC2288
37+ " $$ {download_tool[@]}" " $url " > " $output " || {
38+ echo " ERROR: Failed to download $url "
39+ exit 1
40+ }
2941}
3042
3143# Function to install kasmvncserver for debian-based distros
3244install_deb () {
3345 local url=$1
34- download_file $url /tmp/kasmvncserver.deb
35- sudo apt-get update
36- DEBIAN_FRONTEND=noninteractive sudo apt-get install --yes -qq --no-install-recommends --no-install-suggests /tmp/kasmvncserver.deb
37- sudo adduser $USER ssl-cert
38- rm /tmp/kasmvncserver.deb
39- }
46+ local kasmdeb=" /tmp/kasmvncserver.deb"
4047
41- # Function to install kasmvncserver for Oracle 8
42- install_rpm_oracle8 () {
43- local url=$1
44- download_file $url /tmp/kasmvncserver.rpm
45- sudo dnf config-manager --set-enabled ol8_codeready_builder
46- sudo dnf install oracle-epel-release-el8 -y
47- sudo dnf localinstall /tmp/kasmvncserver.rpm -y
48- sudo usermod -aG kasmvnc-cert $USER
49- rm /tmp/kasmvncserver.rpm
50- }
48+ download_file " $url " " $kasmdeb "
5149
52- # Function to install kasmvncserver for CentOS 7
53- install_rpm_centos7 () {
54- local url=$1
55- download_file $url /tmp/kasmvncserver.rpm
56- sudo yum install epel-release -y
57- sudo yum install /tmp/kasmvncserver.rpm -y
58- sudo usermod -aG kasmvnc-cert $USER
59- rm /tmp/kasmvncserver.rpm
50+ CACHE_DIR=" /var/lib/apt/lists/partial"
51+ # Check if the directory exists and was modified in the last 60 minutes
52+ if [[ ! -d " $CACHE_DIR " ]] || ! find " $CACHE_DIR " -mmin -60 -print -quit & > /dev/null; then
53+ echo " Stale package cache, updating..."
54+ # Update package cache with a 300-second timeout for dpkg lock
55+ sudo apt-get -o DPkg::Lock::Timeout=300 -qq update
56+ fi
57+
58+ DEBIAN_FRONTEND=noninteractive sudo apt-get -o DPkg::Lock::Timeout=300 install --yes -qq --no-install-recommends --no-install-suggests " $kasmdeb "
59+ rm " $kasmdeb "
6060}
6161
6262# Function to install kasmvncserver for rpm-based distros
6363install_rpm () {
6464 local url=$1
65- download_file $url /tmp/kasmvncserver.rpm
66- sudo rpm -i /tmp/kasmvncserver.rpm
67- rm /tmp/kasmvncserver.rpm
65+ local kasmrpm=" /tmp/kasmvncserver.rpm"
66+ local package_manager
67+
68+ if command -v dnf & > /dev/null; then
69+ # shellcheck disable=SC2034
70+ package_manager=(dnf localinstall -y)
71+ elif command -v zypper & > /dev/null; then
72+ # shellcheck disable=SC2034
73+ package_manager=(zypper install -y)
74+ elif command -v yum & > /dev/null; then
75+ # shellcheck disable=SC2034
76+ package_manager=(yum localinstall -y)
77+ elif command -v rpm & > /dev/null; then
78+ # Do we need to manually handle missing dependencies?
79+ # shellcheck disable=SC2034
80+ package_manager=(rpm -i)
81+ else
82+ echo " ERROR: No supported package manager available (dnf, zypper, yum, or rpm required)"
83+ exit 1
84+ fi
85+
86+ download_file " $url " " $kasmrpm "
87+
88+ # shellcheck disable=SC2288
89+ sudo " $$ {package_manager[@]}" " $kasmrpm " || {
90+ echo " ERROR: Failed to install $kasmrpm "
91+ exit 1
92+ }
93+
94+ rm " $kasmrpm "
6895}
6996
7097# Function to install kasmvncserver for Alpine Linux
7198install_alpine () {
7299 local url=$1
73- download_file $url /tmp/kasmvncserver.tgz
74- tar -xzf /tmp/kasmvncserver.tgz -C /usr/local/bin/
75- rm /tmp/kasmvncserver.tgz
100+ local kasmtgz=" /tmp/kasmvncserver.tgz"
101+
102+ download_file " $url " " $kasmtgz "
103+
104+ tar -xzf " $kasmtgz " -C /usr/local/bin/
105+ rm " $kasmtgz "
76106}
77107
78108# Detect system information
79- distro=$( grep " ^ID=" /etc/os-release | awk -F= ' {print $2}' )
80- version=$( grep " ^VERSION_ID=" /etc/os-release | awk -F= ' {print $2}' | tr -d ' "' )
81- arch=$( uname -m)
109+ if [[ ! -f /etc/os-release ]]; then
110+ echo " ERROR: Cannot detect OS: /etc/os-release not found"
111+ exit 1
112+ fi
113+
114+ # shellcheck disable=SC1091
115+ source /etc/os-release
116+ distro=" $ID "
117+ distro_version=" $VERSION_ID "
118+ codename=" $VERSION_CODENAME "
119+ arch=" $( uname -m) "
120+ if [[ " $ID " == " ol" ]]; then
121+ distro=" oracle"
122+ distro_version=" $$ {distro_version%%.*}"
123+ elif [[ " $ID " == " fedora" ]]; then
124+ distro_version=" $( grep -oP ' \(\K[\w ]+' /etc/fedora-release | tr ' [:upper:]' ' [:lower:]' | tr -d ' ' ) "
125+ fi
82126
83127echo " Detected Distribution: $distro "
84- echo " Detected Version: $version "
128+ echo " Detected Version: $distro_version "
129+ echo " Detected Codename: $codename "
85130echo " Detected Architecture: $arch "
86131
87132# Map arch to package arch
88- if [[ " $arch " == " x86_64" ]]; then
89- if [[ " $distro " == " ubuntu" || " $distro " == " debian" || " $distro " == " kali" ]]; then
90- arch=" amd64"
91- else
92- arch=" x86_64"
93- fi
94- elif [[ " $arch " == " aarch64" || " $arch " == " arm64" ]]; then
95- if [[ " $distro " == " ubuntu" || " $distro " == " debian" || " $distro " == " kali" ]]; then
96- arch=" arm64"
97- else
98- arch=" aarch64"
99- fi
100- else
101- echo " Unsupported architecture: $arch "
102- exit 1
103- fi
133+ case " $arch " in
134+ x86_64)
135+ if [[ " $distro " =~ ^(ubuntu| debian| kali)$ ]]; then
136+ arch=" amd64"
137+ fi
138+ ;;
139+ aarch64)
140+ if [[ " $distro " =~ ^(ubuntu| debian| kali)$ ]]; then
141+ arch=" arm64"
142+ fi
143+ ;;
144+ arm64)
145+ : # This is effectively a noop
146+ ;;
147+ * )
148+ echo " ERROR: Unsupported architecture: $arch "
149+ exit 1
150+ ;;
151+ esac
104152
105153# Check if vncserver is installed, and install if not
106154if ! check_installed; then
107- echo " Installing KASM version: ${VERSION} "
155+ # Check for NOPASSWD sudo (required)
156+ if ! command -v sudo & > /dev/null || ! sudo -n true 2> /dev/null; then
157+ echo " ERROR: sudo NOPASSWD access required!"
158+ exit 1
159+ fi
160+
161+ base_url=" https://github.com/kasmtech/KasmVNC/releases/download/v${KASM_VERSION} "
162+
163+ echo " Installing KASM version: ${KASM_VERSION} "
108164 case $distro in
109165 ubuntu | debian | kali)
110- case $version in
111- " 20.04" )
112- install_deb " https://github.com/kasmtech/KasmVNC/releases/download/v${VERSION} /kasmvncserver_focal_${VERSION} _$$ {arch}.deb"
113- ;;
114- " 22.04" )
115- install_deb " https://github.com/kasmtech/KasmVNC/releases/download/v${VERSION} /kasmvncserver_jammy_${VERSION} _$$ {arch}.deb"
116- ;;
117- " 24.04" )
118- install_deb " https://github.com/kasmtech/KasmVNC/releases/download/v${VERSION} /kasmvncserver_noble_${VERSION} _$$ {arch}.deb"
119- ;;
120- * )
121- echo " Unsupported Ubuntu/Debian/Kali version: $$ {version}"
122- exit 1
123- ;;
124- esac
166+ bin_name=" kasmvncserver_$$ {codename}_${KASM_VERSION} _$$ {arch}.deb"
167+ install_deb " $base_url /$bin_name "
125168 ;;
126- oracle)
127- if [[ " $version " == " 8" ]]; then
128- install_rpm_oracle8 " https://github.com/kasmtech/KasmVNC/releases/download/v${VERSION} /kasmvncserver_oracle_8_${VERSION} _$$ {arch}.rpm"
129- else
130- echo " Unsupported Oracle version: $$ {version}"
131- exit 1
132- fi
133- ;;
134- centos)
135- if [[ " $version " == " 7" ]]; then
136- install_rpm_centos7 " https://github.com/kasmtech/KasmVNC/releases/download/v${VERSION} /kasmvncserver_centos_core_${VERSION} _$$ {arch}.rpm"
137- else
138- install_rpm " https://github.com/kasmtech/KasmVNC/releases/download/v${VERSION} /kasmvncserver_centos_core_${VERSION} _$$ {arch}.rpm"
139- fi
169+ oracle | fedora | opensuse)
170+ bin_name=" kasmvncserver_$$ {distro}_$$ {distro_version}_${KASM_VERSION} _$$ {arch}.rpm"
171+ install_rpm " $base_url /$bin_name "
140172 ;;
141173 alpine)
142- if [[ " $version " == " 3.17" || " $version " == " 3.18" || " $version " == " 3.19" || " $version " == " 3.20" ]]; then
143- install_alpine " https://github.com/kasmtech/KasmVNC/releases/download/v${VERSION} /kasmvnc.alpine_$$ {version}_$$ {arch}.tgz"
144- else
145- echo " Unsupported Alpine version: $$ {version}"
146- exit 1
147- fi
148- ;;
149- fedora | opensuse)
150- install_rpm " https://github.com/kasmtech/KasmVNC/releases/download/v${VERSION} /kasmvncserver_$$ {distro}_$$ {version}_${VERSION} _$$ {arch}.rpm"
174+ bin_name=" kasmvnc.alpine_$$ {distro_version//./}_$$ {arch}.tgz"
175+ install_alpine " $base_url /$bin_name "
151176 ;;
152177 * )
153- echo " Unsupported distribution: $$ { distro} "
178+ echo " Unsupported distribution: $distro "
154179 exit 1
155180 ;;
156181 esac
157182else
158183 echo " vncserver already installed. Skipping installation."
159184fi
160185
161- # Coder port-forwarding from dashboard only supports HTTP
162- sudo bash -c " cat > /etc/kasmvnc/kasmvnc.yaml <<EOF
186+ if command -v sudo & > /dev/null && sudo -n true 2> /dev/null; then
187+ kasm_config_file=" /etc/kasmvnc/kasmvnc.yaml"
188+ SUDO=sudo
189+ else
190+ kasm_config_file=" $HOME /.vnc/kasmvnc.yaml"
191+ SUDO=
192+
193+ echo " WARNING: Sudo access not available, using user config dir!"
194+
195+ if [[ -f " $kasm_config_file " ]]; then
196+ echo " WARNING: Custom user KasmVNC config exists, not overwriting!"
197+ echo " WARNING: Ensure that you manually configure the appropriate settings."
198+ kasm_config_file=" /dev/stderr"
199+ else
200+ echo " WARNING: This may prevent custom user KasmVNC settings from applying!"
201+ mkdir -p " $HOME /.vnc"
202+ fi
203+ fi
204+
205+ echo " Writing KasmVNC config to $kasm_config_file "
206+ $SUDO tee " $kasm_config_file " > /dev/null << EOF
163207network:
164208 protocol: http
165209 websocket_port: ${PORT}
166210 ssl:
167211 require_ssl: false
212+ pem_certificate:
213+ pem_key:
168214 udp:
169215 public_ip: 127.0.0.1
170- EOF"
216+ EOF
171217
172218# This password is not used since we start the server without auth.
173219# The server is protected via the Coder session token / tunnel
174220# and does not listen publicly
175- echo -e " password\npassword\n" | vncpasswd -wo -u $USER
221+ echo -e " password\npassword\n" | vncpasswd -wo -u " $USER "
176222
177223# Start the server
178224printf " 🚀 Starting KasmVNC server...\n"
179- sudo -u $USER bash -c " vncserver -select-de ${DESKTOP_ENVIRONMENT} -disableBasicAuth" > /tmp/kasmvncserver.log 2>&1 &
225+ vncserver -select-de " ${DESKTOP_ENVIRONMENT} " -disableBasicAuth > /tmp/kasmvncserver.log 2>&1 &
226+ pid=$!
227+
228+ # Wait for server to start
229+ sleep 5
230+ grep -v ' ^[[:space:]]*$' /tmp/kasmvncserver.log | tail -n 10
231+ if ps -p $pid | grep -q " ^$pid " ; then
232+ echo " ERROR: Failed to start KasmVNC server. Check full logs at /tmp/kasmvncserver.log"
233+ exit 1
234+ fi
235+ printf " 🚀 KasmVNC server started successfully!\n"
0 commit comments