1
1
#! /usr/bin/env bash
2
2
3
- #! /bin/bash
3
+ # Exit on error, undefined variables, and pipe failures
4
+ set -euo pipefail
4
5
5
6
# Function to check if vncserver is already installed
6
7
check_installed () {
@@ -14,166 +15,221 @@ check_installed() {
14
15
15
16
# Function to download a file using wget, curl, or busybox as a fallback
16
17
download_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-)
23
28
elif command -v busybox & > /dev/null; then
24
- busybox wget -O $output $url
29
+ # shellcheck disable=SC2034
30
+ download_tool=(busybox wget -O-)
25
31
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) "
27
33
exit 1
28
34
fi
35
+
36
+ # shellcheck disable=SC2288
37
+ " $$ {download_tool[@]}" " $url " > " $output " || {
38
+ echo " ERROR: Failed to download $url "
39
+ exit 1
40
+ }
29
41
}
30
42
31
43
# Function to install kasmvncserver for debian-based distros
32
44
install_deb () {
33
45
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"
40
47
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 "
51
49
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 "
60
60
}
61
61
62
62
# Function to install kasmvncserver for rpm-based distros
63
63
install_rpm () {
64
64
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 "
68
95
}
69
96
70
97
# Function to install kasmvncserver for Alpine Linux
71
98
install_alpine () {
72
99
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 "
76
106
}
77
107
78
108
# 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
82
126
83
127
echo " Detected Distribution: $distro "
84
- echo " Detected Version: $version "
128
+ echo " Detected Version: $distro_version "
129
+ echo " Detected Codename: $codename "
85
130
echo " Detected Architecture: $arch "
86
131
87
132
# 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
104
152
105
153
# Check if vncserver is installed, and install if not
106
154
if ! 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} "
108
164
case $distro in
109
165
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 "
125
168
;;
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 "
140
172
;;
141
173
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 "
151
176
;;
152
177
* )
153
- echo " Unsupported distribution: $$ { distro} "
178
+ echo " Unsupported distribution: $distro "
154
179
exit 1
155
180
;;
156
181
esac
157
182
else
158
183
echo " vncserver already installed. Skipping installation."
159
184
fi
160
185
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
163
207
network:
164
208
protocol: http
165
209
websocket_port: ${PORT}
166
210
ssl:
167
211
require_ssl: false
212
+ pem_certificate:
213
+ pem_key:
168
214
udp:
169
215
public_ip: 127.0.0.1
170
- EOF"
216
+ EOF
171
217
172
218
# This password is not used since we start the server without auth.
173
219
# The server is protected via the Coder session token / tunnel
174
220
# 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 "
176
222
177
223
# Start the server
178
224
printf " 🚀 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