master
sh 416 lines 16.7 KB
Raw
1 #!/bin/bash
2
3 # Origin: https://github.com/Melo-Professional/MeshCentral-Stylish-UI
4 stylishui_base_url="https://github.com/Melo-Professional/MeshCentral-Stylish-UI/archive/refs"
5 stylishui_compat="https://raw.githubusercontent.com/Melo-Professional/MeshCentral-Stylish-UI/refs/heads/main/metadata/compat.json"
6
7 function graceful_shutdown() {
8 echo "Received SIGTERM from the container host. Cleaning up..."
9 kill -SIGINT "$meshcentral_pid"
10
11 echo "MeshCentral process stopped. Exiting..."
12 exit 0
13 }
14 trap graceful_shutdown SIGTERM
15
16 function test_url() {
17 if wget --spider "$1" &> /dev/null; then
18 echo "is ok."
19 return 0
20 else
21 echo "is NOT ok."
22 return 1
23 fi
24 }
25
26
27 function dynamic_config() {
28 # BEGIN DATABASE CONFIGURATION FIELDS
29 USE_MONGODB=${USE_MONGODB,,}
30 if [[ "$USE_MONGODB" =~ ^(true|yes)$ ]]; then
31 echo "Enabling MongoDB-connector..."
32
33 if [[ -n "$MONGO_URL" ]]; then
34 echo "MONGO_URL is set, using that..."
35 else
36 MONGO_URL="${MONGO_URL:-$MONGO_USERNAME:$MONGO_PASS@}$MONGO_HOST:$MONGO_PORT"
37 fi
38
39 #ESCAPED_MONGO_URL=$(echo "$MONGO_URL" | sed 's/[\/&?=:]/\\&/g')
40 sed -i 's/"_mongoDb"/"mongoDb"/' "$CONFIG_FILE"
41 jq --arg mongo_url "$MONGO_URL" \
42 '.settings.mongoDb = $mongo_url' \
43 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
44 else
45 echo "Disabling MongoDB-connector..."
46 sed -i 's/"mongoDb"/"_mongoDb"/' "$CONFIG_FILE"
47 fi
48
49 USE_POSTGRESQL=${USE_POSTGRESQL,,}
50 if [[ "$USE_POSTGRESQL" =~ ^(true|yes)$ ]]; then
51 echo "Enabling PostgreSQL-connector..."
52
53 sed -i 's/"_postgres"/"postgres"/' "$CONFIG_FILE"
54 jq --arg psql_host "$PSQL_HOST" \
55 --arg psql_port "$PSQL_PORT" \
56 --arg psql_user "$PSQL_USER" \
57 --arg psql_pass "$PSQL_PASS" \
58 --arg psql_db "$PSQL_DATABASE" \
59 '.settings.postgres.host = $psql_host |
60 .settings.postgres.port = $psql_port |
61 .settings.postgres.user = $psql_user |
62 .settings.postgres.password = $psql_pass |
63 .settings.postgres.database = $psql_db' \
64 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
65 else
66 echo "Disabling PostgreSQL-connector..."
67 sed -i 's/"postgres"/"_postgres"/' "$CONFIG_FILE"
68 fi
69
70 USE_MARIADB=${USE_MARIADB,,}
71 if [[ "$USE_MARIADB" =~ ^(true|yes)$ ]]; then
72 echo "Enabling MariaDB-connector..."
73 sed -i 's/"_mariaDB"/"mariaDB"/' "$CONFIG_FILE"
74 jq --arg mariadb_host "$MARIADB_HOST" \
75 --arg mariadb_port "$MARIADB_PORT" \
76 --arg mariadb_user "$MARIADB_USER" \
77 --arg mariadb_pass "$MARIADB_PASS" \
78 --arg mariadb_db "$MARIADB_DATABASE" \
79 '.settings.mariaDB.host = $mariadb_host |
80 .settings.mariaDB.port = $mariadb_port |
81 .settings.mariaDB.user = $mariadb_user |
82 .settings.mariaDB.password = $mariadb_pass |
83 .settings.mariaDB.database = $mariadb_db' \
84 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
85 else
86 echo "Disabling MariaDB-connector..."
87 sed -i 's/"mariaDB"/"_mariaDB"/' "$CONFIG_FILE"
88 fi
89 # END DATABASE CONFIGURATION FIELDS
90
91 # Doing the bulk with JQ utility. Given the remaining variables an opportunity with Sed.
92 # The way this works is if the environment variable is empty, it will add a _ in front of the variable, commenting it.
93 # This will make the default value apply, as per: https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json
94
95 echo "Compiling given environment variables..."
96 echo "If defaults are going to get applied, refer to: https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json"
97
98 # SESSIONKEY
99 if [[ "${REGEN_SESSIONKEY,,}" =~ ^(true|yes)$ ]]; then
100 echo "Regenerating Session-Key because REGENSESSIONKEY is 'true' or 'yes'"
101 SESSION_KEY=$(tr -dc 'A-Z0-9' < /dev/urandom | fold -w 96 | head -n 1)
102
103 sed -i 's/"_sessionKey"/"sessionKey"/' "$CONFIG_FILE"
104 jq --arg session_key "$SESSION_KEY" \
105 '.settings.sessionKey = $session_key' \
106 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
107 else
108 echo "REGENSESSIONKEY is not 'true' or 'yes', therefore it's being kept as is."
109 fi
110
111 # HOSTNAME
112 if [[ -n "$HOSTNAME" ]]; then
113 echo "Setting hostname (cert)... $HOSTNAME"
114
115 jq --arg hostname "$HOSTNAME" \
116 '.settings.cert = $hostname' \
117 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
118 else
119 echo "Invalid or no hostname, defaulting to 'localhost', value(s) given: ${HOSTNAME:-empty}"
120 jq --arg hostname "localhost" \
121 '.settings.cert = $hostname' \
122 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
123 fi
124
125 # PORT
126 if [[ -n "$PORT" ]]; then
127 echo "Setting port... $PORT"
128
129 jq --arg port "$PORT" \
130 '.settings.port = $port' \
131 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
132 else
133 echo "Invalid or no port, defaulting to '443', Value(s) given: ${PORT:-empty}"
134 jq --arg port "443" \
135 '.settings.port = $port' \
136 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
137 fi
138
139 # REDIR_PORT
140 if [[ -n "$REDIR_PORT" ]]; then
141 echo "Setting redirport... $REDIR_PORT"
142
143 jq --arg redirport "$REDIR_PORT" \
144 '.settings.redirPort = $redirport' \
145 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
146 else
147 echo "Invalid or no redirport, defaulting to '80', Value(s) given: ${REDIR_PORT:-empty}"
148 jq --arg redirport "80" \
149 '.settings.redirPort = $redirport' \
150 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
151 fi
152
153 # ALLOWPLUGINS
154 ALLOW_PLUGINS=${ALLOW_PLUGINS,,}
155 if [[ "$ALLOW_PLUGINS" =~ ^(true|false)$ ]]; then
156 echo "Setting plugins... $ALLOW_PLUGINS"
157
158 sed -i 's/"_plugins"/"plugins"/' "$CONFIG_FILE"
159 jq --argjson allow_plugins "$ALLOW_PLUGINS" \
160 '.settings.plugins.enabled = $allow_plugins' \
161 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
162 else
163 echo "Invalid or no ALLOWPLUGINS value given, commenting out so default applies... Value(s) given: ${ALLOW_PLUGINS:-empty}"
164 sed -i 's/"plugins":/"_plugins":/g' "$CONFIG_FILE"
165 fi
166
167 # WEBRTC
168 WEBRTC=${WEBRTC,,}
169 if [[ "$WEBRTC" =~ ^(true|false)$ ]]; then
170 echo "Setting WebRTC... $WEBRTC"
171
172 sed -i 's/"_WebRTC"/"WebRTC"/' "$CONFIG_FILE"
173 jq --argjson webrtc "$WEBRTC" \
174 '.settings.WebRTC = $webrtc' \
175 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
176 #sed -i "s/\"WebRTC\": *[a-z]*/\"WebRTC\": $WEBRTC/" "$CONFIG_FILE"
177 else
178 echo "Invalid or no WEBRTC value given, commenting out so default applies... Value(s) given: ${WEBRTC:-empty}"
179 sed -i 's/"WebRTC":/"_WebRTC":/g' "$CONFIG_FILE"
180 fi
181
182 # IFRAME
183 IFRAME=${IFRAME,,}
184 if [[ "$IFRAME" =~ ^(true|false)$ ]]; then
185 echo "Setting AllowFraming... $IFRAME"
186
187 sed -i 's/"_AllowFraming"/"AllowFraming"/' "$CONFIG_FILE"
188 jq --argjson allow_framing "$IFRAME" \
189 '.settings.AllowFraming = $allow_framing' \
190 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
191 else
192 echo "Invalid or no IFRAME value given, commenting out so default applies... Value(s) given: ${IFRAME:-empty}"
193 sed -i 's/"AllowFraming":/"_AllowFraming":/g' "$CONFIG_FILE"
194 fi
195
196 # ALLOWED_ORIGIN
197 ALLOWED_ORIGIN=${ALLOWED_ORIGIN,,}
198 if [[ "$ALLOWED_ORIGIN" =~ ^(true|false)$ ]]; then
199 echo "Setting allowedOrigin... $ALLOWED_ORIGIN"
200
201 sed -i 's/"_allowedOrigin"/"allowedOrigin"/' "$CONFIG_FILE"
202 jq --argjson allowed_origin "$ALLOWED_ORIGIN" \
203 '.domains[""].allowedOrigin = $allowed_origin' \
204 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
205 else
206 echo "Invalid or no ALLOWED_ORIGIN value given, commenting out so default applies... Value(s) given: ${ALLOWED_ORIGIN:-empty}"
207 sed -i 's/"allowedOrigin":/"_allowedOrigin":/g' "$CONFIG_FILE"
208 fi
209
210 # certUrl || reverseProxy
211 if [[ -n "$REVERSE_PROXY" ]] && [[ -n "$REVERSE_PROXY_TLS_PORT" ]]; then
212 REVERSE_PROXY_STRING="${REVERSE_PROXY}:${REVERSE_PROXY_TLS_PORT}"
213
214 echo "Setting certUrl... - $REVERSE_PROXY_STRING"
215 sed -i 's/"_certUrl"/"certUrl"/' "$CONFIG_FILE"
216 jq --arg cert_url "$REVERSE_PROXY_STRING" \
217 '.domains[""].certUrl = $cert_url' \
218 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
219 #sed -i "s/\"certUrl\": *[a-z]*/\"certUrl\": $REVERSE_PROXY_STRING/" "$CONFIG_FILE"
220 else
221 echo "Invalid or no REVERSE_PROXY and/or REVERSE_PROXY_TLS_PORT value given, commenting out so default applies... Value(s) given: ${REVERSE_PROXY_STRING:-empty}"
222 sed -i 's/"certUrl":/"_certUrl":/g' "$CONFIG_FILE"
223 fi
224
225 # trustedProxy
226 if [[ -n "$TRUSTED_PROXY" ]]; then
227 echo "Setting trustedProxy... - $TRUSTED_PROXY"
228
229 if [[ "$TRUSTED_PROXY" == "all" ]] || [[ "$TRUSTED_PROXY" == "true" ]]; then
230 sed -i 's/"_trustedProxy"/"trustedProxy"/' "$CONFIG_FILE"
231 jq --argjson trusted_proxy "true" \
232 '.settings.trustedProxy = $trusted_proxy' \
233 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
234 else
235 sed -i 's/"_trustedProxy"/"trustedProxy"/' "$CONFIG_FILE"
236 jq --argjson trusted_proxy "$TRUSTED_PROXY" \
237 '.settings.trustedProxy = $trusted_proxy' \
238 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
239 fi
240 else
241 echo "Invalid or no TRUSTED_PROXY value given, commenting out so default applies... Value(s) given: ${TRUSTED_PROXY:-empty}"
242 sed -i 's/"trustedProxy":/"_trustedProxy":/g' "$CONFIG_FILE"
243 fi
244
245 # tlsOffload
246 if [[ -n "$TLS_OFFLOAD" ]]; then
247 echo "Setting tlsOffload... - $TLS_OFFLOAD"
248
249 sed -i 's/"_tlsOffload"/"tlsOffload"/' "$CONFIG_FILE"
250 jq --arg tls_offload "$TLS_OFFLOAD" \
251 '.settings.tlsOffload = $tls_offload' \
252 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
253 else
254 echo "Invalid or no TLS_OFFLOAD value given, commenting out so default applies... Value(s) given: ${TLS_OFFLOAD:-empty}"
255 sed -i 's/"tlsOffload":/"_tlsOffload":/g' "$CONFIG_FILE"
256 fi
257
258 # ALLOW_NEW_ACCOUNTS
259 ALLOW_NEW_ACCOUNTS=${ALLOW_NEW_ACCOUNTS,,}
260 if [[ "$ALLOW_NEW_ACCOUNTS" =~ ^(true|false)$ ]]; then
261 echo "Setting NewAccounts... $ALLOW_NEW_ACCOUNTS"
262
263 sed -i 's/"_NewAccounts"/"NewAccounts"/' "$CONFIG_FILE"
264 jq --argjson new_accounts "$ALLOW_NEW_ACCOUNTS" \
265 '.domains[""].NewAccounts = $new_accounts' \
266 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
267 else
268 echo "Invalid or no ALLOW_NEW_ACCOUNTS value given, commenting out so default applies... Value(s) given: ${ALLOW_NEW_ACCOUNTS:-empty}"
269 sed -i 's/"NewAccounts":/"_NewAccounts":/g' "$CONFIG_FILE"
270 fi
271
272 # LOCALSESSIONRECORDING
273 LOCAL_SESSION_RECORDING=${LOCAL_SESSION_RECORDING,,}
274 if [[ "$LOCAL_SESSION_RECORDING" =~ ^(true|false)$ ]]; then
275 echo "Setting localSessionRecording... $LOCAL_SESSION_RECORDING"
276
277 sed -i 's/"_localSessionRecording"/"localSessionRecording"/' "$CONFIG_FILE"
278 jq --argjson session_recording "$LOCAL_SESSION_RECORDING" \
279 '.domains[""].localSessionRecording = $session_recording' \
280 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
281 else
282 echo "Invalid or no LOCALSESSIONRECORDING value given, commenting out so default applies... Value(s) given: ${LOCAL_SESSION_RECORDING:-empty}"
283 sed -i 's/"localSessionRecording":/"_localSessionRecording":/g' "$CONFIG_FILE"
284 fi
285
286 # MINIFY
287 MINIFY=${MINIFY,,}
288 if [[ "$MINIFY" =~ ^(true|false)$ ]]; then
289 echo "Setting minify... $MINIFY"
290
291 sed -i 's/"_minify"/"minify"/' "$CONFIG_FILE"
292 jq --argjson minify "$MINIFY" \
293 '.domains[""].minify = $minify' \
294 "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
295 #sed -i "s/\"minify\": *[a-z]*/\"minify\": $MINIFY/" "$CONFIG_FILE"
296 else
297 echo "Invalid or no MINIFY value given, commenting out so default applies... Value(s) given: ${MINIFY:-empty}"
298 sed -i 's/"minify":/"_minify":/g' "$CONFIG_FILE"
299 fi
300
301 cat "$CONFIG_FILE"
302 }
303
304 function install_stylishui() {
305 # Start by testing if we can determine compatibility
306 printf "Testing compatibility schema URL..."
307 if ! test_url "$stylishui_compat"; then
308 echo "Compat URL failed."
309 return 1
310 fi
311
312 if [[ ${STYLISHUI_FORCE_LATEST,,} =~ ^(true|yes)$ ]]; then
313 echo "Overriding to main branch..."
314 full_url="${stylishui_base_url}/heads/main.tar.gz"
315 else
316 # Retrieve the values we need to determine compatibility
317 compat_data=$(curl -fsSL "$stylishui_compat")
318 meshcentral_version=$(jq -r '.version' /opt/meshcentral/meshcentral/package.json)
319 # Target the StylishUI version we need for our present Meshcentral version
320 compat_version=$(echo "$compat_data" | jq -r --arg mcv "$meshcentral_version" \
321 '.compatibility[] | select(.meshcentral==$mcv) | .stylishui')
322 echo "Data: MeshCentral: $meshcentral_version, matched StylishUI: $compat_version"
323
324 # From the data gathered above, compile the whole URL.
325 full_url="${stylishui_base_url}/tags/${compat_version}.tar.gz"
326 fi
327
328 # Test if we can reach the data/content URL on github
329 printf "Testing content URL..."
330 if ! test_url "$full_url"; then
331 echo "StylishUI URL failed."
332 return 1
333 fi
334
335 # Lets download and install the UI
336 wget -O /tmp/stylishui.tar.gz "$full_url" > /dev/null
337 tar -xzf /tmp/stylishui.tar.gz -C /tmp
338 web_folder=$(find /tmp -name meshcentral-web)
339
340 # Check if we have some integrity
341 if [[ -z "$web_folder" ]]; then
342 echo "Installation failed, cleaning..."
343 rm /tmp/stylishui*
344 return 1
345 fi
346
347 # Looks good!
348 echo "Found extracted contents at: ${web_folder}"
349 if [[ -d /opt/meshcentral/meshcentral-web/public ]]; then
350 mkdir -p /tmp/web-backup
351 find /opt/meshcentral/meshcentral-web/public -maxdepth 1 -type f -exec mv {} /tmp/web-backup/ \;
352 rm -rf /opt/meshcentral/meshcentral-web/public
353 fi
354
355 echo "Merging!"
356 mv "${web_folder}/"* /opt/meshcentral/meshcentral-web/
357 if [[ -d /tmp/web-backup ]]; then
358 mv /tmp/web-backup/* /opt/meshcentral/meshcentral-web/public/ 2>/dev/null || true
359 rm -rf /tmp/web-backup
360 fi
361 return 0
362 }
363
364 ### Start MeshCentral Docker Container.
365
366 ### BEGIN MAIN CHAIN
367
368 # Make the start more cleared when restarted.
369 echo "-------------------------------------------------------------"
370 date
371 if [ -n "$CONFIG_FILE" ]; then
372 echo "Config file: $CONFIG_FILE"
373 else
374 exit 1
375 fi
376
377 # Failsafe to create a new config if the expected config is not there.
378 if [ -f "${CONFIG_FILE}" ]; then
379 echo "Pre-existing config found, not recreating..."
380 else
381 if [ ! -d "$(dirname "$CONFIG_FILE")" ]; then
382 echo "Creating meshcentral-data directory..."
383 mkdir -p /opt/meshcentral/meshcentral-data
384 fi
385
386 echo "Placing template into the relevant directory: $(dirname "$CONFIG_FILE")"
387 cp /opt/meshcentral/config.json.template "${CONFIG_FILE}"
388 fi
389
390 if [[ ${DYNAMIC_CONFIG,,} =~ ^(true|yes)$ ]]; then
391 echo "-------------------------------------------------------------"
392 echo "Using Dynamic Configuration values..."
393 dynamic_config
394 echo "-------------------------------------------------------------"
395 else
396 echo "Leaving config as-is. Dynamic Configuration is off."
397 fi
398
399 if [[ ${INSTALL_STYLISHUI,,} =~ ^(true|yes)$ ]]; then
400 echo "-------------------------------------------------------------"
401 echo "Reached StylishUI install trigger, installing..."
402 if ! install_stylishui; then
403 echo "Something fatal happened in the StylishUI install. Skipping..."
404 else
405 echo "StylishUI has been installed!"
406 fi
407 echo "-------------------------------------------------------------"
408 fi
409
410 # Actually start MeshCentral.
411 node /opt/meshcentral/meshcentral/meshcentral --configfile "${CONFIG_FILE}" "${ARGS}" >> /proc/1/fd/1 &
412 meshcentral_pid=$!
413
414 wait "$meshcentral_pid"
415
416 ### END MAIN CHAIN