From da5ef522f8c64bd500eba8de9df4a7dd9fb90147 Mon Sep 17 00:00:00 2001 From: Daan Selen Date: Wed, 19 Mar 2025 15:32:28 +0100 Subject: [PATCH 1/9] Modified Dockerfile for readability Renamed startup.sh to entrypoint.sh --- docker/Dockerfile | 53 +++++++++++++++++----------- docker/{startup.sh => entrypoint.sh} | 0 2 files changed, 33 insertions(+), 20 deletions(-) rename docker/{startup.sh => entrypoint.sh} (100%) diff --git a/docker/Dockerfile b/docker/Dockerfile index 20dee2ea..8bd3cde7 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,49 +1,55 @@ -FROM --platform=$BUILDPLATFORM node:22-alpine AS builder +### STAGE 1 BUILDING. +FROM node:current-alpine AS builder RUN mkdir -p /opt/meshcentral/meshcentral COPY ./ /opt/meshcentral/meshcentral/ WORKDIR /opt/meshcentral ARG DISABLE_MINIFY="" -ARG DISABLE_TRANSLATE="" - +ARG DISABLE_TRANSLATE="yes" RUN if ! [ -z "$DISABLE_MINIFY" ] && [ "$DISABLE_MINIFY" != "yes" ] && [ "$DISABLE_MINIFY" != "YES" ] \ && [ "$DISABLE_MINIFY" != "true" ] && [ "$DISABLE_MINIFY" != "TRUE" ]; then \ - echo -e "\e[0;31;49mInvalid value for build argument DISABLE_MINIFY, possible values: yes/true\e[;0m"; exit 1; \ + echo -e "\e[0;31;49mInvalid value for build argument DISABLE_MINIFY, possible values: yes/true\e[;0m"; exit 1; \ fi RUN if ! [ -z "$DISABLE_TRANSLATE" ] && [ "$DISABLE_TRANSLATE" != "yes" ] && [ "$DISABLE_TRANSLATE" != "YES" ] \ && [ "$DISABLE_TRANSLATE" != "true" ] && [ "$DISABLE_TRANSLATE" != "TRUE" ]; then \ - echo -e "\e[0;31;49mInvalid value for build argument DISABLE_TRANSLATE, possible values: yes/true\e[;0m"; exit 1; \ + echo -e "\e[0;31;49mInvalid value for build argument DISABLE_TRANSLATE, possible values: yes/true\e[;0m"; exit 1; \ fi # install translate/minify modules if need too -RUN if [ -z "$DISABLE_MINIFY" ] || [ -z "$DISABLE_TRANSLATE" ]; then cd meshcentral && npm install html-minifier@4.0.0 jsdom@22.1.0 esprima@4.0.1; fi - -# first extractall if need too -RUN if [ -z "$DISABLE_MINIFY" ] || [ -z "$DISABLE_TRANSLATE" ]; then cd meshcentral/translate && node translate.js extractall; fi +RUN if [ -z "$DISABLE_MINIFY" ] || [ -z "$DISABLE_TRANSLATE" ]; then \ + cd meshcentral && npm install html-minifier@4.0.0 jsdom@26.0.0 esprima@4.0.1; \ + cd translate && node translate.js extractall; \ + fi +# @minify-html/node@0.15.0 # minify files -RUN if [ -z "$DISABLE_MINIFY" ]; then cd meshcentral/translate && node translate.js minifyall; fi +RUN if [ -z "$DISABLE_MINIFY" ]; then \ + cd meshcentral/translate && node translate.js minifyall; \ + fi # translate -RUN if [ -z "$DISABLE_TRANSLATE" ]; then cd meshcentral/translate && node translate.js translateall; fi +RUN if [ -z "$DISABLE_TRANSLATE" ]; then \ + cd meshcentral/translate && node translate.js translateall; \ + fi # cleanup RUN rm -rf /opt/meshcentral/meshcentral/docker RUN rm -rf /opt/meshcentral/meshcentral/node_modules +### STAGE 2 BUILDING. -FROM --platform=$TARGETPLATFORM alpine:3.21 +FROM alpine:latest -#Add non-root user, add installation directories and assign proper permissions RUN mkdir -p /opt/meshcentral/meshcentral # meshcentral installation WORKDIR /opt/meshcentral RUN apk update \ - && apk add --no-cache --update tzdata nodejs npm bash python3 make gcc g++ \ + && apk add --no-cache --update \ + tzdata nodejs npm bash python3 postgresql-client make gcc g++ \ && rm -rf /var/cache/apk/* RUN npm install -g npm@latest @@ -74,22 +80,29 @@ ENV ALLOWED_ORIGIN="false" RUN if ! [ -z "$INCLUDE_MONGODBTOOLS" ] && [ "$INCLUDE_MONGODBTOOLS" != "yes" ] && [ "$INCLUDE_MONGODBTOOLS" != "YES" ] \ && [ "$INCLUDE_MONGODBTOOLS" != "true" ] && [ "$INCLUDE_MONGODBTOOLS" != "TRUE" ]; then \ - echo -e "\e[0;31;49mInvalid value for build argument INCLUDE_MONGODBTOOLS, possible values: yes/true\e[;0m"; exit 1; \ + echo -e "\e[0;31;49mInvalid value for build argument INCLUDE_MONGODBTOOLS, possible values: yes/true\e[;0m"; exit 1; \ fi -RUN if ! [ -z "$INCLUDE_MONGODBTOOLS" ]; then apk add --no-cache mongodb-tools; fi +RUN if ! [ -z "$INCLUDE_MONGODBTOOLS" ]; then \ + apk add --no-cache mongodb-tools; \ + fi # copy files from builder-image COPY --from=builder /opt/meshcentral/meshcentral /opt/meshcentral/meshcentral -COPY ./docker/startup.sh ./startup.sh +COPY ./docker/entrypoint.sh ./entrypoint.sh COPY ./docker/config.json.template /opt/meshcentral/config.json.template # install dependencies from package.json RUN cd meshcentral && npm install # NOTE: ALL MODULES MUST HAVE A VERSION NUMBER AND THE VERSION MUST MATCH THAT USED IN meshcentral.js mainStart() -RUN if ! [ -z "$INCLUDE_MONGODBTOOLS" ]; then cd meshcentral && npm install mongodb@4.13.0 saslprep@1.0.3; fi -RUN if ! [ -z "$PREINSTALL_LIBS" ] && [ "$PREINSTALL_LIBS" == "true" ]; then cd meshcentral && npm install ssh2@1.16.0 semver@7.5.4 nodemailer@6.9.15 image-size@1.1.1 wildleek@2.0.0 otplib@10.2.3 yubikeyotp@0.2.0; fi +RUN if ! [ -z "$INCLUDE_MONGODBTOOLS" ]; then \ + cd meshcentral && npm install mongodb@6.15.0 saslprep@1.0.3; \ + fi + +RUN if ! [ -z "$PREINSTALL_LIBS" ] && [ "$PREINSTALL_LIBS" == "true" ]; then \ + cd meshcentral && npm install ssh2@1.16.0 semver@7.7.1 nodemailer@6.10.0 image-size@2.0.1 wildleek@2.0.0 otplib@12.0.1 yubikeyotp@0.2.0; \ + fi EXPOSE 80 443 4433 @@ -99,4 +112,4 @@ VOLUME /opt/meshcentral/meshcentral-files VOLUME /opt/meshcentral/meshcentral-web VOLUME /opt/meshcentral/meshcentral-backups -CMD ["bash", "/opt/meshcentral/startup.sh"] +CMD ["bash", "/opt/meshcentral/entrypoint.sh"] diff --git a/docker/startup.sh b/docker/entrypoint.sh similarity index 100% rename from docker/startup.sh rename to docker/entrypoint.sh From ddeeb8cd58a9d13eaeb94cd4dc8f3faf8a369558 Mon Sep 17 00:00:00 2001 From: Daan Selen Date: Wed, 19 Mar 2025 15:38:22 +0100 Subject: [PATCH 2/9] Renamed the workflow for better recognition and upgraded docker/build-push-action action to version 6 --- .github/workflows/docker.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index e4bafe94..7ca7d314 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,4 +1,4 @@ -name: Docker +name: Docker-Builder on: push: branches: @@ -22,7 +22,7 @@ jobs: MY_TOKEN: ${{ secrets.MY_TOKEN }} if: "${{ env.MY_TOKEN != '' }}" run: echo "token_defined=true" >> "$GITHUB_OUTPUT" - + build: name: Release runs-on: ubuntu-latest @@ -54,7 +54,7 @@ jobs: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - name: Build and push Docker image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . file: docker/Dockerfile From 6eb85fa892dcdfbe41567d4aa360f1ef2f4f3801 Mon Sep 17 00:00:00 2001 From: Daan Selen Date: Thu, 20 Mar 2025 17:07:08 +0100 Subject: [PATCH 3/9] Refactored more Dockerfile --- docker/Dockerfile | 93 ++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 45 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 8bd3cde7..17c74a19 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,40 +1,47 @@ ### STAGE 1 BUILDING. -FROM node:current-alpine AS builder - -RUN mkdir -p /opt/meshcentral/meshcentral -COPY ./ /opt/meshcentral/meshcentral/ -WORKDIR /opt/meshcentral +FROM node:lts-alpine AS builder ARG DISABLE_MINIFY="" ARG DISABLE_TRANSLATE="yes" -RUN if ! [ -z "$DISABLE_MINIFY" ] && [ "$DISABLE_MINIFY" != "yes" ] && [ "$DISABLE_MINIFY" != "YES" ] \ +RUN mkdir -p /opt/meshcentral/meshcentral +COPY ./ /opt/meshcentral/meshcentral/ + +# Check if minify should be disabled on compilation. +RUN if ! [ -z "$DISABLE_MINIFY" ] \ + && [ "$DISABLE_MINIFY" != "yes" ] && [ "$DISABLE_MINIFY" != "YES" ] \ && [ "$DISABLE_MINIFY" != "true" ] && [ "$DISABLE_MINIFY" != "TRUE" ]; then \ - echo -e "\e[0;31;49mInvalid value for build argument DISABLE_MINIFY, possible values: yes/true\e[;0m"; exit 1; \ + echo "Invalid value for build argument DISABLE_MINIFY, possible values: 'yes' or 'true'"; \ + exit 1; \ fi -RUN if ! [ -z "$DISABLE_TRANSLATE" ] && [ "$DISABLE_TRANSLATE" != "yes" ] && [ "$DISABLE_TRANSLATE" != "YES" ] \ +# Check if translations should be compiled. +RUN if ! [ -z "$DISABLE_TRANSLATE" ] \ + && [ "$DISABLE_TRANSLATE" != "yes" ] && [ "$DISABLE_TRANSLATE" != "YES" ] \ && [ "$DISABLE_TRANSLATE" != "true" ] && [ "$DISABLE_TRANSLATE" != "TRUE" ]; then \ - echo -e "\e[0;31;49mInvalid value for build argument DISABLE_TRANSLATE, possible values: yes/true\e[;0m"; exit 1; \ + echo "Invalid value for build argument DISABLE_TRANSLATE, possible values: 'yes' or 'true'"; \ + exit 1; \ fi -# install translate/minify modules if need too +# Check the Docker build arguments and execute them accordingly. RUN if [ -z "$DISABLE_MINIFY" ] || [ -z "$DISABLE_TRANSLATE" ]; then \ - cd meshcentral && npm install html-minifier@4.0.0 jsdom@26.0.0 esprima@4.0.1; \ - cd translate && node translate.js extractall; \ - fi -# @minify-html/node@0.15.0 - -# minify files -RUN if [ -z "$DISABLE_MINIFY" ]; then \ - cd meshcentral/translate && node translate.js minifyall; \ - fi - -# translate -RUN if [ -z "$DISABLE_TRANSLATE" ]; then \ - cd meshcentral/translate && node translate.js translateall; \ + cd meshcentral && \ + npm install html-minifier@4.0.0 jsdom@26.0.0 esprima@4.0.1 && \ +\ + cd translate && \ + node translate.js extractall && \ +\ + if [ -z "$DISABLE_MINIFY" ]; then \ + node translate.js minifyall; \ + fi; \ +\ + if [ -z "$DISABLE_TRANSLATE" ]; then \ + node translate.js translateall; \ + fi \ fi +# Possible more updated alternative? @minify-html/node@0.15.0 -> https://www.npmjs.com/package/@minify-html/node # cleanup +RUN ls -l /opt/meshcentral/meshcentral RUN rm -rf /opt/meshcentral/meshcentral/docker RUN rm -rf /opt/meshcentral/meshcentral/node_modules @@ -42,17 +49,6 @@ RUN rm -rf /opt/meshcentral/meshcentral/node_modules FROM alpine:latest -RUN mkdir -p /opt/meshcentral/meshcentral - -# meshcentral installation -WORKDIR /opt/meshcentral - -RUN apk update \ - && apk add --no-cache --update \ - tzdata nodejs npm bash python3 postgresql-client make gcc g++ \ - && rm -rf /var/cache/apk/* -RUN npm install -g npm@latest - ARG INCLUDE_MONGODBTOOLS="" ARG PREINSTALL_LIBS="false" @@ -72,19 +68,29 @@ ENV LOCALSESSIONRECORDING="true" ENV MINIFY="false" ENV WEBRTC="false" ENV IFRAME="false" -ENV SESSION_KEY="" ENV REVERSE_PROXY="false" ENV REVERSE_PROXY_TLS_PORT="" ENV ARGS="" ENV ALLOWED_ORIGIN="false" -RUN if ! [ -z "$INCLUDE_MONGODBTOOLS" ] && [ "$INCLUDE_MONGODBTOOLS" != "yes" ] && [ "$INCLUDE_MONGODBTOOLS" != "YES" ] \ +RUN mkdir -p /opt/meshcentral/meshcentral + +# meshcentral installation +WORKDIR /opt/meshcentral + +RUN apk update \ + && apk add --no-cache --update tzdata nodejs npm bash python3 postgresql-client make gcc g++ \ + && rm -rf /var/cache/apk/* +RUN npm install -g npm@latest + +# NOTE: ALL MODULES MUST HAVE A VERSION NUMBER AND THE VERSION MUST MATCH THAT USED IN meshcentral.js mainStart() +RUN if ! [ -z "$INCLUDE_MONGODBTOOLS" ] \ + && [ "$INCLUDE_MONGODBTOOLS" != "yes" ] && [ "$INCLUDE_MONGODBTOOLS" != "YES" ] \ && [ "$INCLUDE_MONGODBTOOLS" != "true" ] && [ "$INCLUDE_MONGODBTOOLS" != "TRUE" ]; then \ echo -e "\e[0;31;49mInvalid value for build argument INCLUDE_MONGODBTOOLS, possible values: yes/true\e[;0m"; exit 1; \ - fi - -RUN if ! [ -z "$INCLUDE_MONGODBTOOLS" ]; then \ + else \ apk add --no-cache mongodb-tools; \ + cd meshcentral && npm install mongodb@6.15.0 saslprep@1.0.3; \ fi # copy files from builder-image @@ -95,12 +101,8 @@ COPY ./docker/config.json.template /opt/meshcentral/config.json.template # install dependencies from package.json RUN cd meshcentral && npm install -# NOTE: ALL MODULES MUST HAVE A VERSION NUMBER AND THE VERSION MUST MATCH THAT USED IN meshcentral.js mainStart() -RUN if ! [ -z "$INCLUDE_MONGODBTOOLS" ]; then \ - cd meshcentral && npm install mongodb@6.15.0 saslprep@1.0.3; \ - fi - -RUN if ! [ -z "$PREINSTALL_LIBS" ] && [ "$PREINSTALL_LIBS" == "true" ]; then \ +RUN if ! [ -z "$PREINSTALL_LIBS" ] \ + && [ "$PREINSTALL_LIBS" == "true" ]; then \ cd meshcentral && npm install ssh2@1.16.0 semver@7.7.1 nodemailer@6.10.0 image-size@2.0.1 wildleek@2.0.0 otplib@12.0.1 yubikeyotp@0.2.0; \ fi @@ -112,4 +114,5 @@ VOLUME /opt/meshcentral/meshcentral-files VOLUME /opt/meshcentral/meshcentral-web VOLUME /opt/meshcentral/meshcentral-backups +WORKDIR /opt/meshcentral CMD ["bash", "/opt/meshcentral/entrypoint.sh"] From 86ecc4267dd559146ec0a987680df607c66b5080 Mon Sep 17 00:00:00 2001 From: Daan Selen Date: Fri, 21 Mar 2025 16:32:35 +0100 Subject: [PATCH 4/9] @DaanSelen Docker overhaul intermediate commit. --- docker/Dockerfile | 169 ++++++++++++++++++--------- docker/{readme.md => README.md} | 2 + docker/config.json.template | 11 +- docker/entrypoint.sh | 181 +++++++++++++++++++++++------ docker/{ => tools}/docker.build.sh | 0 5 files changed, 269 insertions(+), 94 deletions(-) rename docker/{readme.md => README.md} (98%) rename docker/{ => tools}/docker.build.sh (100%) diff --git a/docker/Dockerfile b/docker/Dockerfile index 17c74a19..91cc9697 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,28 +1,15 @@ ### STAGE 1 BUILDING. FROM node:lts-alpine AS builder +# Any value inside one of the disable ARGs will be accepted. ARG DISABLE_MINIFY="" ARG DISABLE_TRANSLATE="yes" RUN mkdir -p /opt/meshcentral/meshcentral +WORKDIR /opt/meshcentral COPY ./ /opt/meshcentral/meshcentral/ -# Check if minify should be disabled on compilation. -RUN if ! [ -z "$DISABLE_MINIFY" ] \ - && [ "$DISABLE_MINIFY" != "yes" ] && [ "$DISABLE_MINIFY" != "YES" ] \ - && [ "$DISABLE_MINIFY" != "true" ] && [ "$DISABLE_MINIFY" != "TRUE" ]; then \ - echo "Invalid value for build argument DISABLE_MINIFY, possible values: 'yes' or 'true'"; \ - exit 1; \ - fi -# Check if translations should be compiled. -RUN if ! [ -z "$DISABLE_TRANSLATE" ] \ - && [ "$DISABLE_TRANSLATE" != "yes" ] && [ "$DISABLE_TRANSLATE" != "YES" ] \ - && [ "$DISABLE_TRANSLATE" != "true" ] && [ "$DISABLE_TRANSLATE" != "TRUE" ]; then \ - echo "Invalid value for build argument DISABLE_TRANSLATE, possible values: 'yes' or 'true'"; \ - exit 1; \ - fi - -# Check the Docker build arguments and execute them accordingly. +# Check the Docker build arguments and if they are empty do the task. RUN if [ -z "$DISABLE_MINIFY" ] || [ -z "$DISABLE_TRANSLATE" ]; then \ cd meshcentral && \ npm install html-minifier@4.0.0 jsdom@26.0.0 esprima@4.0.1 && \ @@ -40,8 +27,7 @@ RUN if [ -z "$DISABLE_MINIFY" ] || [ -z "$DISABLE_TRANSLATE" ]; then \ fi # Possible more updated alternative? @minify-html/node@0.15.0 -> https://www.npmjs.com/package/@minify-html/node -# cleanup -RUN ls -l /opt/meshcentral/meshcentral +# cleanup for inter-container copying. RUN rm -rf /opt/meshcentral/meshcentral/docker RUN rm -rf /opt/meshcentral/meshcentral/node_modules @@ -49,70 +35,139 @@ RUN rm -rf /opt/meshcentral/meshcentral/node_modules FROM alpine:latest -ARG INCLUDE_MONGODBTOOLS="" ARG PREINSTALL_LIBS="false" # environment variables ENV NODE_ENV="production" -ENV CONFIG_FILE="config.json" +ENV CONFIG_FILE="/opt/meshcentral/meshcentral-data/config.json" +ENV DYNAMIC_CONFIG="true" -# environment variables for initial configuration file -ENV USE_MONGODB="false" -ENV MONGO_INITDB_ROOT_USERNAME="root" -ENV MONGO_INITDB_ROOT_PASSWORD="pass" -ENV MONGO_URL="" -ENV HOSTNAME="localhost" -ENV ALLOW_NEW_ACCOUNTS="true" +# environment variables for the above defined MeshCentral Config.json ENV ALLOWPLUGINS="false" -ENV LOCALSESSIONRECORDING="true" -ENV MINIFY="false" -ENV WEBRTC="false" -ENV IFRAME="false" -ENV REVERSE_PROXY="false" -ENV REVERSE_PROXY_TLS_PORT="" -ENV ARGS="" +ENV ALLOW_NEW_ACCOUNTS="false" ENV ALLOWED_ORIGIN="false" +ENV ARGS="" +ENV HOSTNAME="localhost" +ENV IFRAME="false" +ENV LOCALSESSIONRECORDING="true" +ENV MINIFY="true" +ENV REGENSESSIONKEY="false" +ENV REVERSE_PROXY="" +ENV REVERSE_PROXY_TLS_PORT="" +ENV WEBRTC="false" + + +# MongoDB Variables +ARG INCLUDE_MONGODB_TOOLS="false" + +ENV USE_MONGODB="false" +ENV MONGO_HOST="" +ENV MONGO_PORT="27017" +ENV MONGO_USERNAME="" +ENV MONGO_PASS="" +# The following Mongo variable overwrites most previously declared variables. +ENV MONGO_URL="" + +# PostgreSQL Variables +ARG INCLUDE_POSTGRESQL_TOOLS="false" + +ENV USE_POSTGRESQL="false" +ENV PSQL_HOST="" +ENV PSQL_PORT="5432" +ENV PSQL_USER="" +ENV PSQL_PASS="" +ENV PSQL_DATABASE="" + +# MariaDB/MySQL Variables, Alpine Linux only provides the actual MariaDB binaries. +ARG INCLUDE_MARIADB_TOOLS="false" + +ENV USE_MARIADB="false" +ENV MARIADB_HOST="" +ENV MARIADB_PORT="3306" +ENV MARIADB_USER="" +ENV MARIADB_PASS="" +ENV MARIADB_DATABASE="" RUN mkdir -p /opt/meshcentral/meshcentral - -# meshcentral installation WORKDIR /opt/meshcentral RUN apk update \ - && apk add --no-cache --update tzdata nodejs npm bash python3 postgresql-client make gcc g++ \ - && rm -rf /var/cache/apk/* + && apk add --no-cache --update \ + bash gcc g++ jq make nodejs npm postgresql-client python3 tzdata \ + && rm -rf /var/cache/* \ + /tmp/* \ + /usr/share/man/ \ + /usr/share/doc/ \ + /var/log/* \ + /var/spool/* \ + /usr/lib/debug/ RUN npm install -g npm@latest -# NOTE: ALL MODULES MUST HAVE A VERSION NUMBER AND THE VERSION MUST MATCH THAT USED IN meshcentral.js mainStart() -RUN if ! [ -z "$INCLUDE_MONGODBTOOLS" ] \ - && [ "$INCLUDE_MONGODBTOOLS" != "yes" ] && [ "$INCLUDE_MONGODBTOOLS" != "YES" ] \ - && [ "$INCLUDE_MONGODBTOOLS" != "true" ] && [ "$INCLUDE_MONGODBTOOLS" != "TRUE" ]; then \ - echo -e "\e[0;31;49mInvalid value for build argument INCLUDE_MONGODBTOOLS, possible values: yes/true\e[;0m"; exit 1; \ - else \ - apk add --no-cache mongodb-tools; \ - cd meshcentral && npm install mongodb@6.15.0 saslprep@1.0.3; \ - fi +# NOTE: ALL MODULES MUST HAVE A VERSION NUMBER AND THE VERSION MUST MATCH THAT USED IN meshcentraljs mainStart() +RUN case "$INCLUDE_MONGODB_TOOLS" in \ + true|yes|TRUE|YES) \ + apk add --no-cache mongodb-tools && \ + cd meshcentral && npm install mongodb@6.15.0 saslprep@1.0.3 \ + ;; \ + false|no|FALSE|NO) \ + echo "Not including MongoDB Tools.";; \ + *) \ + echo "Invalid value for build argument INCLUDE_MONGODB_TOOLS, possible values: 'yes' or 'true'"; \ + exit 1;; \ + esac + +RUN case "$INCLUDE_POSTGRESQL_TOOLS" in \ + true|yes|TRUE|YES) \ + apk add --no-cache postgresql-client && \ + cd meshcentral && npm install pg@8.14.1 \ + ;; \ + false|no|FALSE|NO) \ + echo "Not including PostgreSQL Tools.";; \ + *) \ + echo -e "Invalid value for build argument INCLUDE_POSTGRESQL_TOOLS, possible values: 'yes' or 'true'"; \ + exit 1;; \ + esac + +RUN case "$INCLUDE_MARIADB_TOOLS" in \ + true|yes|TRUE|YES) \ + apk add --no-cache mariadb-client && \ + cd meshcentral && npm install mariadb@3.4.0 \ + ;; \ + false|no|FALSE|NO) \ + echo "Not including MariaDB/MySQL Tools.";; \ + *) \ + echo -e "Invalid value for build argument INCLUDE_MARIADB_TOOLS, possible values: 'yes' or 'true'"; \ + exit 1;; \ + esac # copy files from builder-image COPY --from=builder /opt/meshcentral/meshcentral /opt/meshcentral/meshcentral -COPY ./docker/entrypoint.sh ./entrypoint.sh -COPY ./docker/config.json.template /opt/meshcentral/config.json.template # install dependencies from package.json RUN cd meshcentral && npm install -RUN if ! [ -z "$PREINSTALL_LIBS" ] \ - && [ "$PREINSTALL_LIBS" == "true" ]; then \ - cd meshcentral && npm install ssh2@1.16.0 semver@7.7.1 nodemailer@6.10.0 image-size@2.0.1 wildleek@2.0.0 otplib@12.0.1 yubikeyotp@0.2.0; \ - fi +RUN case "$PREINSTALL_LIBS" in \ + true|yes|TRUE|YES) \ + cd meshcentral && \ + npm install ssh2@1.16.0 semver@7.7.1 nodemailer@6.10.0 image-size@2.0.1 wildleek@2.0.0 otplib@12.0.1 yubikeyotp@0.2.0;; \ + false|no|FALSE|NO) \ + echo "Not pre-installing libraries.";; \ + *) \ + echo -e "Invalid value for build argument INCLUDE_POSTGRESQL_TOOLS, possible values: 'yes' or 'true'"; \ + exit 1;; \ + esac -EXPOSE 80 443 4433 +# Expose only 443 by default to reduce attack surface. (Only encrypted ports). +EXPOSE 443 -# volumes +# These volumes will be created by default even without any declaration, this allows default persistence in Docker/Podman. VOLUME /opt/meshcentral/meshcentral-data VOLUME /opt/meshcentral/meshcentral-files VOLUME /opt/meshcentral/meshcentral-web VOLUME /opt/meshcentral/meshcentral-backups -WORKDIR /opt/meshcentral -CMD ["bash", "/opt/meshcentral/entrypoint.sh"] +# Copy images from Git repo, place it before ending so recompilation can make good use of cache. +COPY ./docker/entrypoint.sh ./entrypoint.sh +COPY ./docker/config.json.template /opt/meshcentral/config.json.template + +CMD ["bash", "/opt/meshcentral/entrypoint.sh"] \ No newline at end of file diff --git a/docker/readme.md b/docker/README.md similarity index 98% rename from docker/readme.md rename to docker/README.md index fa17e6a5..d825e0ff 100644 --- a/docker/readme.md +++ b/docker/README.md @@ -1,5 +1,7 @@ # Create folder-structure and files +# TO BE REWRITTEN - In progress, for questions: dselen@nerthus.nl or @DaanSelen. + ``` | - meshcentral/ # this folder contains the persistent data | - data/ # MeshCentral data-files diff --git a/docker/config.json.template b/docker/config.json.template index 44594aa8..1a1522e4 100644 --- a/docker/config.json.template +++ b/docker/config.json.template @@ -2,7 +2,6 @@ "$schema": "https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json", "settings": { "plugins":{"enabled": false}, - "_mongoDb": null, "cert": "myserver.mydomain.com", "_WANonly": true, "_LANonly": true, @@ -15,7 +14,15 @@ "TLSOffload": false, "SelfUpdate": false, "AllowFraming": false, - "WebRTC": false + "WebRTC": false, + "_mongoDb": "", + "_postgres": { + "host": "", + "port": "", + "user": "", + "password": "", + "database": "" + } }, "domains": { "": { diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index b54c83e8..c80971f9 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,39 +1,150 @@ #!/bin/bash -if [ -f "meshcentral-data/${CONFIG_FILE}" ]; then - node meshcentral/meshcentral --configfile "${CONFIG_FILE}" ${ARGS} +graceful_shutdown() { + echo "Received SIGTERM. Cleaning up..." + node /opt/meshcentral/meshcentral/meshcentral --stop + exit 0 +} +trap cleanup SIGTERM + +### Start MeshCentral Docker Container. + +date +echo "Config file: $CONFIG_FILE" + +# Failsafe to create a new config if the expected config is not there. +if [ -f "${CONFIG_FILE}" ]; then + echo "Pre-existing config found, not recreating..." else - cp config.json.template meshcentral-data/"${CONFIG_FILE}" - if [ -n "$USE_MONGODB" ] && [ "$USE_MONGODB" == "true" ]; then - if [ -z "$MONGO_URL" ]; then - prefix="" - if [ -n "$MONGO_INITDB_ROOT_USERNAME" ] && [ -n "$MONGO_INITDB_ROOT_PASSWORD" ]; then - prefix="$MONGO_INITDB_ROOT_USERNAME:$MONGO_INITDB_ROOT_PASSWORD@" - fi - MONGO_URL="${prefix}mongodb:27017" - fi - sed -i "s/\"_mongoDb\": null/\"mongoDb\": \"mongodb:\/\/$MONGO_URL\"/" meshcentral-data/"${CONFIG_FILE}" - fi - sed -i "s/\"cert\": \"myserver.mydomain.com\"/\"cert\": \"$HOSTNAME\"/" meshcentral-data/"${CONFIG_FILE}" - sed -i "s/\"NewAccounts\": true/\"NewAccounts\": $ALLOW_NEW_ACCOUNTS/" meshcentral-data/"${CONFIG_FILE}" - sed -i "s/\"enabled\": false/\"enabled\": $ALLOWPLUGINS/" meshcentral-data/"${CONFIG_FILE}" - sed -i "s/\"localSessionRecording\": false/\"localSessionRecording\": $LOCALSESSIONRECORDING/" meshcentral-data/"${CONFIG_FILE}" - sed -i "s/\"minify\": false/\"minify\": $MINIFY/" meshcentral-data/"${CONFIG_FILE}" - sed -i "s/\"WebRTC\": false/\"WebRTC\": $WEBRTC/" meshcentral-data/"${CONFIG_FILE}" - sed -i "s/\"AllowFraming\": false/\"AllowFraming\": $IFRAME/" meshcentral-data/"${CONFIG_FILE}" - 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 - if [ -z "$SESSION_KEY" ]; then - SESSION_KEY="$(cat /dev/urandom | tr -dc 'A-Z0-9' | fold -w 48 | head -n 1)" - fi - sed -i "s/\"_sessionKey\": \"MyReallySecretPassword1\"/\"sessionKey\": \"$SESSION_KEY\"/" meshcentral-data/"${CONFIG_FILE}" - if [ "$REVERSE_PROXY" != "false" ]; then - sed -i "s/\"_certUrl\": \"my\.reverse\.proxy\"/\"certUrl\": \"https:\/\/$REVERSE_PROXY:$REVERSE_PROXY_TLS_PORT\"/" meshcentral-data/"${CONFIG_FILE}" - node meshcentral/meshcentral --configfile "${CONFIG_FILE}" ${ARGS} - exit - fi - node meshcentral/meshcentral --configfile "${CONFIG_FILE}" --cert "$HOSTNAME" ${ARGS} + cp /opt/meshcentral/config.json.template "${CONFIG_FILE}" fi + +if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then + + if [[ "$USE_MONGODB" =~ ^(true|yes)$ ]]; then + if [[ -n "$MONGO_URL" ]]; then + echo "MONGO_URL is set, using that..." + else + MONGO_URL="${MONGO_URL:-$MONGO_INITDB_ROOT_USERNAME:$MONGO_INITDB_ROOT_PASSWORD@}$MONGO_HOST:$MONGO_PORT" + fi + sed -i "s/\"?_mongoDb\": \"\"/\"mongoDb\": \"$MONGO_URL\"/" "$CONFIG_FILE" + else + sed -i 's/"?_mongoDb": ""/"_mongoDb": "null"/' "$CONFIG_FILE" + fi + + if [[ "$USE_POSTGRESQL" =~ ^(true|yes)$ ]]; then + echo "So you wanna postgrsex" + fi + + if [[ "$USE_MARIADB" =~ ^(true|yes)$ ]]; then + echo "So you wanna Maria-Dick-Big" + fi + + # 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. + # This will make the default value apply, as per: https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json + + echo "Compiling given environment variables..." + echo "If defaults are going to get applied, refer to: https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json" + + # SESSIONKEY + if [[ $REGENSESSIONKEY =~ ^(true|yes)$ ]]; then + echo "Regenerating Session-Key because REGENSESSIONKEY is 'true' or 'yes'" + SESSION_KEY=$(tr -dc 'A-Z0-9' < /dev/urandom | fold -w 60 | head -n 1) + sed -i "s/sessionKey:/ sessionKey\": \"$SESSION_KEY\"/g" "$CONFIG_FILE" + else + echo "REGENSESSIONKEY is not 'true' or 'yes', therefore it's being kept as is." + fi + + # HOSTNAME + if [[ -n $HOSTNAME ]]; then + echo "Setting hostname (cert)... - $HOSTNAME" + sed -i '/cert/ c\ "cert": "'"$HOSTNAME"'"' "$CONFIG_FILE" + else + echo "Hostname environment variable is empty, commenting it out..." + sed -i 's/"cert":/ "_cert":/g' "$CONFIG_FILE" + fi + + # ALLOW_NEW_ACCOUNTS + if [[ -n $ALLOW_NEW_ACCOUNTS ]] && [[ $ALLOW_NEW_ACCOUNTS =~ ^(true|false)$ ]]; then + echo "Setting NewAccounts... - $ALLOW_NEW_ACCOUNTS" + sed -i '/NewAccounts/ c\ "NewAccounts": "'"$ALLOW_NEW_ACCOUNTS"'"' "$CONFIG_FILE" + else + echo "Invalid ALLOW_NEW_ACCOUNTS value given, commenting out so default applies..." + sed -i 's/"NewAccounts":/ "_NewAccounts":/g' "$CONFIG_FILE" + fi + + # ALLOWPLUGINS + if [[ -n $ALLOWPLUGINS ]] && [[ $ALLOWPLUGINS =~ ^(true|false)$ ]]; then + echo "Setting plugins... - $ALLOWPLUGINS" + sed -i '/plugins/ c\ "plugins": {"enabled": '"$ALLOWPLUGINS"'}"' "$CONFIG_FILE" + else + echo "Invalid ALLOWPLUGINS value given, commenting out so default applies..." + sed -i 's/"plugins":/ "_plugins":/g' "$CONFIG_FILE" + fi + + # LOCALSESSIONRECORDING + if [[ -n $LOCALSESSIONRECORDING ]] && [[ $LOCALSESSIONRECORDING =~ ^(true|false)$ ]]; then + echo "Setting localSessionRecording... - $LOCALSESSIONRECORDING" + sed -i '/localSessionRecording/ c\ "localSessionRecording": "'"$LOCALSESSIONRECORDING"'"' "$CONFIG_FILE" + else + echo "Invalid LOCALSESSIONRECORDING value given, commenting out so default applies..." + sed -i 's/"localSessionRecording":/ "_localSessionRecording":/g' "$CONFIG_FILE" + fi + + # MINIFY + if [[ -n $MINIFY ]] && [[ $MINIFY =~ ^(true|false)$ ]]; then + echo "Setting minify... - $MINIFY" + sed -i '/minify/ c\ "minify": "'"$MINIFY"'"' "$CONFIG_FILE" + else + echo "Invalid MINIFY value given, commenting out so default applies..." + sed -i 's/"minify":/ "_minify":/g' "$CONFIG_FILE" + fi + + # WEBRTC + if [[ -n $WEBRTC ]] && [[ $WEBRTC =~ ^(true|false)$ ]]; then + echo "Setting WebRTC... - $WEBRTC" + sed -i '/WebRTC/ c\ "WebRTC": "'"$WEBRTC"'"' "$CONFIG_FILE" + else + echo "Invalid WEBRTC value given, commenting out so default applies..." + sed -i 's/"WebRTC":/ "_WebRTC":/g' "$CONFIG_FILE" + fi + + # IFRAME + if [[ -n $IFRAME ]] && [[ $IFRAME =~ ^(true|false)$ ]]; then + echo "Setting AllowFraming... - $IFRAME" + sed -i '/AllowFraming/ c\ "AllowFraming": "'"$IFRAME"'"' "$CONFIG_FILE" + else + echo "Invalid IFRAME value given, commenting out so default applies..." + 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" + sed -i '/allowedOrigin/ c\ "allowedOrigin": "'"$ALLOWED_ORIGIN"'"' "$CONFIG_FILE" + else + echo "Invalid ALLOWED_ORIGIN value given, commenting out so default applies..." + sed -i 's/"allowedOrigin":/ "_allowedOrigin":/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 + +# Actually start MeshCentral. +node /opt/meshcentral/meshcentral/meshcentral --configfile "${CONFIG_FILE}" "${ARGS}" >> /proc/1/fd/1 & +meshcentral_pid=$! + +wait "$meshcentral_pid" diff --git a/docker/docker.build.sh b/docker/tools/docker.build.sh similarity index 100% rename from docker/docker.build.sh rename to docker/tools/docker.build.sh From e11a858081fec5b64ab3c55c737e19ed8750d622 Mon Sep 17 00:00:00 2001 From: Daan Selen Date: Fri, 21 Mar 2025 16:56:47 +0100 Subject: [PATCH 5/9] I hate sed modification but I must. --- docker/Dockerfile | 2 +- docker/entrypoint.sh | 40 ++++++++++++++++++++-------------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 91cc9697..b0d8a4d9 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -2,7 +2,7 @@ FROM node:lts-alpine AS builder # Any value inside one of the disable ARGs will be accepted. -ARG DISABLE_MINIFY="" +ARG DISABLE_MINIFY="yes" ARG DISABLE_TRANSLATE="yes" RUN mkdir -p /opt/meshcentral/meshcentral diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index c80971f9..9b8cda8a 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -51,81 +51,81 @@ if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then if [[ $REGENSESSIONKEY =~ ^(true|yes)$ ]]; then echo "Regenerating Session-Key because REGENSESSIONKEY is 'true' or 'yes'" SESSION_KEY=$(tr -dc 'A-Z0-9' < /dev/urandom | fold -w 60 | head -n 1) - sed -i "s/sessionKey:/ sessionKey\": \"$SESSION_KEY\"/g" "$CONFIG_FILE" + sed -i "s/\"sessionKey\": *\"[^\"]*\"/\"sessionKey\": \"$SESSION_KEY\"/" "$CONFIG_FILE" else echo "REGENSESSIONKEY is not 'true' or 'yes', therefore it's being kept as is." fi # HOSTNAME - if [[ -n $HOSTNAME ]]; then + if [[ -n $HOSTNAME ]] && [[ $HOSTNAME =~ ^([a-zA-Z0-9-]+\.)+[a-zA-Z0-9-]+$ ]]; then echo "Setting hostname (cert)... - $HOSTNAME" - sed -i '/cert/ c\ "cert": "'"$HOSTNAME"'"' "$CONFIG_FILE" + sed -i "s/\"cert\": *\"[^\"]*\"/\"cert\": \"$HOSTNAME\"/" "$CONFIG_FILE" else - echo "Hostname environment variable is empty, commenting it out..." - sed -i 's/"cert":/ "_cert":/g' "$CONFIG_FILE" + echo "Invalid hostname, commenting it out..." + sed -i "s/\"cert\": *\"[^\"]*\"/\"cert\": \"localhost\"/" "$CONFIG_FILE" fi # ALLOW_NEW_ACCOUNTS if [[ -n $ALLOW_NEW_ACCOUNTS ]] && [[ $ALLOW_NEW_ACCOUNTS =~ ^(true|false)$ ]]; then echo "Setting NewAccounts... - $ALLOW_NEW_ACCOUNTS" - sed -i '/NewAccounts/ c\ "NewAccounts": "'"$ALLOW_NEW_ACCOUNTS"'"' "$CONFIG_FILE" + sed -i "s/\"NewAccounts\": *[a-z]*/\"NewAccounts\": $ALLOW_NEW_ACCOUNTS/" "$CONFIG_FILE" else echo "Invalid ALLOW_NEW_ACCOUNTS value given, commenting out so default applies..." - sed -i 's/"NewAccounts":/ "_NewAccounts":/g' "$CONFIG_FILE" + sed -i 's/"NewAccounts":/"_NewAccounts":/g' "$CONFIG_FILE" fi # ALLOWPLUGINS if [[ -n $ALLOWPLUGINS ]] && [[ $ALLOWPLUGINS =~ ^(true|false)$ ]]; then echo "Setting plugins... - $ALLOWPLUGINS" - sed -i '/plugins/ c\ "plugins": {"enabled": '"$ALLOWPLUGINS"'}"' "$CONFIG_FILE" + sed -i "s/\"plugins\": *{[^}]*}/\"plugins\": {\"enabled\": $ALLOWPLUGINS}/" "$CONFIG_FILE" else echo "Invalid ALLOWPLUGINS value given, commenting out so default applies..." - sed -i 's/"plugins":/ "_plugins":/g' "$CONFIG_FILE" + sed -i 's/"plugins":/"_plugins":/g' "$CONFIG_FILE" fi # LOCALSESSIONRECORDING if [[ -n $LOCALSESSIONRECORDING ]] && [[ $LOCALSESSIONRECORDING =~ ^(true|false)$ ]]; then echo "Setting localSessionRecording... - $LOCALSESSIONRECORDING" - sed -i '/localSessionRecording/ c\ "localSessionRecording": "'"$LOCALSESSIONRECORDING"'"' "$CONFIG_FILE" + sed -i "s/\"localSessionRecording\": *[a-z]*/\"localSessionRecording\": $LOCALSESSIONRECORDING/" "$CONFIG_FILE" else echo "Invalid LOCALSESSIONRECORDING value given, commenting out so default applies..." - sed -i 's/"localSessionRecording":/ "_localSessionRecording":/g' "$CONFIG_FILE" + sed -i 's/"localSessionRecording":/"_localSessionRecording":/g' "$CONFIG_FILE" fi # MINIFY if [[ -n $MINIFY ]] && [[ $MINIFY =~ ^(true|false)$ ]]; then echo "Setting minify... - $MINIFY" - sed -i '/minify/ c\ "minify": "'"$MINIFY"'"' "$CONFIG_FILE" + sed -i "s/\"minify\": *[a-z]*/\"minify\": $MINIFY/" "$CONFIG_FILE" else echo "Invalid MINIFY value given, commenting out so default applies..." - sed -i 's/"minify":/ "_minify":/g' "$CONFIG_FILE" + sed -i 's/"minify":/"_minify":/g' "$CONFIG_FILE" fi # WEBRTC if [[ -n $WEBRTC ]] && [[ $WEBRTC =~ ^(true|false)$ ]]; then echo "Setting WebRTC... - $WEBRTC" - sed -i '/WebRTC/ c\ "WebRTC": "'"$WEBRTC"'"' "$CONFIG_FILE" + sed -i "s/\"WebRTC\": *[a-z]*/\"WebRTC\": $WEBRTC/" "$CONFIG_FILE" else echo "Invalid WEBRTC value given, commenting out so default applies..." - sed -i 's/"WebRTC":/ "_WebRTC":/g' "$CONFIG_FILE" + sed -i 's/"WebRTC":/"_WebRTC":/g' "$CONFIG_FILE" fi # IFRAME if [[ -n $IFRAME ]] && [[ $IFRAME =~ ^(true|false)$ ]]; then echo "Setting AllowFraming... - $IFRAME" - sed -i '/AllowFraming/ c\ "AllowFraming": "'"$IFRAME"'"' "$CONFIG_FILE" + sed -i "s/\"AllowFraming\": *[a-z]*/\"AllowFraming\": $IFRAME/" "$CONFIG_FILE" else echo "Invalid IFRAME value given, commenting out so default applies..." - sed -i 's/"AllowFraming":/ "_AllowFraming":/g' "$CONFIG_FILE" + 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" - sed -i '/allowedOrigin/ c\ "allowedOrigin": "'"$ALLOWED_ORIGIN"'"' "$CONFIG_FILE" + sed -i "s/\"allowedOrigin\": *[a-z]*/\"allowedOrigin\": $ALLOWED_ORIGIN/" "$CONFIG_FILE" else echo "Invalid ALLOWED_ORIGIN value given, commenting out so default applies..." - sed -i 's/"allowedOrigin":/ "_allowedOrigin":/g' "$CONFIG_FILE" + sed -i 's/"allowedOrigin":/"_allowedOrigin":/g' "$CONFIG_FILE" fi echo -e "\n$(cat "$CONFIG_FILE")" @@ -147,4 +147,4 @@ fi node /opt/meshcentral/meshcentral/meshcentral --configfile "${CONFIG_FILE}" "${ARGS}" >> /proc/1/fd/1 & meshcentral_pid=$! -wait "$meshcentral_pid" +wait "$meshcentral_pid" \ No newline at end of file From 59194abc276ca847b8189ebbffd805855dee2139 Mon Sep 17 00:00:00 2001 From: Daan Date: Sat, 22 Mar 2025 02:10:42 +0100 Subject: [PATCH 6/9] More work done on the logic. mongoDB url editing works. --- .gitignore | 3 ++- docker/entrypoint.sh | 31 ++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index e2031237..58d02781 100644 --- a/.gitignore +++ b/.gitignore @@ -310,4 +310,5 @@ __pycache__/ # When running mkdocs locally as dev docs/__pycache__/ -docs/env/ \ No newline at end of file +docs/env/ +docker-compose.yaml diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 9b8cda8a..dd6d0ba8 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -22,22 +22,29 @@ fi if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then if [[ "$USE_MONGODB" =~ ^(true|yes)$ ]]; then - if [[ -n "$MONGO_URL" ]]; then + if [[ -n "$MONGO_URL" ]]; then echo "MONGO_URL is set, using that..." else - MONGO_URL="${MONGO_URL:-$MONGO_INITDB_ROOT_USERNAME:$MONGO_INITDB_ROOT_PASSWORD@}$MONGO_HOST:$MONGO_PORT" + MONGO_URL="${MONGO_URL:-$MONGO_USERNAME:$MONGO_PASS@}$MONGO_HOST:$MONGO_PORT" fi - sed -i "s/\"?_mongoDb\": \"\"/\"mongoDb\": \"$MONGO_URL\"/" "$CONFIG_FILE" + + ESCAPED_MONGO_URL=$(echo "$MONGO_URL" | sed 's/[\/&?=:]/\\&/g') + sed -i 's/"_mongoDb"/"mongoDb"/' "$CONFIG_FILE" + sed -i "s/\"mongoDb\": *\"[^\"]*\"/\"mongoDb\": \"$ESCAPED_MONGO_URL\"/" "$CONFIG_FILE" else - sed -i 's/"?_mongoDb": ""/"_mongoDb": "null"/' "$CONFIG_FILE" + sed -i 's/"mongoDb"/"_mongoDb"/' "$CONFIG_FILE" fi if [[ "$USE_POSTGRESQL" =~ ^(true|yes)$ ]]; then - echo "So you wanna postgrsex" + echo "So you wanna postgres" + else + echo "No Postgres" fi if [[ "$USE_MARIADB" =~ ^(true|yes)$ ]]; then - echo "So you wanna Maria-Dick-Big" + echo "So you wanna MariaDB" + else + echo "No MariaDB" fi # Doing the bulk with JQ utility. Given the remaining variables an opportunity with Sed. @@ -50,7 +57,9 @@ if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then # SESSIONKEY if [[ $REGENSESSIONKEY =~ ^(true|yes)$ ]]; then echo "Regenerating Session-Key because REGENSESSIONKEY is 'true' or 'yes'" - SESSION_KEY=$(tr -dc 'A-Z0-9' < /dev/urandom | fold -w 60 | head -n 1) + 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" else echo "REGENSESSIONKEY is not 'true' or 'yes', therefore it's being kept as is." @@ -59,6 +68,7 @@ if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then # 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" else echo "Invalid hostname, commenting it out..." @@ -68,6 +78,7 @@ if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then # ALLOW_NEW_ACCOUNTS if [[ -n $ALLOW_NEW_ACCOUNTS ]] && [[ $ALLOW_NEW_ACCOUNTS =~ ^(true|false)$ ]]; then 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" else echo "Invalid ALLOW_NEW_ACCOUNTS value given, commenting out so default applies..." @@ -77,6 +88,7 @@ if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then # ALLOWPLUGINS if [[ -n $ALLOWPLUGINS ]] && [[ $ALLOWPLUGINS =~ ^(true|false)$ ]]; then echo "Setting plugins... - $ALLOWPLUGINS" + sed -i 's/"_plugins"/"plugins"/' "$CONFIG_FILE" sed -i "s/\"plugins\": *{[^}]*}/\"plugins\": {\"enabled\": $ALLOWPLUGINS}/" "$CONFIG_FILE" else echo "Invalid ALLOWPLUGINS value given, commenting out so default applies..." @@ -86,6 +98,7 @@ if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then # LOCALSESSIONRECORDING if [[ -n $LOCALSESSIONRECORDING ]] && [[ $LOCALSESSIONRECORDING =~ ^(true|false)$ ]]; then echo "Setting localSessionRecording... - $LOCALSESSIONRECORDING" + sed -i 's/"_localSessionRecording"/"localSessionRecording"/' "$CONFIG_FILE" sed -i "s/\"localSessionRecording\": *[a-z]*/\"localSessionRecording\": $LOCALSESSIONRECORDING/" "$CONFIG_FILE" else echo "Invalid LOCALSESSIONRECORDING value given, commenting out so default applies..." @@ -95,6 +108,7 @@ if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then # MINIFY if [[ -n $MINIFY ]] && [[ $MINIFY =~ ^(true|false)$ ]]; then echo "Setting minify... - $MINIFY" + sed -i 's/"_minify"/"minify"/' "$CONFIG_FILE" sed -i "s/\"minify\": *[a-z]*/\"minify\": $MINIFY/" "$CONFIG_FILE" else echo "Invalid MINIFY value given, commenting out so default applies..." @@ -104,6 +118,7 @@ if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then # WEBRTC if [[ -n $WEBRTC ]] && [[ $WEBRTC =~ ^(true|false)$ ]]; then echo "Setting WebRTC... - $WEBRTC" + sed -i 's/"_WebRTC"/"WebRTC"/' "$CONFIG_FILE" sed -i "s/\"WebRTC\": *[a-z]*/\"WebRTC\": $WEBRTC/" "$CONFIG_FILE" else echo "Invalid WEBRTC value given, commenting out so default applies..." @@ -113,6 +128,7 @@ if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then # IFRAME if [[ -n $IFRAME ]] && [[ $IFRAME =~ ^(true|false)$ ]]; then echo "Setting AllowFraming... - $IFRAME" + sed -i 's/"_AllowFraming"/"AllowFraming"/' "$CONFIG_FILE" sed -i "s/\"AllowFraming\": *[a-z]*/\"AllowFraming\": $IFRAME/" "$CONFIG_FILE" else echo "Invalid IFRAME value given, commenting out so default applies..." @@ -122,6 +138,7 @@ if [[ "$DYNAMIC_CONFIG" =~ ^(true|yes)$ ]]; then # ALLOWED_ORIGIN if [[ -n $ALLOWED_ORIGIN ]] && [[ $ALLOWED_ORIGIN =~ ^(true|false)$ ]]; then echo "Setting allowedOrigin... - $ALLOWED_ORIGIN" + sed -i 's/"_allowedOrigin"/"allowedOrigin"/' "$CONFIG_FILE" sed -i "s/\"allowedOrigin\": *[a-z]*/\"allowedOrigin\": $ALLOWED_ORIGIN/" "$CONFIG_FILE" else echo "Invalid ALLOWED_ORIGIN value given, commenting out so default applies..." From 660312eff37fc8d7c28f905264c3aa25f08151d9 Mon Sep 17 00:00:00 2001 From: Daan Date: Sat, 22 Mar 2025 03:21:45 +0100 Subject: [PATCH 7/9] 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 From 62443dd4f48bb43d9da4807346dfbcc170706e5a Mon Sep 17 00:00:00 2001 From: Daan Date: Sun, 23 Mar 2025 21:02:30 +0100 Subject: [PATCH 8/9] Dockerfile change. --- docker/Dockerfile | 22 ++-- docker/README.md | 293 +++++++++++++++++++++++++++------------------- 2 files changed, 184 insertions(+), 131 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index db5b3de6..a88aca21 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -17,13 +17,19 @@ RUN if [ -z "$DISABLE_MINIFY" ] || [ -z "$DISABLE_TRANSLATE" ]; then \ cd translate && \ node translate.js extractall && \ \ - if [ -z "$DISABLE_MINIFY" ]; then \ - node translate.js minifyall; \ - fi; \ + case "$DISABLE_MINIFY" in \ + false|no|FALSE|NO) \ + node translate.js minifyall;; \ + *) \ + echo "Setting MINIFY as disabled.";; \ + esac \ \ - if [ -z "$DISABLE_TRANSLATE" ]; then \ - node translate.js translateall; \ - fi \ + case "$DISABLE_TRANSLATE" in \ + false|no|FALSE|NO) \ + node translate.js translateall;; \ + *) \ + echo "Setting TRANSLATE as disabled.";; \ + esac \ fi # Possible more updated alternative? @minify-html/node@0.15.0 -> https://www.npmjs.com/package/@minify-html/node @@ -53,7 +59,7 @@ ENV LOCALSESSIONRECORDING="true" ENV MINIFY="true" ENV REGENSESSIONKEY="false" ENV REVERSE_PROXY="" -ENV REVERSE_PROXY_TLS_PORT="" +ENV REVERSE_PROXY_TLS_PORT="443" ENV WEBRTC="false" @@ -170,4 +176,4 @@ VOLUME /opt/meshcentral/meshcentral-backups COPY ./docker/entrypoint.sh ./entrypoint.sh COPY ./docker/config.json.template /opt/meshcentral/config.json.template -CMD ["bash", "/opt/meshcentral/entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["bash", "/opt/meshcentral/entrypoint.sh"] \ No newline at end of file diff --git a/docker/README.md b/docker/README.md index 31cf018e..070d1a3d 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,138 +1,185 @@ -# Create folder-structure and files +# MeshCentral Docker Configuration Guide -# TO BE REWRITTEN - In progress, for questions: dselen@nerthus.nl or @DaanSelen. +## Overview +This document provides a comprehensive guide to setting up and configuring MeshCentral in a Docker environment. It includes available options, security measures, and deployment instructions. -``` -| - meshcentral/ # this folder contains the persistent data - | - data/ # MeshCentral data-files - | - user_files/ # where file uploads for users live - | - web/ # location for site customization files - | - backup/ # location for the meshcentral-backups -| - .env # environment file with initial variables -| - docker-compose.yml +## Environment Variables +Below is a breakdown of environment variables used in this setup. + +### General MeshCentral Configuration +| Variable | Default Value | Description | +|----------|--------------|-------------| +| NODE_ENV | production | Specifies the Node.js environment. | +| CONFIG_FILE | /opt/meshcentral/meshcentral-data/config.json | Path to the configuration file. | +| DYNAMIC_CONFIG | true | Enables/disables dynamic configuration. This means config is being rechecked every container restart. | +| ALLOWPLUGINS | false | Enables/disables plugins. | +| ALLOW_NEW_ACCOUNTS | false | Enables/disables new account creation. | +| ALLOWED_ORIGIN | false | Enables/disables allowed origin policy. | +| ARGS | "" | Additional arguments for MeshCentral. | +| HOSTNAME | localhost | Specifies the hostname. | +| IFRAME | false | Enables/disables embedding in an iframe. | +| LOCALSESSIONRECORDING | true | Enables session recording. | +| MINIFY | true | Minifies the JavaScript and HTML output. | +| REGENSESSIONKEY | false | Regenerates the session key on each restart of the container. | +| REVERSE_PROXY | "" | Configures reverse proxy support through `certUrl`. | +| REVERSE_PROXY_TLS_PORT | "443" | Configures reverse proxy TLS port, will be combined with: `REVERSE_PROXY`. | +| WEBRTC | false | Enables/disables WebRTC support. | + +### Database Configuration + +#### MeshCentral Database Settings +| Variable | Default Value | Description | +|----------|--------------|-------------| +| USE_MONGODB | false | Enables MongoDB usage. | +| USE_POSTGRESQL | false | Enables PostgreSQL usage. | +| USE_MARIADB | false | Enables MariaDB usage. | + +#### MongoDB Configuration +| Variable | Default Value | Description | +|----------|--------------|-------------| +| MONGO_HOST | "" | MongoDB server hostname. | +| MONGO_PORT | 27017 | MongoDB server port. | +| MONGO_USERNAME | "" | MongoDB username. | +| MONGO_PASS | "" | MongoDB password. | +| MONGO_URL | "" | Overrides other MongoDB connection settings. | + +#### PostgreSQL Configuration +| Variable | Default Value | Description | +|----------|--------------|-------------| +| PSQL_HOST | "" | PostgreSQL server hostname. | +| PSQL_PORT | 5432 | PostgreSQL server port. | +| PSQL_USER | "" | PostgreSQL username. | +| PSQL_PASS | "" | PostgreSQL password. | +| PSQL_DATABASE | "" | PostgreSQL database name. | + +#### MariaDB Configuration +| Variable | Default Value | Description | +|----------|--------------|-------------| +| MARIADB_HOST | "" | MariaDB server hostname. | +| MARIADB_PORT | 3306 | MariaDB server port. | +| MARIADB_USER | "" | MariaDB username. | +| MARIADB_PASS | "" | MariaDB password. | +| MARIADB_DATABASE | "" | MariaDB database name. | + +## Deployment Instructions + +### Running with Docker CLI +```sh +docker run -d \ + -e HOSTNAME=myserver.domain.com \ + -e ALLOW_NEW_ACCOUNTS=true \ + -e USE_MONGODB=true \ + -e MONGO_HOST=mongodb \ + -e MONGO_PORT=27017 \ + -v meshcentral-data:/opt/meshcentral/meshcentral-data \ + -p 443:443 \ + ghcr.io/ylianst/meshcentral: ``` -# Templates - -## .env -You can place the `config.json` file directly under `./meshcentral/data/`, or use the following `.env` file instead. +### Running with Docker Compose +```yaml +services: + meshcentral: + image: ghcr.io/ylianst/meshcentral: + environment: + - HOSTNAME=myserver.domain.com + - ALLOW_NEW_ACCOUNTS=true + - USE_MONGODB=true + - MONGO_HOST=mongodb + - MONGO_PORT=27017 + volumes: + - meshcentral-data:/opt/meshcentral/meshcentral-data + ports: + - "443:443" +volumes: + meshcentral-data: +``` +### Using an `.env` File +Create a `.env` file: ```ini -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" +# Environment variables +NODE_ENV=production +CONFIG_FILE=/opt/meshcentral/meshcentral-data/config.json +DYNAMIC_CONFIG=true -# 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" +# MeshCentral Configuration +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 -# MongoDB Variables -INCLUDE_MONGODB_TOOLS = "false" -USE_MONGODB = "false" -MONGO_HOST = "" -MONGO_PORT = "27017" -MONGO_USERNAME = "" -MONGO_PASS = "" -MONGO_URL = "" +# MongoDB Configuration +USE_MONGODB=false +MONGO_HOST= +MONGO_PORT=27017 +MONGO_USERNAME= +MONGO_PASS= +MONGO_URL= -# PostgreSQL Variables -INCLUDE_POSTGRESQL_TOOLS = "false" -USE_POSTGRESQL = "false" -PSQL_HOST = "" -PSQL_PORT = "5432" -PSQL_USER = "" -PSQL_PASS = "" -PSQL_DATABASE = "" +# PostgreSQL Configuration +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 = "" +# MariaDB/MySQL Configuration +USE_MARIADB=false +MARIADB_HOST= +MARIADB_PORT=3306 +MARIADB_USER= +MARIADB_PASS= +MARIADB_DATABASE= + +# Build options +INCLUDE_MONGODB_TOOLS=false +INCLUDE_POSTGRESQL_TOOLS=false +INCLUDE_MARIADB_TOOLS=false +PREINSTALL_LIBS=false +``` +Then run Docker Compose: +```sh +docker-compose --env-file .env up -d ``` -## docker-compose.yml +# MeshCentral Docker Build Process -```yaml -services: - meshcentral: - restart: always - container_name: meshcentral - # use the official meshcentral container - image: ghcr.io/ylianst/meshcentral:latest - ports: - - 8086:443 - env_file: - - .env - volumes: - # config.json and other important files live here. A must for data persistence - - ./meshcentral/data:/opt/meshcentral/meshcentral-data - # where file uploads for users live - - ./meshcentral/user_files:/opt/meshcentral/meshcentral-files - # location for the meshcentral-backups - this should be mounted to an external storage - - ./meshcentral/backup:/opt/meshcentral/meshcentral-backups - # location for site customization files - - ./meshcentral/web:/opt/meshcentral/meshcentral-web +This document explains the build process for the MeshCentral Docker image, along with details on various build arguments and how to use them. + +## Build Arguments + +The following build arguments are available for customizing the build process: + +- **DISABLE_MINIFY**: Disable HTML/JS minification during the build. +- **DISABLE_TRANSLATE**: Disable translation of strings in MeshCentral. +- **INCLUDE_MONGODB_TOOLS**: Include MongoDB client and related tools. +- **INCLUDE_POSTGRESQL_TOOLS**: Include PostgreSQL client tools. +- **INCLUDE_MARIADB_TOOLS**: Include MariaDB/MySQL client tools. +- **PREINSTALL_LIBS**: Pre-install specific libraries like `ssh2`, `semver`, `nodemailer`, etc. + +### Build Commands with Arguments + +Here are the shell commands to build the Docker image with different configurations. + +#### 1. Build with Minify and Translate Disabled +If you want to disable both HTML/JS minification and translation during the build process, use the following command: + +```sh +docker build --build-arg DISABLE_MINIFY=no --build-arg DISABLE_TRANSLATE=no -t meshcentral . ``` -## docker-compose.yml mongodb - -```yaml -version: '3' - -networks: - meshcentral-tier: - driver: bridge - -services: - mongodb: - restart: always - container_name: mongodb - image: mongo:latest - env_file: - - .env - volumes: - # mongodb data-directory - A must for data persistence - - ./meshcentral/mongodb_data:/data/db - networks: - - meshcentral-tier - - meshcentral: - restart: always - container_name: meshcentral - # use the official meshcentral container - image: ghcr.io/ylianst/meshcentral:latest - depends_on: - - mongodb - 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 - volumes: - # config.json and other important files live here. A must for data persistence - - ./meshcentral/data:/opt/meshcentral/meshcentral-data - # where file uploads for users live - - ./meshcentral/user_files:/opt/meshcentral/meshcentral-files - # location for the meshcentral-backups - this should be mounted to an external storage - - ./meshcentral/backup:/opt/meshcentral/meshcentral-backups - # location for site customization files - - ./meshcentral/web:/opt/meshcentral/meshcentral-web - networks: - - meshcentral-tier -``` +## Security Measures +- Only exposing port 443 to minimize attack surface. +- Using environment variables for sensitive credentials. +- Removing unnecessary files after installation. +- Enforcing proper permissions on configuration files. \ No newline at end of file From 8448a6add01638c7a2f72fe4255d82ea6fd616a3 Mon Sep 17 00:00:00 2001 From: Daan Date: Sun, 23 Mar 2025 22:00:02 +0100 Subject: [PATCH 9/9] Further foolproofed the Dockerfile. --- docker/Dockerfile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index a88aca21..1524970c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -13,17 +13,14 @@ COPY ./ /opt/meshcentral/meshcentral/ RUN if [ -z "$DISABLE_MINIFY" ] || [ -z "$DISABLE_TRANSLATE" ]; then \ cd meshcentral && \ npm install html-minifier@4.0.0 jsdom@26.0.0 esprima@4.0.1 && \ -\ cd translate && \ node translate.js extractall && \ -\ case "$DISABLE_MINIFY" in \ false|no|FALSE|NO) \ node translate.js minifyall;; \ *) \ - echo "Setting MINIFY as disabled.";; \ - esac \ -\ + echo "Setting MINIFY as disabled.";; \ + esac && \ case "$DISABLE_TRANSLATE" in \ false|no|FALSE|NO) \ node translate.js translateall;; \