From 660312eff37fc8d7c28f905264c3aa25f08151d9 Mon Sep 17 00:00:00 2001 From: Daan Date: Sat, 22 Mar 2025 03:21:45 +0100 Subject: [PATCH] Working prototype and clear and easy to understand logic. --- docker/Dockerfile | 2 +- docker/README.md | 77 ++++++++++-------- docker/config.json.template | 11 ++- docker/entrypoint.sh | 156 ++++++++++++++++++++++++++---------- 4 files changed, 167 insertions(+), 79 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index b0d8a4d9..db5b3de6 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -93,7 +93,7 @@ WORKDIR /opt/meshcentral RUN apk update \ && apk add --no-cache --update \ - bash gcc g++ jq make nodejs npm postgresql-client python3 tzdata \ + bash gcc g++ jq make nodejs npm python3 tzdata \ && rm -rf /var/cache/* \ /tmp/* \ /usr/share/man/ \ diff --git a/docker/README.md b/docker/README.md index d825e0ff..31cf018e 100644 --- a/docker/README.md +++ b/docker/README.md @@ -18,47 +18,57 @@ You can place the `config.json` file directly under `./meshcentral/data/`, or use the following `.env` file instead. ```ini -NODE_ENV=production +NODE_ENV = "production" +# Leave CONFIG_FILE as per default by using this, or removing it completely from the list. Otherwise if you know what you are doing, you can use this. +CONFIG_FILE = "/opt/meshcentral/meshcentral-data/config.json" +# DYNAMIC_CONFIG enables the config to be rechecked on every restart. If disabled then the container runtime will not change the config.json. +DYNAMIC_CONFIG = "true" -USE_MONGODB=false -# set already exist mongo connection string url here -MONGO_URL= -# or set following init params for new mongodb, use it with docker-compose file with mongodb version -MONGO_INITDB_ROOT_USERNAME=mongodbadmin -MONGO_INITDB_ROOT_PASSWORD=mongodbpasswd +# Environment variables for the MeshCentral Config.json +ALLOWPLUGINS = "false" +ALLOW_NEW_ACCOUNTS = "false" +ALLOWED_ORIGIN = "false" +ARGS = "" +HOSTNAME = "localhost" +IFRAME = "false" +LOCALSESSIONRECORDING = "true" +MINIFY = "true" +REGENSESSIONKEY = "false" +REVERSE_PROXY = "" +REVERSE_PROXY_TLS_PORT = "" +WEBRTC = "false" -# initial meshcentral-variables -# the following options are only used if no config.json exists in the data-folder +# MongoDB Variables +INCLUDE_MONGODB_TOOLS = "false" +USE_MONGODB = "false" +MONGO_HOST = "" +MONGO_PORT = "27017" +MONGO_USERNAME = "" +MONGO_PASS = "" +MONGO_URL = "" -# your hostname -HOSTNAME=my.domain.com -# set to your reverse proxy IP if you want to put meshcentral behind a reverse proxy -REVERSE_PROXY=false -REVERSE_PROXY_TLS_PORT= -# set to true if you wish to enable iframe support -IFRAME=false -# set to false if you want disable self-service creation of new accounts besides the first (admin) -ALLOW_NEW_ACCOUNTS=true -# set to true to enable WebRTC - per documentation it is not officially released with meshcentral and currently experimental. Use with caution -WEBRTC=false -# set to true to allow plugins -ALLOWPLUGINS=false -# set to true to allow session recording -LOCALSESSIONRECORDING=false -# set to enable or disable minification of json, reduces traffic -MINIFY=true -# set this value to add extra arguments to meshcentral on startup (e.g --debug ldap) -ARGS= -# set to the hostname(s) meshcentral will be reachable on, or true to disable origin checking -# forms allowed "hostname" or "hostname1,hostname2" or ["hostname1","hostname2"] -ALLOWED_ORIGIN=false +# PostgreSQL Variables +INCLUDE_POSTGRESQL_TOOLS = "false" +USE_POSTGRESQL = "false" +PSQL_HOST = "" +PSQL_PORT = "5432" +PSQL_USER = "" +PSQL_PASS = "" +PSQL_DATABASE = "" + +# MariaDB/MySQL Variables (Alpine Linux only provides MariaDB binaries) +INCLUDE_MARIADB_TOOLS = "false" +USE_MARIADB = "false" +MARIADB_HOST = "" +MARIADB_PORT = "3306" +MARIADB_USER = "" +MARIADB_PASS = "" +MARIADB_DATABASE = "" ``` ## docker-compose.yml ```yaml -version: '3' - services: meshcentral: restart: always @@ -66,7 +76,6 @@ services: # use the official meshcentral container image: ghcr.io/ylianst/meshcentral:latest ports: - # MeshCentral will moan and try everything not to use port 80, but you can also use it if you so desire, just change the config.json according to your needs - 8086:443 env_file: - .env diff --git a/docker/config.json.template b/docker/config.json.template index 1a1522e4..588d2184 100644 --- a/docker/config.json.template +++ b/docker/config.json.template @@ -1,7 +1,9 @@ { "$schema": "https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json", "settings": { - "plugins":{"enabled": false}, + "plugins":{ + "enabled": false + }, "cert": "myserver.mydomain.com", "_WANonly": true, "_LANonly": true, @@ -22,6 +24,13 @@ "user": "", "password": "", "database": "" + }, + "_mariaDB": { + "host": "", + "port": "", + "user": "", + "password": "", + "database": "" } }, "domains": { diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index dd6d0ba8..dd2bbe7d 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -3,9 +3,11 @@ graceful_shutdown() { echo "Received SIGTERM. Cleaning up..." node /opt/meshcentral/meshcentral/meshcentral --stop + + echo "MeshCentral process stopped. Exiting..." exit 0 } -trap cleanup SIGTERM +trap graceful_shutdown SIGTERM ### Start MeshCentral Docker Container. @@ -20,8 +22,13 @@ else fi if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then + cat $CONFIG_FILE + echo "Using Dynamic Configuration values..." + # BEGIN DATABASE CONFIGURATION FIELDS if [[ "$USE_MONGODB" =~ ^(true|yes)$ ]]; then + echo "Enabling MongoDB-connector..." + if [[ -n "$MONGO_URL" ]]; then echo "MONGO_URL is set, using that..." else @@ -32,20 +39,49 @@ if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then sed -i 's/"_mongoDb"/"mongoDb"/' "$CONFIG_FILE" sed -i "s/\"mongoDb\": *\"[^\"]*\"/\"mongoDb\": \"$ESCAPED_MONGO_URL\"/" "$CONFIG_FILE" else + echo "Disabling MongoDB-connector..." sed -i 's/"mongoDb"/"_mongoDb"/' "$CONFIG_FILE" fi if [[ "$USE_POSTGRESQL" =~ ^(true|yes)$ ]]; then - echo "So you wanna postgres" + echo "Enabling PostgreSQL-connector..." + + sed -i 's/"_postgres"/"postgres"/' "$CONFIG_FILE" + jq --arg psql_host "$PSQL_HOST" \ + --arg psql_port "$PSQL_PORT" \ + --arg psql_user "$PSQL_USER" \ + --arg psql_pass "$PSQL_PASS" \ + --arg psql_db "$PSQL_DATABASE" \ + '.settings.postgres.host = $psql_host | + .settings.postgres.port = $psql_port | + .settings.postgres.user = $psql_user | + .settings.postgres.password = $psql_pass | + .settings.postgres.database = $psql_db' \ + "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE" else - echo "No Postgres" + echo "Disabling PostgreSQL-connector..." + sed -i 's/"postgres"/"_postgres"/' "$CONFIG_FILE" fi if [[ "$USE_MARIADB" =~ ^(true|yes)$ ]]; then - echo "So you wanna MariaDB" + echo "Enabling MariaDB-connector..." + sed -i 's/"_mariaDB"/"mariaDB"/' "$CONFIG_FILE" + jq --arg mariadb_host "$MARIADB_HOST" \ + --arg mariadb_port "$MARIADB_PORT" \ + --arg mariadb_user "$MARIADB_USER" \ + --arg mariadb_pass "$MARIADB_PASS" \ + --arg mariadb_db "$MARIADB_DATABASE" \ + '.settings.mariaDB.host = $mariadb_host | + .settings.mariaDB.port = $mariadb_port | + .settings.mariaDB.user = $mariadb_user | + .settings.mariaDB.password = $mariadb_pass | + .settings.mariaDB.database = $mariadb_db' \ + "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE" else - echo "No MariaDB" + echo "Disabling MariaDB-connector..." + sed -i 's/"mariaDB"/"_mariaDB"/' "$CONFIG_FILE" fi + # END DATABASE CONFIGURATION FIELDS # Doing the bulk with JQ utility. Given the remaining variables an opportunity with Sed. # The way this works is if the environment variable is empty, it will add a _ in front of the variable, commenting it. @@ -60,102 +96,136 @@ if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then SESSION_KEY=$(tr -dc 'A-Z0-9' < /dev/urandom | fold -w 96 | head -n 1) sed -i 's/"_sessionKey"/"sessionKey"/' "$CONFIG_FILE" - sed -i "s/\"sessionKey\": *\"[^\"]*\"/\"sessionKey\": \"$SESSION_KEY\"/" "$CONFIG_FILE" + jq --arg session_key "$SESSION_KEY" \ + '.settings.sessionKey = $session_key' \ + "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE" else echo "REGENSESSIONKEY is not 'true' or 'yes', therefore it's being kept as is." fi # HOSTNAME - if [[ -n $HOSTNAME ]] && [[ $HOSTNAME =~ ^([a-zA-Z0-9-]+\.)+[a-zA-Z0-9-]+$ ]]; then - echo "Setting hostname (cert)... - $HOSTNAME" - sed -i 's/"_cert"/"cert"/' "$CONFIG_FILE" - sed -i "s/\"cert\": *\"[^\"]*\"/\"cert\": \"$HOSTNAME\"/" "$CONFIG_FILE" + if [[ -n $HOSTNAME ]] && [[ $HOSTNAME =~ ^[a-zA-Z0-9-]+$ ]]; then + echo "Setting hostname (cert)... $HOSTNAME" + + jq --arg hostname "$HOSTNAME" \ + '.settings.cert = $hostname' \ + "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE" else - echo "Invalid hostname, commenting it out..." - sed -i "s/\"cert\": *\"[^\"]*\"/\"cert\": \"localhost\"/" "$CONFIG_FILE" + echo "Invalid or no hostname, defaulting to 'localhost', value given: $HOSTNAME" + jq --arg hostname "localhost" \ + '.settings.cert = $hostname' \ + "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE" fi # ALLOW_NEW_ACCOUNTS if [[ -n $ALLOW_NEW_ACCOUNTS ]] && [[ $ALLOW_NEW_ACCOUNTS =~ ^(true|false)$ ]]; then - echo "Setting NewAccounts... - $ALLOW_NEW_ACCOUNTS" + echo "Setting NewAccounts... $ALLOW_NEW_ACCOUNTS" + sed -i 's/"_NewAccounts"/"NewAccounts"/' "$CONFIG_FILE" - sed -i "s/\"NewAccounts\": *[a-z]*/\"NewAccounts\": $ALLOW_NEW_ACCOUNTS/" "$CONFIG_FILE" + jq --argjson new_accounts "$ALLOW_NEW_ACCOUNTS" \ + '.domains[""].NewAccounts = $new_accounts' \ + "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE" else - echo "Invalid ALLOW_NEW_ACCOUNTS value given, commenting out so default applies..." + echo "Invalid or no ALLOW_NEW_ACCOUNTS value given, commenting out so default applies... Value given: $ALLOW_NEW_ACCOUNTS" sed -i 's/"NewAccounts":/"_NewAccounts":/g' "$CONFIG_FILE" fi # ALLOWPLUGINS if [[ -n $ALLOWPLUGINS ]] && [[ $ALLOWPLUGINS =~ ^(true|false)$ ]]; then - echo "Setting plugins... - $ALLOWPLUGINS" + echo "Setting plugins... $ALLOWPLUGINS" + sed -i 's/"_plugins"/"plugins"/' "$CONFIG_FILE" - sed -i "s/\"plugins\": *{[^}]*}/\"plugins\": {\"enabled\": $ALLOWPLUGINS}/" "$CONFIG_FILE" + jq --argjson allow_plugins "$ALLOWPLUGINS" \ + '.settings.plugins.enabled = $allow_plugins' \ + "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE" else - echo "Invalid ALLOWPLUGINS value given, commenting out so default applies..." + echo "Invalid or no ALLOWPLUGINS value given, commenting out so default applies... Value given: $ALLOWPLUGINS" sed -i 's/"plugins":/"_plugins":/g' "$CONFIG_FILE" fi # LOCALSESSIONRECORDING if [[ -n $LOCALSESSIONRECORDING ]] && [[ $LOCALSESSIONRECORDING =~ ^(true|false)$ ]]; then - echo "Setting localSessionRecording... - $LOCALSESSIONRECORDING" + echo "Setting localSessionRecording... $LOCALSESSIONRECORDING" + sed -i 's/"_localSessionRecording"/"localSessionRecording"/' "$CONFIG_FILE" - sed -i "s/\"localSessionRecording\": *[a-z]*/\"localSessionRecording\": $LOCALSESSIONRECORDING/" "$CONFIG_FILE" + jq --argjson session_recording "$LOCALSESSIONRECORDING" \ + '.domains[""].localSessionRecording = $session_recording' \ + "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE" else - echo "Invalid LOCALSESSIONRECORDING value given, commenting out so default applies..." + echo "Invalid or no LOCALSESSIONRECORDING value given, commenting out so default applies... Value given: $LOCALSESSIONRECORDING" sed -i 's/"localSessionRecording":/"_localSessionRecording":/g' "$CONFIG_FILE" fi # MINIFY if [[ -n $MINIFY ]] && [[ $MINIFY =~ ^(true|false)$ ]]; then - echo "Setting minify... - $MINIFY" + echo "Setting minify... $MINIFY" + sed -i 's/"_minify"/"minify"/' "$CONFIG_FILE" - sed -i "s/\"minify\": *[a-z]*/\"minify\": $MINIFY/" "$CONFIG_FILE" + jq --arg minify "$MINIFY" \ + '.domains[""].minify = $minify' \ + "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE" + #sed -i "s/\"minify\": *[a-z]*/\"minify\": $MINIFY/" "$CONFIG_FILE" else - echo "Invalid MINIFY value given, commenting out so default applies..." + echo "Invalid or no MINIFY value given, commenting out so default applies... Value given: $MINIFY" sed -i 's/"minify":/"_minify":/g' "$CONFIG_FILE" fi # WEBRTC if [[ -n $WEBRTC ]] && [[ $WEBRTC =~ ^(true|false)$ ]]; then - echo "Setting WebRTC... - $WEBRTC" + echo "Setting WebRTC... $WEBRTC" + sed -i 's/"_WebRTC"/"WebRTC"/' "$CONFIG_FILE" - sed -i "s/\"WebRTC\": *[a-z]*/\"WebRTC\": $WEBRTC/" "$CONFIG_FILE" + jq --argjson webrtc "$WEBRTC" \ + '.settings.WebRTC = $webrtc' \ + "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE" + #sed -i "s/\"WebRTC\": *[a-z]*/\"WebRTC\": $WEBRTC/" "$CONFIG_FILE" else - echo "Invalid WEBRTC value given, commenting out so default applies..." + echo "Invalid or no WEBRTC value given, commenting out so default applies... Value given: $WEBRTC" sed -i 's/"WebRTC":/"_WebRTC":/g' "$CONFIG_FILE" fi # IFRAME if [[ -n $IFRAME ]] && [[ $IFRAME =~ ^(true|false)$ ]]; then - echo "Setting AllowFraming... - $IFRAME" + echo "Setting AllowFraming... $IFRAME" + sed -i 's/"_AllowFraming"/"AllowFraming"/' "$CONFIG_FILE" - sed -i "s/\"AllowFraming\": *[a-z]*/\"AllowFraming\": $IFRAME/" "$CONFIG_FILE" + jq --argjson allow_framing "$IFRAME" \ + '.settings.AllowFraming = $allow_framing' \ + "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE" else - echo "Invalid IFRAME value given, commenting out so default applies..." + echo "Invalid or no IFRAME value given, commenting out so default applies... Value given: $IFRAME" sed -i 's/"AllowFraming":/"_AllowFraming":/g' "$CONFIG_FILE" fi # ALLOWED_ORIGIN if [[ -n $ALLOWED_ORIGIN ]] && [[ $ALLOWED_ORIGIN =~ ^(true|false)$ ]]; then - echo "Setting allowedOrigin... - $ALLOWED_ORIGIN" + echo "Setting allowedOrigin... $ALLOWED_ORIGIN" + sed -i 's/"_allowedOrigin"/"allowedOrigin"/' "$CONFIG_FILE" - sed -i "s/\"allowedOrigin\": *[a-z]*/\"allowedOrigin\": $ALLOWED_ORIGIN/" "$CONFIG_FILE" + jq --arg allowed_origin "$ALLOWED_ORIGIN" \ + '.domains[""].allowedOrigin = $allowed_origin' \ + "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE" else - echo "Invalid ALLOWED_ORIGIN value given, commenting out so default applies..." + echo "Invalid or no ALLOWED_ORIGIN value given, commenting out so default applies... Value given: $ALLOWED_ORIGIN" sed -i 's/"allowedOrigin":/"_allowedOrigin":/g' "$CONFIG_FILE" fi + # certUrl + if [[ -n $REVERSE_PROXY ]] && [[ -n $REVERSE_PROXY_TLS_PORT ]]; then + REVERSE_PROXY_STRING="${REVERSE_PROXY}:${REVERSE_PROXY_TLS_PORT}" + + echo "Setting certUrl... - $REVERSE_PROXY_STRING" + sed -i 's/"_certUrl"/"certUrl"/' "$CONFIG_FILE" + jq --arg cert_url "$REVERSE_PROXY_STRING" \ + '.domains[""].certUrl = $cert_url' \ + "$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE" + #sed -i "s/\"certUrl\": *[a-z]*/\"certUrl\": $REVERSE_PROXY_STRING/" "$CONFIG_FILE" + else + 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" + sed -i 's/"certUrl":/"_certUrl":/g' "$CONFIG_FILE" + fi + echo -e "\n$(cat "$CONFIG_FILE")" - - # TO DO CERTURL - POSTGRESQL - MONGO_INITDB_ROOT_PASSWORD="pass" - - #if [[ "$ALLOWED_ORIGIN" =~ ^\[.*\]|^true|^false ]]; then - # sed -i "s/\"allowedOrigin\": false/\"allowedOrigin\": $ALLOWED_ORIGIN/" meshcentral-data/"${CONFIG_FILE}" - #else - # sed -i "s/\"allowedOrigin\": false/\"allowedOrigin\": \"$ALLOWED_ORIGIN\"/" meshcentral-data/"${CONFIG_FILE}" - #fi - #SESSION_KEY= # Session key should be random. Not passed in through arguments. - #sed -i "s/\"_sessionKey\": \"MyReallySecretPassword1\"/\"sessionKey\": \"$SESSION_KEY\"/" meshcentral-data/"${CONFIG_FILE}" else echo "Leaving config as-is." fi