Compare commits
202 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49da5da9dd | ||
|
|
1bd06ccded | ||
|
|
7681f52ee6 | ||
|
|
3bcfd031ca | ||
|
|
b50d07c183 | ||
|
|
a051cb5548 | ||
|
|
d0e352c6c8 | ||
|
|
d7efb1f3b1 | ||
|
|
4137132701 | ||
|
|
c899ee2404 | ||
|
|
6e2f9aad37 | ||
|
|
f58217280a | ||
|
|
29858c65e7 | ||
|
|
d31a7e54dc | ||
|
|
f9bb7315cc | ||
|
|
751f6a80e5 | ||
|
|
d386f02a2e | ||
|
|
781c2ea60a | ||
|
|
b96db142c8 | ||
|
|
683b4e882b | ||
|
|
740a2bfbaa | ||
|
|
e89f97aaed | ||
|
|
bd37bb5391 | ||
|
|
acd6001a8a | ||
|
|
c7d1c0e18f | ||
|
|
e5205f285b | ||
|
|
dd01abc38e | ||
|
|
64ece1df90 | ||
|
|
4140656028 | ||
|
|
bd78975048 | ||
|
|
1a37425f6e | ||
|
|
dedae6c495 | ||
|
|
819e9c528c | ||
|
|
f2a2676cbb | ||
|
|
4c9729290d | ||
|
|
7b7c8348c6 | ||
|
|
bd3f582b68 | ||
|
|
63092f16c1 | ||
|
|
5d3c3941f4 | ||
|
|
cc9a2d109c | ||
|
|
c7d096a0e5 | ||
|
|
003e0ded6a | ||
|
|
5032755c29 | ||
|
|
d4c4a90395 | ||
|
|
709675ffb7 | ||
|
|
4295901fc1 | ||
|
|
0a837aa96d | ||
|
|
4379eb5f33 | ||
|
|
f1ddf6e26a | ||
|
|
ea341774e5 | ||
|
|
0f247f835f | ||
|
|
ce5111477d | ||
|
|
15f6c9d30b | ||
|
|
b66948132a | ||
|
|
dbb4615ce0 | ||
|
|
760ee24be9 | ||
|
|
6bcf39610a | ||
|
|
4bff9f1788 | ||
|
|
97f61b3562 | ||
|
|
b515576317 | ||
|
|
3cf6b9334c | ||
|
|
d2433cb250 | ||
|
|
6dfdb5267e | ||
|
|
88ccd14438 | ||
|
|
28f6f5b7e0 | ||
|
|
2a9daae82e | ||
|
|
87c37ea3f9 | ||
|
|
6bb1441330 | ||
|
|
b3ca1f9882 | ||
|
|
793ec3384c | ||
|
|
8f4a98a781 | ||
|
|
5c5bcb4152 | ||
|
|
27472852a2 | ||
|
|
8c90f5c67d | ||
|
|
1e534282ac | ||
|
|
f723486fc4 | ||
|
|
a50265a2c5 | ||
|
|
9345ee718c | ||
|
|
2383280736 | ||
|
|
a63a1de2f2 | ||
|
|
b770086132 | ||
|
|
ae46993519 | ||
|
|
a7633d27c5 | ||
|
|
bd670a74b4 | ||
|
|
aa44cfb319 | ||
|
|
baddb42664 | ||
|
|
cebbb68fdd | ||
|
|
554999d07f | ||
|
|
e891596a3e | ||
|
|
62bfe0aa37 | ||
|
|
4565158b94 | ||
|
|
6feebaee57 | ||
|
|
4a48ea0323 | ||
|
|
d820f7aee0 | ||
|
|
045fac4639 | ||
|
|
5939cf4e6c | ||
|
|
cb9bc580d0 | ||
|
|
11eee2f5eb | ||
|
|
1383df3f4e | ||
|
|
8e47123611 | ||
|
|
0b6d4b28be | ||
|
|
0aaab322ad | ||
|
|
f2bb94c8ca | ||
|
|
3e07d92e6f | ||
|
|
7ad49ba0ac | ||
|
|
92c2b61318 | ||
|
|
e47626a688 | ||
|
|
6467947904 | ||
|
|
28aa2710fd | ||
|
|
fb7940b2ce | ||
|
|
9bc2b3f4cf | ||
|
|
cadc0d03d2 | ||
|
|
c6d8428725 | ||
|
|
809451741e | ||
|
|
95759d4022 | ||
|
|
2b4ab2b122 | ||
|
|
1d7d68cde3 | ||
|
|
d21d7ab935 | ||
|
|
960326ab40 | ||
|
|
8588fe2497 | ||
|
|
b3f3d658b2 | ||
|
|
b1876f0fcf | ||
|
|
ec3e06e37f | ||
|
|
fa75a96af0 | ||
|
|
108a297b84 | ||
|
|
5044339c80 | ||
|
|
28b31b2476 | ||
|
|
809e6e6ef8 | ||
|
|
a2a9939a23 | ||
|
|
bb58763308 | ||
|
|
653074c5f4 | ||
|
|
8f70820629 | ||
|
|
1ea043a94b | ||
|
|
cd30e13ad7 | ||
|
|
6f5f5325f8 | ||
|
|
31e4ebe803 | ||
|
|
62020e1cde | ||
|
|
d533cc377b | ||
|
|
da3c4ad7f7 | ||
|
|
1009f7470a | ||
|
|
ae0aa7e9ac | ||
|
|
5ef5e9ce0e | ||
|
|
cf183cfdae | ||
|
|
3b2aaccf1b | ||
|
|
89238303cb | ||
|
|
5fcffcd608 | ||
|
|
620df54036 | ||
|
|
1399ce3590 | ||
|
|
3d57a25e49 | ||
|
|
d98f41ad31 | ||
|
|
12c5908ae4 | ||
|
|
ab17a5858b | ||
|
|
6bb6b186ce | ||
|
|
933b37f3aa | ||
|
|
5d18a1ad71 | ||
|
|
5223cbd619 | ||
|
|
f17b96bc05 | ||
|
|
6eacc9f312 | ||
|
|
5d47415edb | ||
|
|
d864789451 | ||
|
|
59ca8b0815 | ||
|
|
39395c9ac7 | ||
|
|
b7512b9bed | ||
|
|
8c5c319323 | ||
|
|
0514f4a859 | ||
|
|
5f306a23e1 | ||
|
|
4cd9196650 | ||
|
|
90b2a3dfec | ||
|
|
8b2dcf4d9d | ||
|
|
ecd32fa665 | ||
|
|
23c8c4999b | ||
|
|
17a36325d0 | ||
|
|
9464c1b01a | ||
|
|
46f77841e2 | ||
|
|
ea1b71ede6 | ||
|
|
6008767f0e | ||
|
|
75df7b86c4 | ||
|
|
e3636c0452 | ||
|
|
9e6b98a031 | ||
|
|
db7eacbca3 | ||
|
|
910f12c25a | ||
|
|
39e5691c24 | ||
|
|
c5a2286149 | ||
|
|
1e897ee401 | ||
|
|
470f22b0c0 | ||
|
|
3919c12d64 | ||
|
|
7f0f12a2e0 | ||
|
|
51ad698213 | ||
|
|
162b372b4d | ||
|
|
6a99f3c723 | ||
|
|
c2f590e39d | ||
|
|
8448a6add0 | ||
|
|
1604764a3b | ||
|
|
62443dd4f4 | ||
|
|
660312eff3 | ||
|
|
59194abc27 | ||
|
|
e11a858081 | ||
|
|
86ecc4267d | ||
|
|
5594b15df3 | ||
|
|
6eb85fa892 | ||
|
|
ddeeb8cd58 | ||
|
|
da5ef522f8 |
2
.github/workflows/deploy-docs.yml
vendored
@ -20,5 +20,5 @@ jobs:
|
||||
python-version: 3.x
|
||||
- run: pip install --upgrade pip
|
||||
- run: pip install --upgrade setuptools wheel
|
||||
- run: pip install mkdocs mkdocs-material pymdown-extensions
|
||||
- run: pip install mkdocs mkdocs-material mkdocs-print-site-plugin pymdown-extensions
|
||||
- run: mkdocs gh-deploy --force
|
||||
|
||||
410
.github/workflows/docker.yml
vendored
@ -1,67 +1,371 @@
|
||||
name: Docker
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
release:
|
||||
types: [published]
|
||||
name: Docker-Builder
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '2 0 * * *' # Daily at 00:02 UTC
|
||||
release:
|
||||
types: [ published ]
|
||||
|
||||
jobs:
|
||||
check-token:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
token_defined: ${{ steps.token_check.outputs.token_defined }}
|
||||
steps:
|
||||
- name: Check token
|
||||
id: token_check
|
||||
env:
|
||||
MY_TOKEN: ${{ secrets.MY_TOKEN }}
|
||||
if: "${{ env.MY_TOKEN != '' }}"
|
||||
run: echo "token_defined=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-token]
|
||||
if: needs.check-token.outputs.token_defined == 'true'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
translate:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Run Translations
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "lts/*"
|
||||
- name: Run translate.js (ignore errors)
|
||||
run: node translate.js || true
|
||||
working-directory: translate
|
||||
- name: Run translate extractall
|
||||
run: node translate extractall
|
||||
working-directory: translate
|
||||
- name: Run translate.js minifyall
|
||||
run: node translate.js minifyall
|
||||
working-directory: translate
|
||||
- name: Run translate.js translateall
|
||||
run: node translate.js translateall
|
||||
working-directory: translate
|
||||
- name: Upload repo with translations
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: repo-with-translations
|
||||
path: .
|
||||
|
||||
build-amd64:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: translate
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 3
|
||||
matrix:
|
||||
variant: [mongodb, postgresql, mariadb, all, slim]
|
||||
name: Build Docker Image (amd64-${{ matrix.variant }})
|
||||
steps:
|
||||
- name: Download repo artifact
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: repo-with-translations
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
with:
|
||||
cache-image: false
|
||||
platforms: amd64
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to the Container registry
|
||||
with:
|
||||
cache-binary: false
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.MY_TOKEN }}
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.MY_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push Docker image (amd64-${{ matrix.variant }})
|
||||
run: |
|
||||
REPO_OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')"
|
||||
case "${{ matrix.variant }}" in
|
||||
mongodb)
|
||||
MONGODB=YES; POSTGRESQL=NO; MARIADB=NO; TAG="-amd64-mongodb";;
|
||||
postgresql)
|
||||
MONGODB=NO; POSTGRESQL=YES; MARIADB=NO; TAG="-amd64-postgresql";;
|
||||
mariadb)
|
||||
MONGODB=NO; POSTGRESQL=NO; MARIADB=YES; TAG="-amd64-mariadb";;
|
||||
all)
|
||||
MONGODB=YES; POSTGRESQL=YES; MARIADB=YES; TAG="-amd64";;
|
||||
slim)
|
||||
MONGODB=NO; POSTGRESQL=NO; MARIADB=NO; TAG="-amd64-slim";;
|
||||
esac
|
||||
docker buildx build \
|
||||
--platform linux/amd64 \
|
||||
--build-arg INCLUDE_MONGODB_TOOLS=$MONGODB \
|
||||
--build-arg INCLUDE_POSTGRESQL_TOOLS=$POSTGRESQL \
|
||||
--build-arg INCLUDE_MARIADB_TOOLS=$MARIADB \
|
||||
--build-arg DISABLE_MINIFY=yes \
|
||||
--build-arg DISABLE_TRANSLATE=yes \
|
||||
--build-arg DISABLE_EXTRACT=yes \
|
||||
--build-arg PREINSTALL_LIBS=true \
|
||||
-f docker/Dockerfile \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}$TAG \
|
||||
--push \
|
||||
.
|
||||
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
build-arm64:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: translate
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 3
|
||||
matrix:
|
||||
variant: [mongodb, postgresql, mariadb, all, slim]
|
||||
name: Build Docker Image (arm64-${{ matrix.variant }})
|
||||
steps:
|
||||
- name: Download repo artifact
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
name: repo-with-translations
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
cache-image: false
|
||||
platforms: arm64
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
cache-binary: false
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v5
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: docker/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
INCLUDE_MONGODBTOOLS=true
|
||||
PREINSTALL_LIBS=true
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.MY_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push Docker image (arm64-${{ matrix.variant }})
|
||||
run: |
|
||||
REPO_OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')"
|
||||
case "${{ matrix.variant }}" in
|
||||
mongodb)
|
||||
MONGODB=YES; POSTGRESQL=NO; MARIADB=NO; TAG="-arm64-mongodb";;
|
||||
postgresql)
|
||||
MONGODB=NO; POSTGRESQL=YES; MARIADB=NO; TAG="-arm64-postgresql";;
|
||||
mariadb)
|
||||
MONGODB=NO; POSTGRESQL=NO; MARIADB=YES; TAG="-arm64-mariadb";;
|
||||
all)
|
||||
MONGODB=YES; POSTGRESQL=YES; MARIADB=YES; TAG="-arm64";;
|
||||
slim)
|
||||
MONGODB=NO; POSTGRESQL=NO; MARIADB=NO; TAG="-arm64-slim";;
|
||||
esac
|
||||
docker buildx build \
|
||||
--platform linux/arm64 \
|
||||
--build-arg INCLUDE_MONGODB_TOOLS=$MONGODB \
|
||||
--build-arg INCLUDE_POSTGRESQL_TOOLS=$POSTGRESQL \
|
||||
--build-arg INCLUDE_MARIADB_TOOLS=$MARIADB \
|
||||
--build-arg DISABLE_MINIFY=yes \
|
||||
--build-arg DISABLE_TRANSLATE=yes \
|
||||
--build-arg DISABLE_EXTRACT=yes \
|
||||
--build-arg PREINSTALL_LIBS=true \
|
||||
-f docker/Dockerfile \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}$TAG \
|
||||
--push \
|
||||
.
|
||||
|
||||
build-armv7:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: translate
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 3
|
||||
matrix:
|
||||
variant: [mongodb, postgresql, mariadb, all, slim]
|
||||
name: Build Docker Image (armv7-${{ matrix.variant }})
|
||||
steps:
|
||||
- name: Download repo artifact
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: repo-with-translations
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
cache-image: false
|
||||
platforms: arm
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
cache-binary: false
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.MY_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push Docker image (armv7-${{ matrix.variant }})
|
||||
run: |
|
||||
REPO_OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')"
|
||||
case "${{ matrix.variant }}" in
|
||||
mongodb)
|
||||
MONGODB=YES; POSTGRESQL=NO; MARIADB=NO; TAG="-armv7-mongodb";;
|
||||
postgresql)
|
||||
MONGODB=NO; POSTGRESQL=YES; MARIADB=NO; TAG="-armv7-postgresql";;
|
||||
mariadb)
|
||||
MONGODB=NO; POSTGRESQL=NO; MARIADB=YES; TAG="-armv7-mariadb";;
|
||||
all)
|
||||
MONGODB=YES; POSTGRESQL=YES; MARIADB=YES; TAG="-armv7";;
|
||||
slim)
|
||||
MONGODB=NO; POSTGRESQL=NO; MARIADB=NO; TAG="-armv7-slim";;
|
||||
esac
|
||||
docker buildx build \
|
||||
--platform linux/arm/v7 \
|
||||
--build-arg INCLUDE_MONGODB_TOOLS=$MONGODB \
|
||||
--build-arg INCLUDE_POSTGRESQL_TOOLS=$POSTGRESQL \
|
||||
--build-arg INCLUDE_MARIADB_TOOLS=$MARIADB \
|
||||
--build-arg DISABLE_MINIFY=yes \
|
||||
--build-arg DISABLE_TRANSLATE=yes \
|
||||
--build-arg DISABLE_EXTRACT=yes \
|
||||
--build-arg PREINSTALL_LIBS=true \
|
||||
-f docker/Dockerfile \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}$TAG \
|
||||
--push \
|
||||
.
|
||||
|
||||
build-armv6:
|
||||
runs-on: ubuntu-22.04
|
||||
needs: translate
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 3
|
||||
matrix:
|
||||
variant: [mongodb, postgresql, mariadb, all, slim]
|
||||
name: Build Docker Image (armv6-${{ matrix.variant }})
|
||||
steps:
|
||||
- name: Download repo artifact
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: repo-with-translations
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
with:
|
||||
cache-image: false
|
||||
platforms: arm
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
cache-binary: false
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.MY_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
- name: Build and push Docker image (armv6-${{ matrix.variant }})
|
||||
run: |
|
||||
REPO_OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')"
|
||||
case "${{ matrix.variant }}" in
|
||||
mongodb)
|
||||
MONGODB=YES; POSTGRESQL=NO; MARIADB=NO; TAG="-armv6-mongodb";;
|
||||
postgresql)
|
||||
MONGODB=NO; POSTGRESQL=YES; MARIADB=NO; TAG="-armv6-postgresql";;
|
||||
mariadb)
|
||||
MONGODB=NO; POSTGRESQL=NO; MARIADB=YES; TAG="-armv6-mariadb";;
|
||||
all)
|
||||
MONGODB=YES; POSTGRESQL=YES; MARIADB=YES; TAG="-armv6";;
|
||||
slim)
|
||||
MONGODB=NO; POSTGRESQL=NO; MARIADB=NO; TAG="-armv6-slim";;
|
||||
esac
|
||||
docker buildx build \
|
||||
--platform linux/arm/v6 \
|
||||
--build-arg INCLUDE_MONGODB_TOOLS=$MONGODB \
|
||||
--build-arg INCLUDE_POSTGRESQL_TOOLS=$POSTGRESQL \
|
||||
--build-arg INCLUDE_MARIADB_TOOLS=$MARIADB \
|
||||
--build-arg DISABLE_MINIFY=yes \
|
||||
--build-arg DISABLE_TRANSLATE=yes \
|
||||
--build-arg DISABLE_EXTRACT=yes \
|
||||
--build-arg PREINSTALL_LIBS=true \
|
||||
-f docker/Dockerfile \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}$TAG \
|
||||
--push \
|
||||
.
|
||||
|
||||
merge-manifest:
|
||||
runs-on: ubuntu-22.04
|
||||
needs:
|
||||
- translate
|
||||
- build-amd64
|
||||
- build-arm64
|
||||
- build-armv7
|
||||
- build-armv6
|
||||
name: Create and Push Multi-Arch Manifest
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
cache-binary: false
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.MY_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
- name: Create and push multi-arch manifests for all variants
|
||||
run: |
|
||||
REPO_OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')"
|
||||
# mongodb
|
||||
docker buildx imagetools create \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-mongodb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-mongodb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-mongodb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv7-mongodb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv6-mongodb
|
||||
# postgresql
|
||||
docker buildx imagetools create \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-postgresql \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-postgresql \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-postgresql \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv7-postgresql \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv6-postgresql
|
||||
# mariadb
|
||||
docker buildx imagetools create \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-mariadb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-mariadb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-mariadb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv7-mariadb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv6-mariadb
|
||||
# all (no suffix)
|
||||
docker buildx imagetools create \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }} \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64 \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64 \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv7 \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv6
|
||||
# slim
|
||||
docker buildx imagetools create \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-slim \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-slim \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-slim \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv7-slim \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv6-slim
|
||||
- name: Create and push 'latest' tags (releases only)
|
||||
if: github.event_name == 'release'
|
||||
run: |
|
||||
REPO_OWNER_LC="$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')"
|
||||
# latest-mongodb
|
||||
docker buildx imagetools create \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:latest-mongodb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-mongodb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-mongodb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv7-mongodb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv6-mongodb
|
||||
# latest-postgresql
|
||||
docker buildx imagetools create \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:latest-postgresql \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-postgresql \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-postgresql \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv7-postgresql \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv6-postgresql
|
||||
# latest-mariadb
|
||||
docker buildx imagetools create \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:latest-mariadb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-mariadb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-mariadb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv7-mariadb \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv6-mariadb
|
||||
# latest (all databases)
|
||||
docker buildx imagetools create \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:latest \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64 \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64 \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv7 \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv6
|
||||
# latest-slim
|
||||
docker buildx imagetools create \
|
||||
-t ghcr.io/$REPO_OWNER_LC/meshcentral:latest-slim \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-amd64-slim \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-arm64-slim \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv7-slim \
|
||||
ghcr.io/$REPO_OWNER_LC/meshcentral:${{ github.ref_name }}-armv6-slim
|
||||
|
||||
36
.github/workflows/stale.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
name: "Close stale issues and PRs"
|
||||
on:
|
||||
schedule:
|
||||
- cron: "1 2 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
actions: write
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
# Issues configuration
|
||||
stale-issue-message: "This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions."
|
||||
close-issue-message: "This issue has been automatically closed due to inactivity. If you believe this is still relevant, please feel free to reopen it."
|
||||
close-issue-label: "Closed"
|
||||
stale-issue-label: "Stale"
|
||||
exempt-issue-labels: "pinned,important,Closed"
|
||||
|
||||
# PRs configuration
|
||||
stale-pr-message: "This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions."
|
||||
close-pr-message: "This pull request has been automatically closed due to inactivity. If you'd like to continue working on it, please reopen it."
|
||||
close-pr-label: "Closed"
|
||||
stale-pr-label: "Stale"
|
||||
exempt-pr-labels: "pinned,important,Closed"
|
||||
exempt-draft-pr: true
|
||||
|
||||
# Common configuration
|
||||
operations-per-run: 5000
|
||||
ascending: true
|
||||
4
.gitignore
vendored
@ -18,6 +18,7 @@ meshcentral.db.json
|
||||
mesherrors.txt
|
||||
bob.json
|
||||
.greenlockrc
|
||||
venv
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
@ -310,4 +311,5 @@ __pycache__/
|
||||
|
||||
# When running mkdocs locally as dev
|
||||
docs/__pycache__/
|
||||
docs/env/
|
||||
docs/env/
|
||||
docker-compose.yaml
|
||||
|
||||
10
.vscode/launch.json
vendored
@ -10,6 +10,16 @@
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"name": "Test docs locally with mkdocs",
|
||||
"type": "debugpy",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/docs/env/Scripts/mkdocs.exe",
|
||||
"args": ["serve", "--dev-addr", "127.0.0.1:8010"],
|
||||
"cwd": "${workspaceFolder}/docs",
|
||||
"console": "integratedTerminal",
|
||||
"preLaunchTask": "Start MkDocs Server"
|
||||
}
|
||||
]
|
||||
}
|
||||
60
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Setup Python Environment",
|
||||
"type": "shell",
|
||||
"command": "python",
|
||||
"args": ["-m", "venv", "env"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/docs"
|
||||
},
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Install MkDocs Requirements",
|
||||
"type": "shell",
|
||||
"command": ".\\env\\Scripts\\activate.ps1; python -m pip install --upgrade pip; pip install -r requirements.txt",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/docs"
|
||||
},
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"dependsOn": "Setup Python Environment"
|
||||
},
|
||||
{
|
||||
"label": "Start MkDocs Server",
|
||||
"type": "shell",
|
||||
"command": ".\\env\\Scripts\\activate.ps1; Start-Process http://localhost:8010; mkdocs serve",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/docs"
|
||||
},
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"presentation": {
|
||||
"echo": true,
|
||||
"reveal": "always",
|
||||
"focus": false,
|
||||
"panel": "shared"
|
||||
},
|
||||
"problemMatcher": [],
|
||||
"isBackground": true,
|
||||
"dependsOn": "Install MkDocs Requirements"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -28,7 +28,8 @@
|
||||
"NOT RUNNING"
|
||||
],
|
||||
"statusDescription": "Current Agent Status",
|
||||
"description": "Click the buttons below to install or uninstall this remote management software. When installed, this software runs in the background allowing this computer to be managed and controlled by a remote administrator."
|
||||
"description": "Click the buttons below to install or uninstall this remote management software. When installed, this software runs in the background allowing this computer to be managed and controlled by a remote administrator.",
|
||||
"connectionDetailsButton": "Connection Details..."
|
||||
},
|
||||
"cs": {
|
||||
"agent": "Agent",
|
||||
@ -59,7 +60,8 @@
|
||||
"agentVersion": "Nová verze",
|
||||
"elevation": "K instalaci/odinstalaci tohoto softwaru jsou vyžadována zvýšená oprávnění.",
|
||||
"graphicalerror": "Na tomto systému nelze spustit grafickou verzi tohoto instalačního programu",
|
||||
"description": "Klepnutím na tlačítka níže nainstalujete nebo odinstalujete tento software pro vzdálenou správu. Když je tento software nainstalován, běží na pozadí, což umožňuje spravovat a ovládat tento počítač vzdáleným správcem."
|
||||
"description": "Klepnutím na tlačítka níže nainstalujete nebo odinstalujete tento software pro vzdálenou správu. Když je tento software nainstalován, běží na pozadí, což umožňuje spravovat a ovládat tento počítač vzdáleným správcem.",
|
||||
"connectionDetailsButton": "Podrobnosti o připojení..."
|
||||
},
|
||||
"de": {
|
||||
"agent": "Agent",
|
||||
@ -123,7 +125,8 @@
|
||||
"agentVersion": "Nueva versión",
|
||||
"elevation": "Se requieren permisos elevados para instalar/desinstalar este software.",
|
||||
"graphicalerror": "La versión gráfica de este instalador no puede ejecutarse en este sistema",
|
||||
"description": "Haga clic en los botones a continuación para instalar o desinstalar este software de administración remota. Cuando se instala, este software se ejecuta en segundo plano, lo que permite que un administrador remoto administre y controle esta computadora."
|
||||
"description": "Haga clic en los botones a continuación para instalar o desinstalar este software de administración remota. Cuando se instala, este software se ejecuta en segundo plano, lo que permite que un administrador remoto administre y controle esta computadora.",
|
||||
"connectionDetailsButton": "Detalles de conexión..."
|
||||
},
|
||||
"fi": {
|
||||
"agent": "Agentti",
|
||||
@ -154,7 +157,8 @@
|
||||
"agentVersion": "Uusi versio",
|
||||
"elevation": "Tämän ohjelmiston asentaminen/asennuksen poistaminen edellyttää korotettuja käyttöoikeuksia.",
|
||||
"graphicalerror": "Tämän asennusohjelman graafista versiota ei voi käyttää tässä järjestelmässä",
|
||||
"description": "Napsauta alla olevia painikkeita asentaaksesi tai poistaaksesi tämän etähallintaohjelmiston. Kun ohjelmisto on asennettu, se toimii taustalla, jolloin etäjärjestelmänvalvoja voi hallita ja ohjata tätä tietokonetta."
|
||||
"description": "Napsauta alla olevia painikkeita asentaaksesi tai poistaaksesi tämän etähallintaohjelmiston. Kun ohjelmisto on asennettu, se toimii taustalla, jolloin etäjärjestelmänvalvoja voi hallita ja ohjata tätä tietokonetta.",
|
||||
"connectionDetailsButton": "Yhteyden tiedot..."
|
||||
},
|
||||
"fr": {
|
||||
"agent": "Agent",
|
||||
@ -185,7 +189,8 @@
|
||||
"agentVersion": "Nouvelle version",
|
||||
"elevation": "Des autorisations élevées sont requises pour installer/désinstaller ce logiciel.",
|
||||
"graphicalerror": "La version graphique de ce programme d'installation ne peut pas s'exécuter sur ce système",
|
||||
"description": "Cliquez sur les boutons ci-dessous pour installer ou désinstaller ce logiciel de gestion à distance. Une fois installé, ce logiciel s'exécute en arrière-plan, ce qui permet à cet ordinateur d'être géré et contrôlé par un administrateur distant."
|
||||
"description": "Cliquez sur les boutons ci-dessous pour installer ou désinstaller ce logiciel de gestion à distance. Une fois installé, ce logiciel s'exécute en arrière-plan, ce qui permet à cet ordinateur d'être géré et contrôlé par un administrateur distant.",
|
||||
"connectionDetailsButton": "Détails de la connexion..."
|
||||
},
|
||||
"hi": {
|
||||
"agent": "एजेंट",
|
||||
@ -216,7 +221,8 @@
|
||||
"agentVersion": "नया संस्करण",
|
||||
"elevation": "इस सॉफ़्टवेयर को स्थापित/अनइंस्टॉल करने के लिए उन्नत अनुमतियों की आवश्यकता होती है।",
|
||||
"graphicalerror": "इस इंस्टालर का आलेखीय संस्करण इस सिस्टम पर नहीं चल सकता",
|
||||
"description": "इस दूरस्थ प्रबंधन सॉफ़्टवेयर को स्थापित या अनइंस्टॉल करने के लिए नीचे दिए गए बटनों पर क्लिक करें। स्थापित होने पर, यह सॉफ़्टवेयर पृष्ठभूमि में चलता है जिससे इस कंप्यूटर को दूरस्थ व्यवस्थापक द्वारा प्रबंधित और नियंत्रित किया जा सकता है।"
|
||||
"description": "इस दूरस्थ प्रबंधन सॉफ़्टवेयर को स्थापित या अनइंस्टॉल करने के लिए नीचे दिए गए बटनों पर क्लिक करें। स्थापित होने पर, यह सॉफ़्टवेयर पृष्ठभूमि में चलता है जिससे इस कंप्यूटर को दूरस्थ व्यवस्थापक द्वारा प्रबंधित और नियंत्रित किया जा सकता है।",
|
||||
"connectionDetailsButton": "कनेक्शन विवरण..."
|
||||
},
|
||||
"it": {
|
||||
"agent": "Agente",
|
||||
@ -247,7 +253,8 @@
|
||||
"agentVersion": "Nuova versione",
|
||||
"elevation": "Per installare/disinstallare questo software sono necessarie autorizzazioni elevate.",
|
||||
"graphicalerror": "La versione grafica di questo programma di installazione non può essere eseguita su questo sistema",
|
||||
"description": "Fare clic sui pulsanti seguenti per installare o disinstallare questo software di gestione remota. Una volta installato, questo software viene eseguito in background consentendo a questo computer di essere gestito e controllato da un amministratore remoto."
|
||||
"description": "Fare clic sui pulsanti seguenti per installare o disinstallare questo software di gestione remota. Una volta installato, questo software viene eseguito in background consentendo a questo computer di essere gestito e controllato da un amministratore remoto.",
|
||||
"connectionDetailsButton": "Dettagli di connessione..."
|
||||
},
|
||||
"ja": {
|
||||
"agent": "エージェント",
|
||||
@ -278,7 +285,8 @@
|
||||
"agentVersion": "新しいバージョン",
|
||||
"elevation": "このソフトウェアをインストール/アンインストールするには、昇格された権限が必要です。",
|
||||
"graphicalerror": "このインストーラーのグラフィカルバージョンは、このシステムでは実行できません",
|
||||
"description": "このリモート管理ソフトウェアをインストールまたはアンインストールするには、下のボタンをクリックしてください。インストールすると、このソフトウェアはバックグラウンドで実行され、リモート管理者がこのコンピューターを管理および制御できるようになります。"
|
||||
"description": "このリモート管理ソフトウェアをインストールまたはアンインストールするには、下のボタンをクリックしてください。インストールすると、このソフトウェアはバックグラウンドで実行され、リモート管理者がこのコンピューターを管理および制御できるようになります。",
|
||||
"connectionDetailsButton": "接続の詳細..."
|
||||
},
|
||||
"ko": {
|
||||
"agent": "에이전트",
|
||||
@ -309,7 +317,8 @@
|
||||
"agentVersion": "새로운 버전",
|
||||
"elevation": "이 소프트웨어를 설치/제거하려면 높은 권한이 필요합니다.",
|
||||
"graphicalerror": "이 설치 프로그램의 그래픽 버전은 이 시스템에서 실행할 수 없습니다.",
|
||||
"description": "이 원격 관리 소프트웨어를 설치하거나 제거하려면 아래 버튼을 클릭하십시오. 이 소프트웨어를 설치하면 백그라운드에서 실행되어 원격 관리자가 이 컴퓨터를 관리하고 제어할 수 있습니다."
|
||||
"description": "이 원격 관리 소프트웨어를 설치하거나 제거하려면 아래 버튼을 클릭하십시오. 이 소프트웨어를 설치하면 백그라운드에서 실행되어 원격 관리자가 이 컴퓨터를 관리하고 제어할 수 있습니다.",
|
||||
"connectionDetailsButton": "연결 세부정보..."
|
||||
},
|
||||
"nl": {
|
||||
"agent": "Agent",
|
||||
@ -340,7 +349,8 @@
|
||||
"agentVersion": "Nieuwe versie",
|
||||
"elevation": "Verhoogde machtigingen zijn vereist om deze software te installeren/verwijderen.",
|
||||
"graphicalerror": "De grafische versie van dit installatieprogramma kan niet op dit systeem draaien",
|
||||
"description": "Klik op de onderstaande knoppen om deze software voor beheer op afstand te installeren of te verwijderen. Na installatie draait deze software op de achtergrond waardoor deze computer kan worden beheerd en gecontroleerd door een externe beheerder."
|
||||
"description": "Klik op de onderstaande knoppen om deze software voor beheer op afstand te installeren of te verwijderen. Na installatie draait deze software op de achtergrond waardoor deze computer kan worden beheerd en gecontroleerd door een externe beheerder.",
|
||||
"connectionDetailsButton": "Verbindingsdetails..."
|
||||
},
|
||||
"pt": {
|
||||
"agent": "Agente",
|
||||
@ -371,7 +381,8 @@
|
||||
"agentVersion": "Nova versão",
|
||||
"elevation": "Permissões elevadas são necessárias para instalar/desinstalar este software.",
|
||||
"graphicalerror": "A versão gráfica deste instalador não pode ser executada neste sistema",
|
||||
"description": "Clique nos botões abaixo para instalar ou desinstalar este software de gerenciamento remoto. Quando instalado, este software é executado em segundo plano, permitindo que este computador seja gerenciado e controlado por um administrador remoto."
|
||||
"description": "Clique nos botões abaixo para instalar ou desinstalar este software de gerenciamento remoto. Quando instalado, este software é executado em segundo plano, permitindo que este computador seja gerenciado e controlado por um administrador remoto.",
|
||||
"connectionDetailsButton": "Detalhes da conexão..."
|
||||
},
|
||||
"ru": {
|
||||
"agent": "Агент",
|
||||
@ -402,7 +413,8 @@
|
||||
"agentVersion": "Новая версия",
|
||||
"elevation": "Для установки/удаления этого программного обеспечения требуются повышенные права.",
|
||||
"graphicalerror": "Графическая версия этого установщика не может быть запущена в этой системе.",
|
||||
"description": "Нажмите кнопки ниже, чтобы установить или удалить это программное обеспечение для удаленного управления..После установки это программное обеспечение работает в фоновом режиме, что позволяет удаленному администратору управлять этим компьютером."
|
||||
"description": "Нажмите кнопки ниже, чтобы установить или удалить это программное обеспечение для удаленного управления..После установки это программное обеспечение работает в фоновом режиме, что позволяет удаленному администратору управлять этим компьютером.",
|
||||
"connectionDetailsButton": "Подробности подключения..."
|
||||
},
|
||||
"sv": {
|
||||
"agent": "Agent",
|
||||
@ -433,7 +445,8 @@
|
||||
"agentVersion": "Ny version",
|
||||
"elevation": "Förhöjda behörigheter krävs för att installera/avinstallera denna programvara.",
|
||||
"graphicalerror": "Den grafiska versionen av detta installationsprogram kan inte köras på det här systemet",
|
||||
"description": "Klicka på knapparna nedan för att installera eller avinstallera denna fjärrhanteringsprogramvara. När den är installerad körs den här programvaran i bakgrunden så att den här datorn kan hanteras och kontrolleras av en fjärradministratör."
|
||||
"description": "Klicka på knapparna nedan för att installera eller avinstallera denna fjärrhanteringsprogramvara. När den är installerad körs den här programvaran i bakgrunden så att den här datorn kan hanteras och kontrolleras av en fjärradministratör.",
|
||||
"connectionDetailsButton": "Anslutningsdetaljer..."
|
||||
},
|
||||
"tr": {
|
||||
"agent": "Agent",
|
||||
@ -464,7 +477,8 @@
|
||||
"agentVersion": "Yeni sürüm",
|
||||
"elevation": "Bu yazılımı yüklemek/kaldırmak için yüksek izinler gerekir.",
|
||||
"graphicalerror": "Bu yükleyicinin grafik sürümü bu sistemde çalışamaz",
|
||||
"description": "Bu uzaktan yönetim yazılımını yüklemek veya kaldırmak için aşağıdaki düğmelere tıklayın. Yüklendiğinde, bu yazılım arka planda çalışır ve bu bilgisayarın uzak bir yönetici tarafından yönetilmesine ve kontrol edilmesine olanak tanır."
|
||||
"description": "Bu uzaktan yönetim yazılımını yüklemek veya kaldırmak için aşağıdaki düğmelere tıklayın. Yüklendiğinde, bu yazılım arka planda çalışır ve bu bilgisayarın uzak bir yönetici tarafından yönetilmesine ve kontrol edilmesine olanak tanır.",
|
||||
"connectionDetailsButton": "Bağlantı ayrıntıları..."
|
||||
},
|
||||
"zh-chs": {
|
||||
"agent": "代理",
|
||||
@ -495,7 +509,8 @@
|
||||
"agentVersion": "新版本",
|
||||
"elevation": "安装/卸载此软件需要提升权限。",
|
||||
"graphicalerror": "此安装程序的图形版本无法在此系统上运行",
|
||||
"description": "单击下面的按钮以安装或卸载此远程管理软件。安装后,该软件在后台运行,允许远程管理员管理和控制该计算机。"
|
||||
"description": "单击下面的按钮以安装或卸载此远程管理软件。安装后,该软件在后台运行,允许远程管理员管理和控制该计算机。",
|
||||
"connectionDetailsButton": "连接详情..."
|
||||
},
|
||||
"zh-cht": {
|
||||
"agent": "代理",
|
||||
@ -526,7 +541,8 @@
|
||||
"agentVersion": "新版本",
|
||||
"elevation": "安裝/卸載此軟件需要提升權限。",
|
||||
"graphicalerror": "此安裝程序的圖形版本無法在此系統上運行",
|
||||
"description": "單擊下面的按鈕以安裝或卸載此遠程管理軟件。安裝後,該軟件在後台運行,允許遠程管理員管理和控制該計算機。"
|
||||
"description": "單擊下面的按鈕以安裝或卸載此遠程管理軟件。安裝後,該軟件在後台運行,允許遠程管理員管理和控制該計算機。",
|
||||
"connectionDetailsButton": "連接詳情..."
|
||||
},
|
||||
"da": {
|
||||
"agent": "Agent",
|
||||
@ -557,7 +573,8 @@
|
||||
"agentVersion": "Ny version",
|
||||
"elevation": "Forhøjede tilladelser er nødvendige for at installere/afinstallere denne software.",
|
||||
"graphicalerror": "Den grafiske version af dette installationsprogram kan ikke køre på dette system",
|
||||
"description": "Klik på knapperne nedenfor for at installere eller afinstallere denne fjernstyringssoftware. Når den er installeret, kører denne software i baggrunden, så denne computer kan administreres og kontrolleres af en fjernadministrator."
|
||||
"description": "Klik på knapperne nedenfor for at installere eller afinstallere denne fjernstyringssoftware. Når den er installeret, kører denne software i baggrunden, så denne computer kan administreres og kontrolleres af en fjernadministrator.",
|
||||
"connectionDetailsButton": "Forbindelsesdetaljer..."
|
||||
},
|
||||
"pl": {
|
||||
"agent": "Agent",
|
||||
@ -588,7 +605,8 @@
|
||||
"agentVersion": "Nowa Wersja",
|
||||
"elevation": "Do zainstalowania/odinstalowania tego oprogramowania wymagane są podwyższone uprawnienia.",
|
||||
"graphicalerror": "Graficzna wersja tego instalatora nie może być uruchomiona w tym systemie",
|
||||
"description": "Kliknij poniższe przyciski, aby zainstalować lub odinstalować oprogramowanie zdalnego dostępu. Po zainstalowaniu, to oprogramowanie działa w tle, umożliwiając zarządzanie i kontrolowanie tego komputera przez zdalnego administratora."
|
||||
"description": "Kliknij poniższe przyciski, aby zainstalować lub odinstalować oprogramowanie zdalnego dostępu. Po zainstalowaniu, to oprogramowanie działa w tle, umożliwiając zarządzanie i kontrolowanie tego komputera przez zdalnego administratora.",
|
||||
"connectionDetailsButton": "Szczegóły połączenia..."
|
||||
},
|
||||
"pt-br": {
|
||||
"agent": "Agente",
|
||||
@ -619,7 +637,8 @@
|
||||
"agentVersion": "Nova Versão",
|
||||
"elevation": "Permissões Elevadas são necessárias para instalar/desinstalar este software",
|
||||
"graphicalerror": "A versão gráfica do instalador não pode ser executada neste sistema",
|
||||
"description": "Clique nos botões abaixo para instalar ou desinstalar este software de gerenciamento remoto. Quando instalado, este software é executado em segundo plano permitindo que este computador seja gerenciado e controlado por um administrador remoto"
|
||||
"description": "Clique nos botões abaixo para instalar ou desinstalar este software de gerenciamento remoto. Quando instalado, este software é executado em segundo plano permitindo que este computador seja gerenciado e controlado por um administrador remoto",
|
||||
"connectionDetailsButton": "Detalhes da conexão..."
|
||||
},
|
||||
"bs": {
|
||||
"agent": "Agent",
|
||||
@ -650,7 +669,8 @@
|
||||
"NOT RUNNING"
|
||||
],
|
||||
"statusDescription": "Trenutni status agenta",
|
||||
"description": "Kliknite na dugmad ispod da instalirate ili deinstalirate ovaj softver za daljinsko upravljanje. Kada je instaliran, ovaj softver radi u pozadini, što omogućava da ovim računarom upravlja i kontroliše udaljeni administrator."
|
||||
"description": "Kliknite na dugmad ispod da instalirate ili deinstalirate ovaj softver za daljinsko upravljanje. Kada je instaliran, ovaj softver radi u pozadini, što omogućava da ovim računarom upravlja i kontroliše udaljeni administrator.",
|
||||
"connectionDetailsButton": "Detalji veze..."
|
||||
},
|
||||
"hu": {
|
||||
"agent": "Agent",
|
||||
@ -681,7 +701,8 @@
|
||||
"NEM FUT"
|
||||
],
|
||||
"statusDescription": "Jelenlegi agent állapota",
|
||||
"description": "Kattintson a Telepítés vagy Eltávolítás gombokra a Távfelügyeleti alkalmazás telepítéséhez vagy eltávolításához. Telepítés után ez az alkalmazás a háttérben fut, lehetővé téve, hogy a számítógépet egy távoli rendszergazda kezelje."
|
||||
"description": "Kattintson a Telepítés vagy Eltávolítás gombokra a Távfelügyeleti alkalmazás telepítéséhez vagy eltávolításához. Telepítés után ez az alkalmazás a háttérben fut, lehetővé téve, hogy a számítógépet egy távoli rendszergazda kezelje.",
|
||||
"connectionDetailsButton": "Kapcsolat részletei..."
|
||||
},
|
||||
"ca": {
|
||||
"agent": "Agent",
|
||||
@ -712,37 +733,39 @@
|
||||
"NO CORRE"
|
||||
],
|
||||
"statusDescription": "Estat actual de l'agent",
|
||||
"description": "Feu clic als botons següents per instal·lar o desinstal·lar aquest programari de gestió remota. Quan s'instal·la, aquest programari s'executa en segon pla i permet que aquest ordinador sigui gestionat i controlat per un administrador remot."
|
||||
"description": "Feu clic als botons següents per instal·lar o desinstal·lar aquest programari de gestió remota. Quan s'instal·la, aquest programari s'executa en segon pla i permet que aquest ordinador sigui gestionat i controlat per un administrador remot.",
|
||||
"connectionDetailsButton": "Detalls de la connexió..."
|
||||
},
|
||||
"uk": {
|
||||
"agent": "Агент",
|
||||
"agentVersion": "Нова Версія",
|
||||
"group": "Група Пристроїв",
|
||||
"agentVersion": "Нова версія",
|
||||
"group": "Група пристроїв",
|
||||
"url": "URL Сервера",
|
||||
"meshName": "Ім'я Групи",
|
||||
"meshName": "Ім'я групи",
|
||||
"meshId": "Ідентифікатор групи",
|
||||
"serverId": "Ідентифікатор серверу",
|
||||
"serverId": "Ідентифікатор сервера",
|
||||
"setup": "Налаштувати",
|
||||
"update": "Оновлення",
|
||||
"update": "Оновити",
|
||||
"install": "Інсталювати",
|
||||
"uninstall": "Видалити",
|
||||
"connect": "Підключитися",
|
||||
"connect": "Підключитись",
|
||||
"disconnect": "Відключити",
|
||||
"cancel": "Скасувати",
|
||||
"close": "Закрити",
|
||||
"pressok": "Натисніть OK, щоб від'єднатися",
|
||||
"elevation": "Для інсталяції/деінсталяції цього програмного забезпечення потрібні підвищені дозволи.",
|
||||
"pressok": "Натисніть OK, щоб від'єднатись",
|
||||
"elevation": "Для встановлення/видалення цієї програми потрібні права адміністратора.",
|
||||
"sudo": "Будь ласка, спробуйте ще раз за допомогою sudo.",
|
||||
"ctrlc": "Натисніть Ctrl-C, щоб вийти",
|
||||
"commands": "Ви можете запустити текстову версію з командного рядка за допомогою таких команд",
|
||||
"graphicalerror": "Графічна версія цього інсталятора не може працювати в цій системі",
|
||||
"zenity": "Спробуйте встановити/оновити Zenity та запустіть наново",
|
||||
"graphicalerror": "Графічна версія цього інсталятора не може запуститись в цій системі",
|
||||
"zenity": "Спробуйте встановити або оновити Zenity, а тоді запустіть програму знову",
|
||||
"status": [
|
||||
"НЕ ВСТАНОВЛЕНО",
|
||||
"ВИКОНУЄТЬСЯ",
|
||||
"ПРАЦЮЄ",
|
||||
"НЕ ПРАЦЮЄ"
|
||||
],
|
||||
"statusDescription": "Поточний Статус Агента",
|
||||
"description": "Клікнути кнопки нижче, щоб інсталювати або видалити це програмне забезпечення для віддаленого керування. Після інсталювання ця програма працює у фоновому режимі, що дозволяє віддаленому адміністратору керувати цим комп'ютером."
|
||||
"statusDescription": "Поточний статус Агента",
|
||||
"description": "Щоб встановити або видалити це програмне забезпечення для віддаленого керування, скористайтеся кнопками нижче. Після інсталяції програма працютиме у фоновому режимі, що дозволить віддаленому адміністратору керувати цим комп'ютером. Підключення ж надасть тимчасовий доступ поки це вікно відкрите",
|
||||
"connectionDetailsButton": "Деталі з'єднання..."
|
||||
}
|
||||
}
|
||||
@ -1176,6 +1176,13 @@ function handleServerCommand(data) {
|
||||
tunnel.consentTimeout = (tunnel.soptions && tunnel.soptions.consentTimeout) ? tunnel.soptions.consentTimeout : 30;
|
||||
tunnel.consentAutoAccept = (tunnel.soptions && (tunnel.soptions.consentAutoAccept === true));
|
||||
tunnel.consentAutoAcceptIfNoUser = (tunnel.soptions && (tunnel.soptions.consentAutoAcceptIfNoUser === true));
|
||||
tunnel.consentAutoAcceptIfDesktopNoUser = (tunnel.soptions && (tunnel.soptions.consentAutoAcceptIfDesktopNoUser === true));
|
||||
tunnel.consentAutoAcceptIfTerminalNoUser = (tunnel.soptions && (tunnel.soptions.consentAutoAcceptIfTerminalNoUser === true));
|
||||
tunnel.consentAutoAcceptIfFileNoUser = (tunnel.soptions && (tunnel.soptions.consentAutoAcceptIfFileNoUser === true));
|
||||
tunnel.consentAutoAcceptIfLocked = (tunnel.soptions && (tunnel.soptions.consentAutoAcceptIfLocked === true));
|
||||
tunnel.consentAutoAcceptIfDesktopLocked = (tunnel.soptions && (tunnel.soptions.consentAutoAcceptIfDesktopLocked === true));
|
||||
tunnel.consentAutoAcceptIfTerminalLocked = (tunnel.soptions && (tunnel.soptions.consentAutoAcceptIfTerminalLocked === true));
|
||||
tunnel.consentAutoAcceptIfFileLocked = (tunnel.soptions && (tunnel.soptions.consentAutoAcceptIfFileLocked === true));
|
||||
tunnel.oldStyle = (tunnel.soptions && tunnel.soptions.oldStyle) ? tunnel.soptions.oldStyle : false;
|
||||
tunnel.tcpaddr = data.tcpaddr;
|
||||
tunnel.tcpport = data.tcpport;
|
||||
@ -1302,8 +1309,10 @@ function handleServerCommand(data) {
|
||||
case 'pskill': {
|
||||
// Kill a process
|
||||
if (data.value) {
|
||||
MeshServerLogEx(19, [data.value], "Killing process " + data.value, data);
|
||||
try { process.kill(data.value); } catch (ex) { sendConsoleText("pskill: " + JSON.stringify(ex)); }
|
||||
var info = data.value.split('|'), pid = data.value, msg = " (Unknown)";
|
||||
if (info.length > 1) { pid = info[0]; msg = " (" + info[1] + ")"; } else { info[1] = "Unknown"; }
|
||||
MeshServerLogEx(19, info, "Killing process " + pid + msg, data);
|
||||
try { process.kill(parseInt(pid)); } catch (ex) { sendConsoleText("pskill: " + JSON.stringify(ex)); }
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -3065,7 +3074,7 @@ function onTunnelData(data)
|
||||
// Perform User-Consent if needed.
|
||||
if (this.httprequest.consent && (this.httprequest.consent & 16)) {
|
||||
// User asked for consent so now we check if we can auto accept if no user is present/loggedin
|
||||
if (this.httprequest.consentAutoAcceptIfNoUser) {
|
||||
if (this.httprequest.consentAutoAcceptIfNoUser || this.httprequest.consentAutoAcceptIfTerminalNoUser || this.httprequest.consentAutoAcceptIfLocked || this.httprequest.consentAutoAcceptIfTerminalLocked) {
|
||||
var p = require('user-sessions').enumerateUsers();
|
||||
p.sessionid = this.httprequest.sessionid;
|
||||
p.ws = this;
|
||||
@ -3074,10 +3083,35 @@ function onTunnelData(data)
|
||||
for (var i in u) {
|
||||
if (u[i].State == 'Active') { v.push({ tsid: i, type: u[i].StationName, user: u[i].Username, domain: u[i].Domain }); }
|
||||
}
|
||||
if (v.length == 0) { // No user is present, auto accept
|
||||
var autoAccept = false;
|
||||
|
||||
// Check if we should auto-accept because no user is present
|
||||
if ((this.ws.httprequest.consentAutoAcceptIfNoUser || this.ws.httprequest.consentAutoAcceptIfTerminalNoUser) && (v.length == 0)) {
|
||||
autoAccept = true;
|
||||
}
|
||||
|
||||
// Check if we should auto-accept because all users are locked
|
||||
if ((this.ws.httprequest.consentAutoAcceptIfLocked || this.ws.httprequest.consentAutoAcceptIfTerminalLocked) && (v.length > 0)) {
|
||||
var allUsersLocked = true;
|
||||
if (!meshCoreObj.lusers || meshCoreObj.lusers.length == 0) {
|
||||
// No locked users list available, assume users are not locked
|
||||
allUsersLocked = false;
|
||||
} else {
|
||||
for (var i in v) {
|
||||
var username = v[i].domain ? (v[i].domain + '\\' + v[i].user) : v[i].user;
|
||||
if (meshCoreObj.lusers.indexOf(username) == -1) {
|
||||
allUsersLocked = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allUsersLocked) { autoAccept = true; }
|
||||
}
|
||||
|
||||
if (autoAccept) {
|
||||
this.ws.httprequest.tpromise._res();
|
||||
} else {
|
||||
// User is present so we still need consent
|
||||
// User is present and not all locked, so we still need consent
|
||||
terminal_consent_ask(this.ws);
|
||||
}
|
||||
});
|
||||
@ -3186,7 +3220,7 @@ function onTunnelData(data)
|
||||
if (this.httprequest.consent && (this.httprequest.consent & 8)) {
|
||||
|
||||
// User asked for consent but now we check if can auto accept if no user is present
|
||||
if (this.httprequest.consentAutoAcceptIfNoUser) {
|
||||
if (this.httprequest.consentAutoAcceptIfNoUser || this.httprequest.consentAutoAcceptIfDesktopNoUser || this.httprequest.consentAutoAcceptIfLocked || this.httprequest.consentAutoAcceptIfDesktopLocked) {
|
||||
// Get list of users to check if we any actual users logged in, and if users logged in, we still need consent
|
||||
var p = require('user-sessions').enumerateUsers();
|
||||
p.sessionid = this.httprequest.sessionid;
|
||||
@ -3196,10 +3230,36 @@ function onTunnelData(data)
|
||||
for (var i in u) {
|
||||
if (u[i].State == 'Active') { v.push({ tsid: i, type: u[i].StationName, user: u[i].Username, domain: u[i].Domain }); }
|
||||
}
|
||||
if (v.length == 0) { // No user is present, auto accept
|
||||
var autoAccept = false;
|
||||
|
||||
// Check if we can auto-accept because no user is present
|
||||
if ((this.ws.httprequest.consentAutoAcceptIfNoUser || this.ws.httprequest.consentAutoAcceptIfDesktopNoUser) && (v.length == 0)) {
|
||||
// No user is present, auto accept
|
||||
autoAccept = true;
|
||||
}
|
||||
|
||||
// Check if we can auto-accept because all users are locked
|
||||
if ((this.ws.httprequest.consentAutoAcceptIfLocked || this.ws.httprequest.consentAutoAcceptIfDesktopLocked) && (v.length > 0)) {
|
||||
var allUsersLocked = true;
|
||||
if (!meshCoreObj.lusers || meshCoreObj.lusers.length == 0) {
|
||||
// No locked users list available, assume users are not locked
|
||||
allUsersLocked = false;
|
||||
} else {
|
||||
for (var i in v) {
|
||||
var username = v[i].domain ? (v[i].domain + '\\' + v[i].user) : v[i].user;
|
||||
if (meshCoreObj.lusers.indexOf(username) == -1) {
|
||||
allUsersLocked = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allUsersLocked) { autoAccept = true; }
|
||||
}
|
||||
|
||||
if (autoAccept) {
|
||||
kvm_consent_ok(this.ws);
|
||||
} else {
|
||||
// User is present so we still need consent
|
||||
// User is present and not all locked, so we still need consent
|
||||
kvm_consent_ask(this.ws);
|
||||
}
|
||||
});
|
||||
@ -3257,10 +3317,7 @@ function onTunnelData(data)
|
||||
};
|
||||
|
||||
// Perform notification if needed. Toast messages may not be supported on all platforms.
|
||||
if (this.httprequest.consent && (this.httprequest.consent & 32))
|
||||
{
|
||||
// User asked for consent so now we check if we can auto accept if no user is present/loggedin
|
||||
if (this.httprequest.consentAutoAcceptIfNoUser) {
|
||||
if (this.httprequest.consentAutoAcceptIfNoUser || this.httprequest.consentAutoAcceptIfFileNoUser || this.httprequest.consentAutoAcceptIfLocked || this.httprequest.consentAutoAcceptIfFileLocked) {
|
||||
var p = require('user-sessions').enumerateUsers();
|
||||
p.sessionid = this.httprequest.sessionid;
|
||||
p.ws = this;
|
||||
@ -3269,19 +3326,40 @@ function onTunnelData(data)
|
||||
for (var i in u) {
|
||||
if (u[i].State == 'Active') { v.push({ tsid: i, type: u[i].StationName, user: u[i].Username, domain: u[i].Domain }); }
|
||||
}
|
||||
if (v.length == 0) { // No user is present, auto accept
|
||||
var autoAccept = false;
|
||||
|
||||
// Check if we should auto-accept because no user is present
|
||||
if ((this.ws.httprequest.consentAutoAcceptIfNoUser || this.ws.httprequest.consentAutoAcceptIfFileNoUser) && (v.length == 0)) {
|
||||
autoAccept = true;
|
||||
}
|
||||
|
||||
// Check if we should auto-accept because all users are locked
|
||||
if ((this.ws.httprequest.consentAutoAcceptIfLocked || this.ws.httprequest.consentAutoAcceptIfFileLocked) && (v.length > 0)) {
|
||||
var allUsersLocked = true;
|
||||
if (!meshCoreObj.lusers || meshCoreObj.lusers.length == 0) {
|
||||
// No locked users list available, assume users are not locked
|
||||
allUsersLocked = false;
|
||||
} else {
|
||||
for (var i in v) {
|
||||
var username = v[i].domain ? (v[i].domain + '\\' + v[i].user) : v[i].user;
|
||||
if (meshCoreObj.lusers.indexOf(username) == -1) {
|
||||
allUsersLocked = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allUsersLocked) { autoAccept = true; }
|
||||
}
|
||||
|
||||
if (autoAccept) {
|
||||
// User Consent Prompt is not required
|
||||
files_consent_ok(this.ws);
|
||||
} else {
|
||||
// User is present so we still need consent
|
||||
// User is present and not all locked, so we still need consent
|
||||
files_consent_ask(this.ws);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// User Consent Prompt is required
|
||||
files_consent_ask(this);
|
||||
}
|
||||
} else {
|
||||
// User Consent Prompt is not required
|
||||
files_consent_ok(this);
|
||||
}
|
||||
@ -5906,6 +5984,23 @@ function sendNetworkUpdate(force) {
|
||||
try {
|
||||
// Update the network interfaces information data
|
||||
var netInfo = { netif2: require('os').networkInterfaces() };
|
||||
if (process.platform == 'win32') {
|
||||
try {
|
||||
var ret = require('win-wmi').query('ROOT\\CIMV2', 'SELECT InterfaceIndex,NetConnectionID,Speed FROM Win32_NetworkAdapter', ['InterfaceIndex','NetConnectionID','Speed']);
|
||||
if (ret[0]) {
|
||||
var speedMap = {};
|
||||
for (var i = 0; i < ret.length; i++) speedMap[ret[i].InterfaceIndex] = ret[i].Speed;
|
||||
var adapterNames = Object.keys(netInfo.netif2);
|
||||
for (var j = 0; j < adapterNames.length; j++) {
|
||||
var interfaces = netInfo.netif2[adapterNames[j]];
|
||||
for (var k = 0; k < interfaces.length; k++) {
|
||||
var iface = interfaces[k], speed = speedMap[iface.index] || 0;
|
||||
iface.speed = parseInt(speed); // bits per seconds
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(ex) { }
|
||||
}
|
||||
if (netInfo.netif2) {
|
||||
netInfo.action = 'netinfo';
|
||||
var netInfoStr = JSON.stringify(netInfo);
|
||||
|
||||
@ -278,13 +278,13 @@
|
||||
"uk": {
|
||||
"allow": "Дозволити",
|
||||
"deny": "Відмовити",
|
||||
"autoAllowForFive": "Автоматично приймати всі підключення впродовж наступних 5 хвилин",
|
||||
"terminalConsent": "{0} запитує доступ до віддаленого терміналу. Надати доступ?",
|
||||
"desktopConsent": "{0} запитує віддалений доступ до стільниці. Надати доступ?",
|
||||
"fileConsent": "{0} запитує віддалений доступ до файлу. Надати доступ?",
|
||||
"terminalNotify": "{0} почав сеанс віддаленого терміналу.",
|
||||
"desktopNotify": "{0} розпочав сеанс віддаленої стільниці.",
|
||||
"fileNotify": "{0} розпочав віддалений файловий сеанс.",
|
||||
"privacyBar": "Поширити доступ до стільниці з: {0}"
|
||||
"autoAllowForFive": "Автоматично підтверджувати всі підключення впродовж наступних 5 хвилин",
|
||||
"terminalConsent": "{0} запитує дозвіл на віддалене використання вашого терміналу (командного рядка). Надати доступ?",
|
||||
"desktopConsent": "{0} запитує дозвіл на віддалений доступ до робочого столу. Надати доступ?",
|
||||
"fileConsent": "{0} запитує дозвіл на віддалене управління файлами. Надати доступ?",
|
||||
"terminalNotify": "{0} почав віддалено використовувати ваш термінал (командний рядок).",
|
||||
"desktopNotify": "{0} розпочав сеанс віддаленого робочого столу.",
|
||||
"fileNotify": "{0} почав віддалене управління вашими файлами.",
|
||||
"privacyBar": "Ви ділитесь робочим столом з: {0}"
|
||||
}
|
||||
}
|
||||
@ -775,9 +775,12 @@ module.exports.CreateAmtManager = function (parent) {
|
||||
});
|
||||
} else {
|
||||
// We got a bad response
|
||||
if ((dev.conntype != 0) && (dev.tlsfail !== true) && (status == 408)) { // If not using CIRA and we get a 408 error while using TLS, try non-TLS.
|
||||
if ((dev.connType != 0) && (dev.tlsfail !== false) && (status == 408)) { // If not using CIRA and we get a 408 error while using non-TLS, try TLS.
|
||||
// non-TLS error on a local connection, try again with TLS
|
||||
dev.tlsfail = false; dev.intelamt.tls = 1; attemptInitialContact(dev); return;
|
||||
} else if ((dev.connType != 0) && (dev.tlsfail !== true) && (status == 408)) { // If not using CIRA and we get a 408 error while using TLS, try non-TLS.
|
||||
// TLS error on a local connection, try again without TLS
|
||||
dev.tlsfail = true; attemptInitialContact(dev); return;
|
||||
dev.tlsfail = true; dev.intelamt.tls = 0; attemptInitialContact(dev); return;
|
||||
} else if (status == 401) {
|
||||
// Authentication error, see if we can use alternative credentials
|
||||
if (dev.acctry != null) {
|
||||
|
||||
@ -107,7 +107,7 @@ module.exports.CreateWebRelaySession = function (parent, db, req, args, domain,
|
||||
|
||||
// Check if any tunnels need to be cleaned up
|
||||
obj.checkTimeout = function () {
|
||||
const limit = Date.now() - (1 * 60 * 1000); // This is is 5 minutes before current time
|
||||
const limit = Date.now() - (5 * 60 * 1000); // This is 5 minutes before current time
|
||||
|
||||
// Close any old non-websocket tunnels
|
||||
const tunnelToRemove = [];
|
||||
@ -149,7 +149,7 @@ module.exports.CreateWebRelaySession = function (parent, db, req, args, domain,
|
||||
// Check to see if any of the tunnels are free
|
||||
var count = 0;
|
||||
for (var i in tunnels) {
|
||||
count += ((tunnels[i].isWebSocket || tunnels[i].isStreaming) ? 0 : 1);
|
||||
count += ((tunnels[i].isWebSocket || tunnels[i].isStreaming || (tunnels[i].res != null)) ? 0 : 1);
|
||||
if ((tunnels[i].relayActive == true) && (tunnels[i].res == null) && (tunnels[i].isWebSocket == false) && (tunnels[i].isStreaming == false)) {
|
||||
// Found a free tunnel, use it
|
||||
const x = pendingRequests.shift();
|
||||
@ -339,6 +339,9 @@ module.exports.CreateWebRelay = function (parent, db, args, domain, mtype) {
|
||||
var cookieStr = '';
|
||||
for (var i in parent.webCookies) { if (cookieStr != '') { cookieStr += '; ' } cookieStr += (i + '=' + parent.webCookies[i].value); }
|
||||
if (cookieStr.length > 0) { request += 'cookie: ' + cookieStr + '\r\n' } // If we have session cookies, set them in the header here
|
||||
var reqCookies = parseRequestCookies(req.headers.cookie);
|
||||
for (var i in reqCookies) { if ((i != 'xid') && (i != 'xid.sig')) { if (cookieStr != '') { cookieStr += '; ' } cookieStr += (i + '=' + reqCookies[i]); } }
|
||||
if (cookieStr.length > 0) { request += 'cookie: ' + cookieStr + '\r\n' } // If we have session cookies, set them in the header here
|
||||
request += '\r\n';
|
||||
send(Buffer.from(request));
|
||||
|
||||
|
||||
15
common.js
@ -419,4 +419,19 @@ module.exports.uniqueArray = function (a) {
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Replace placeholders in a string with values from an object or a function
|
||||
module.exports.replacePlaceholders = function (template, values) {
|
||||
return template.replace(/\{(\w+)\}/g, (match, key) => {
|
||||
if (typeof values === 'function') {
|
||||
return values(key);
|
||||
}
|
||||
else if (values && typeof values === 'object') {
|
||||
return values[key] !== undefined ? values[key] : match;
|
||||
}
|
||||
else {
|
||||
return values !== undefined ? values : match;
|
||||
}
|
||||
});
|
||||
}
|
||||
169
db.js
@ -261,6 +261,20 @@ module.exports.CreateDB = function (parent, func) {
|
||||
if (obj.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come.
|
||||
parent.DispatchEvent(targets, obj, event);
|
||||
}
|
||||
} else if (i.startsWith('ugrp/')) {
|
||||
var cusergroup = parent.userGroups[i];
|
||||
if ((cusergroup != null) && (cusergroup.links != null) && (cusergroup.links[node._id] != null)) {
|
||||
// Remove the user link & save the user
|
||||
delete cusergroup.links[node._id];
|
||||
if (Object.keys(cusergroup.links).length == 0) { delete cusergroup.links; }
|
||||
obj.Set(cusergroup);
|
||||
|
||||
// Notify user change
|
||||
var targets = ['*', 'server-users', cusergroup._id];
|
||||
var event = { etype: 'ugrp', ugrpid: cusergroup._id, name: cusergroup.name, desc: cusergroup.desc, action: 'usergroupchange', links: cusergroup.links, msgid: 163, msgArgs: [node.name, cusergroup.name], msg: 'Removed device ' + node.name + ' from user group ' + cusergroup.name };
|
||||
if (obj.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come.
|
||||
parent.DispatchEvent(targets, obj, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -919,7 +933,7 @@ module.exports.CreateDB = function (parent, func) {
|
||||
connectinArgs.database = 'postgres';
|
||||
DatastoreTest = new Client(connectinArgs);
|
||||
DatastoreTest.connect();
|
||||
|
||||
connectinArgs.database = databaseName; //put the name back for backupconfig info
|
||||
DatastoreTest.query('SELECT 1 FROM pg_catalog.pg_database WHERE datname = $1', [databaseName], function (err, res) { // check database exists first before creating
|
||||
if (res.rowCount != 0) { // database exists now check tables exists
|
||||
DatastoreTest.end();
|
||||
@ -936,7 +950,7 @@ module.exports.CreateDB = function (parent, func) {
|
||||
});
|
||||
} else { // If not present, create the tables and indexes
|
||||
//not needed, just use a create db statement: const pgtools = require('pgtools');
|
||||
DatastoreTest.query('CREATE DATABASE '+ databaseName + ';', [], function (err, res) {
|
||||
DatastoreTest.query('CREATE DATABASE "'+ databaseName + '";', [], function (err, res) {
|
||||
if (err == null) {
|
||||
// Create the tables and indexes
|
||||
DatastoreTest.end();
|
||||
@ -3192,6 +3206,7 @@ module.exports.CreateDB = function (parent, func) {
|
||||
if (parent.args.mongodbname) { dbname = parent.args.mongodbname; }
|
||||
else if ((typeof parent.args.mariadb == 'object') && (typeof parent.args.mariadb.database == 'string')) { dbname = parent.args.mariadb.database; }
|
||||
else if ((typeof parent.args.mysql == 'object') && (typeof parent.args.mysql.database == 'string')) { dbname = parent.args.mysql.database; }
|
||||
else if ((typeof parent.args.postgres == 'object') && (typeof parent.args.postgres.database == 'string')) { dbname = parent.args.postgres.database; }
|
||||
else if (typeof parent.config.settings.sqlite3 == 'string') {dbname = parent.config.settings.sqlite3 + '.sqlite'};
|
||||
|
||||
const currentDate = new Date();
|
||||
@ -3200,18 +3215,17 @@ module.exports.CreateDB = function (parent, func) {
|
||||
|
||||
r += 'DB Name: ' + dbname + '\r\n';
|
||||
r += 'DB Type: ' + DB_LIST[obj.databaseType] + '\r\n';
|
||||
r += 'BackupPath: ' + backupPath + '\r\n';
|
||||
r += 'BackupFile: ' + obj.newAutoBackupFile + '.zip\r\n';
|
||||
|
||||
if (parent.config.settings.autobackup == null) {
|
||||
r += 'No Settings/AutoBackup\r\n';
|
||||
if (parent.config.settings.autobackup.backupintervalhours == -1) {
|
||||
r += 'Backup disabled\r\n';
|
||||
} else {
|
||||
r += 'BackupPath: ' + backupPath + '\r\n';
|
||||
r += 'BackupFile: ' + obj.newAutoBackupFile + '.zip\r\n';
|
||||
|
||||
if (parent.config.settings.autobackup.backuphour != null && parent.config.settings.autobackup.backuphour != -1) {
|
||||
r += 'Backup between: ' + parent.config.settings.autobackup.backuphour + 'H-' + (parent.config.settings.autobackup.backuphour + 1) + 'H\r\n';
|
||||
}
|
||||
if (parent.config.settings.autobackup.backupintervalhours != null) {
|
||||
r += 'Backup Interval (Hours): ' + parent.config.settings.autobackup.backupintervalhours + '\r\n';
|
||||
}
|
||||
r += 'Backup Interval (Hours): ' + parent.config.settings.autobackup.backupintervalhours + '\r\n';
|
||||
if (parent.config.settings.autobackup.keeplastdaysbackup != null) {
|
||||
r += 'Keep Last Backups (Days): ' + parent.config.settings.autobackup.keeplastdaysbackup + '\r\n';
|
||||
}
|
||||
@ -3231,6 +3245,11 @@ module.exports.CreateDB = function (parent, func) {
|
||||
if (typeof parent.config.settings.autobackup.mysqldumppath != 'string') { r += 'Bad mysqldump type\r\n'; }
|
||||
else { r += parent.config.settings.autobackup.mysqldumppath + '\r\n'; }
|
||||
}
|
||||
if (parent.config.settings.autobackup.pgdumppath != null) {
|
||||
r += 'pgDump Path: ';
|
||||
if (typeof parent.config.settings.autobackup.pgdumppath != 'string') { r += 'Bad pgdump type\r\n'; }
|
||||
else { r += parent.config.settings.autobackup.pgdumppath + '\r\n'; }
|
||||
}
|
||||
if (parent.config.settings.autobackup.backupotherfolders) {
|
||||
r += 'Backup other folders: ';
|
||||
r += parent.filespath + ', ' + parent.recordpath + '\r\n';
|
||||
@ -3334,7 +3353,7 @@ module.exports.CreateDB = function (parent, func) {
|
||||
// Tries configured custom location with fallback to default location
|
||||
// Now runs after autobackup config init in meshcentral.js so config options are checked
|
||||
obj.checkBackupCapability = function (func) {
|
||||
if ((parent.config.settings.autobackup == null) || (parent.config.settings.autobackup == false)) { return; };
|
||||
if (parent.config.settings.autobackup.backupintervalhours == -1) { return; };
|
||||
//block backup until validated. Gets put back if all checks are ok.
|
||||
let backupInterval = parent.config.settings.autobackup.backupintervalhours;
|
||||
parent.config.settings.autobackup.backupintervalhours = -1;
|
||||
@ -3381,7 +3400,7 @@ module.exports.CreateDB = function (parent, func) {
|
||||
const child_process = require('child_process');
|
||||
child_process.exec(cmd, { cwd: backupPath }, function (error, stdout, stderr) {
|
||||
if ((error != null) && (error != '')) {
|
||||
func(1, "Mongodump error, backup will not be performed. Command tried: " + cmd + ' --> ERROR: ' + stderr);
|
||||
func(1, "Mongodump error, backup will not be performed. Check path or use mongodumppath & mongodumpargs");
|
||||
return;
|
||||
} else {parent.config.settings.autobackup.backupintervalhours = backupInterval;}
|
||||
});
|
||||
@ -3392,7 +3411,7 @@ module.exports.CreateDB = function (parent, func) {
|
||||
const child_process = require('child_process');
|
||||
child_process.exec(cmd, { cwd: backupPath, timeout: 1000*30 }, function(error, stdout, stdin) {
|
||||
if ((error != null) && (error != '')) {
|
||||
func(1, "Unable to find mysqldump tool, backup will not be performed. Command tried: " + cmd);
|
||||
func(1, "mysqldump error, backup will not be performed. Check path or use mysqldumppath");
|
||||
return;
|
||||
} else {parent.config.settings.autobackup.backupintervalhours = backupInterval;}
|
||||
|
||||
@ -3401,13 +3420,13 @@ module.exports.CreateDB = function (parent, func) {
|
||||
// Check that we have access to pg_dump
|
||||
parent.config.settings.autobackup.pgdumppath = path.normalize(parent.config.settings.autobackup.pgdumppath ? parent.config.settings.autobackup.pgdumppath : 'pg_dump');
|
||||
let cmd = '"' + parent.config.settings.autobackup.pgdumppath + '"'
|
||||
+ ' --dbname=postgresql://' + parent.config.settings.postgres.user + ":" +parent.config.settings.postgres.password
|
||||
+ "@" + parent.config.settings.postgres.host + ":" + parent.config.settings.postgres.port + "/" + databaseName
|
||||
+ ' --dbname=postgresql://' + encodeURIComponent(parent.config.settings.postgres.user) + ":" + encodeURIComponent(parent.config.settings.postgres.password)
|
||||
+ "@" + parent.config.settings.postgres.host + ":" + parent.config.settings.postgres.port + "/" + encodeURIComponent(databaseName)
|
||||
+ ' > ' + ((parent.platform == 'win32') ? '\"nul\"' : '\"/dev/null\"');
|
||||
const child_process = require('child_process');
|
||||
child_process.exec(cmd, { cwd: backupPath }, function(error, stdout, stdin) {
|
||||
if ((error != null) && (error != '')) {
|
||||
func(1, "Unable to find pg_dump tool, backup will not be performed. Command tried: " + cmd);
|
||||
func(1, "pg_dump error, backup will not be performed. Check path or use pgdumppath.");
|
||||
return;
|
||||
} else {parent.config.settings.autobackup.backupintervalhours = backupInterval;}
|
||||
});
|
||||
@ -3595,11 +3614,11 @@ module.exports.CreateDB = function (parent, func) {
|
||||
});
|
||||
} else if (obj.databaseType == DB_POSTGRESQL) {
|
||||
// Perform a PostgresDump backup
|
||||
const newBackupFile = databaseName + '-pgdump-' + fileSuffix + '.sql';
|
||||
const newBackupFile = 'pgdump-' + fileSuffix + '.sql';
|
||||
obj.newDBDumpFile = path.join(backupPath, newBackupFile);
|
||||
let cmd = '"' + parent.config.settings.autobackup.pgdumppath + '"'
|
||||
+ ' --dbname=postgresql://' + parent.config.settings.postgres.user + ":" +parent.config.settings.postgres.password
|
||||
+ "@" + parent.config.settings.postgres.host + ":" + parent.config.settings.postgres.port + "/" + databaseName
|
||||
+ ' --dbname=postgresql://' + encodeURIComponent(parent.config.settings.postgres.user) + ":" + encodeURIComponent(parent.config.settings.postgres.password)
|
||||
+ "@" + parent.config.settings.postgres.host + ":" + parent.config.settings.postgres.port + "/" + encodeURIComponent(databaseName)
|
||||
+ " --file=" + obj.newDBDumpFile;
|
||||
parent.debug('backup','Postgresqldump cmd: ' + cmd);
|
||||
const child_process = require('child_process');
|
||||
@ -3780,84 +3799,50 @@ module.exports.CreateDB = function (parent, func) {
|
||||
}
|
||||
}
|
||||
|
||||
async function webDAVBackup(filename, func) {
|
||||
try {
|
||||
const webDAV = await import ('webdav');
|
||||
const wdConfig = parent.config.settings.autobackup.webdav;
|
||||
const client = webDAV.createClient(wdConfig.url, {
|
||||
username: wdConfig.username,
|
||||
password: wdConfig.password,
|
||||
maxContentLength: Infinity,
|
||||
maxBodyLength: Infinity
|
||||
});
|
||||
if (await client.exists(wdConfig.foldername) === false) {
|
||||
await client.createDirectory(wdConfig.foldername, { recursive: true});
|
||||
} else {
|
||||
// Clean up our WebDAV folder
|
||||
if ((typeof wdConfig.maxfiles == 'number') && (wdConfig.maxfiles > 1)) {
|
||||
const fileName = parent.config.settings.autobackup.backupname;
|
||||
//only files matching our backupfilename
|
||||
let files = await client.getDirectoryContents(wdConfig.foldername, { deep: false, glob: "/**/" + fileName + "*.zip" });
|
||||
const xdateTimeSort = function (a, b) { if (a.xdate > b.xdate) return 1; if (a.xdate < b.xdate) return -1; return 0; }
|
||||
for (const i in files) { files[i].xdate = new Date(files[i].lastmod); }
|
||||
files.sort(xdateTimeSort);
|
||||
while (files.length >= wdConfig.maxfiles) {
|
||||
let delFile = files.shift().filename;
|
||||
await client.deleteFile(delFile);
|
||||
console.log('WebDAV file deleted: ' + delFile); if (func) { func('WebDAV file deleted: ' + delFile); }
|
||||
}
|
||||
}
|
||||
}
|
||||
// Upload to the WebDAV folder
|
||||
const { pipeline } = require('stream/promises');
|
||||
await pipeline(fs.createReadStream(filename), client.createWriteStream( wdConfig.foldername + path.basename(filename)));
|
||||
console.log('WebDAV upload completed: ' + wdConfig.foldername + path.basename(filename)); if (func) { func('WebDAV upload completed: ' + wdConfig.foldername + path.basename(filename)); }
|
||||
}
|
||||
catch(err) {
|
||||
console.error('WebDAV error: ' + err.message); if (func) { func('WebDAV error: ' + err.message);}
|
||||
}
|
||||
}
|
||||
|
||||
// Perform cloud backup
|
||||
obj.performCloudBackup = function (filename, func) {
|
||||
// WebDAV Backup
|
||||
if ((typeof parent.config.settings.autobackup == 'object') && (typeof parent.config.settings.autobackup.webdav == 'object')) {
|
||||
parent.debug( 'backup', 'Entering WebDAV backup');
|
||||
if (func) { func('Entering WebDAV backup.'); }
|
||||
|
||||
const xdateTimeSort = function (a, b) { if (a.xdate > b.xdate) return 1; if (a.xdate < b.xdate) return -1; return 0; }
|
||||
// Fetch the folder name
|
||||
var webdavfolderName = 'MeshCentral-Backups';
|
||||
if (typeof parent.config.settings.autobackup.webdav.foldername == 'string') { webdavfolderName = parent.config.settings.autobackup.webdav.foldername; }
|
||||
|
||||
// Clean up our WebDAV folder
|
||||
function performWebDavCleanup(client) {
|
||||
if ((typeof parent.config.settings.autobackup.webdav.maxfiles == 'number') && (parent.config.settings.autobackup.webdav.maxfiles > 1)) {
|
||||
let fileName = parent.config.settings.autobackup.backupname;
|
||||
//only files matching our backupfilename
|
||||
let directoryItems = client.getDirectoryContents(webdavfolderName, { deep: false, glob: "/**/" + fileName + "*.zip" });
|
||||
directoryItems.then(
|
||||
function (files) {
|
||||
for (var i in files) { files[i].xdate = new Date(files[i].lastmod); }
|
||||
files.sort(xdateTimeSort);
|
||||
parent.debug('backup','WebDAV filtered directory contents: ' + JSON.stringify(files, null, 4));
|
||||
while (files.length >= parent.config.settings.autobackup.webdav.maxfiles) {
|
||||
let delFile = files.shift().filename;
|
||||
client.deleteFile(delFile).then(function (state) {
|
||||
parent.debug('backup','WebDAV file deleted: ' + delFile);
|
||||
if (func) { func('WebDAV file deleted: ' + delFile); }
|
||||
}).catch(function (err) {
|
||||
console.error(err);
|
||||
if (func) { func('WebDAV (deleteFile) error: ' + err.message); }
|
||||
});
|
||||
}
|
||||
}
|
||||
).catch(function (err) {
|
||||
console.error(err);
|
||||
if (func) { func('WebDAV (getDirectoryContents) error: ' + err.message); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Upload to the WebDAV folder
|
||||
function performWebDavUpload(client, filepath) {
|
||||
require('fs').stat(filepath, function(err,stat){
|
||||
var fileStream = require('fs').createReadStream(filepath);
|
||||
fileStream.on('close', function () { console.log('WebDAV upload completed: ' + webdavfolderName + '/' + require('path').basename(filepath)); if (func) { func('WebDAV upload completed: ' + webdavfolderName + '/' + require('path').basename(filepath)); } })
|
||||
fileStream.on('error', function (err) { console.error(err); if (func) { func('WebDAV (fileUpload) error: ' + err.message); } })
|
||||
fileStream.pipe(client.createWriteStream('/' + webdavfolderName + '/' + require('path').basename(filepath), { headers: { "Content-Length": stat.size } }));
|
||||
parent.debug('backup', 'Uploading using WebDAV to: ' + parent.config.settings.autobackup.webdav.url);
|
||||
if (func) { func('Uploading using WebDAV to: ' + parent.config.settings.autobackup.webdav.url); }
|
||||
});
|
||||
}
|
||||
|
||||
const { createClient } = require('webdav');
|
||||
const client = createClient(parent.config.settings.autobackup.webdav.url, {
|
||||
username: parent.config.settings.autobackup.webdav.username,
|
||||
password: parent.config.settings.autobackup.webdav.password,
|
||||
maxContentLength: Infinity,
|
||||
maxBodyLength: Infinity
|
||||
});
|
||||
client.exists(webdavfolderName).then(function(a){
|
||||
if(a){
|
||||
performWebDavCleanup(client);
|
||||
performWebDavUpload(client, filename);
|
||||
}else{
|
||||
client.createDirectory(webdavfolderName, {recursive: true}).then(function (a) {
|
||||
console.log('backup','WebDAV folder created: ' + webdavfolderName);
|
||||
if (func) { func('WebDAV folder created: ' + webdavfolderName); }
|
||||
performWebDavUpload(client, filename);
|
||||
}).catch(function (err) {
|
||||
console.error(err);
|
||||
if (func) { func('WebDAV (createDirectory) error: ' + err.message); }
|
||||
});
|
||||
}
|
||||
}).catch(function (err) {
|
||||
console.error(err);
|
||||
if (func) { func('WebDAV (exists) error: ' + err.message); }
|
||||
});
|
||||
parent.debug( 'backup', 'Entering WebDAV backup'); if (func) { func('Entering WebDAV backup.'); }
|
||||
webDAVBackup(filename, func);
|
||||
}
|
||||
|
||||
// Google Drive Backup
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
"@seald-io/nedb": "4.0.4",
|
||||
"@seald-io/nedb": "4.1.2",
|
||||
"archiver": "7.0.1",
|
||||
"body-parser": "1.20.3",
|
||||
"cbor": "5.2.0",
|
||||
"compression": "1.7.5",
|
||||
"cookie-session": "2.1.0",
|
||||
"compression": "1.8.1",
|
||||
"cookie-session": "2.1.1",
|
||||
"express": "4.21.2",
|
||||
"express-handlebars": "7.1.3",
|
||||
"express-ws": "5.0.2",
|
||||
@ -11,7 +11,8 @@
|
||||
"minimist": "1.2.8",
|
||||
"multiparty": "4.2.3",
|
||||
"node-forge": "1.3.1",
|
||||
"ua-parser-js": "1.0.40",
|
||||
"otplib": "12.0.1",
|
||||
"ua-client-hints-js": "0.1.2",
|
||||
"ws": "8.18.0",
|
||||
"ua-parser-js": "1.0.40",
|
||||
"ws": "8.18.3",
|
||||
"yauzl": "2.10.0"
|
||||
@ -1,29 +0,0 @@
|
||||
# How to create a docker image for meshcentral
|
||||
|
||||
```
|
||||
> git clone https://github.com/Ylianst/MeshCentral.git
|
||||
> cd MeshCentral
|
||||
|
||||
> docker build -f docker/Dockerfile --force-rm -t meshcentral .
|
||||
|
||||
# alternative, if you want to include the mongodb-tools (mongodump, ...), you can add the 'INCLUDE_MONGODBTOOLS=yes' build argument
|
||||
> docker build -f docker/Dockerfile --force-rm --build-arg INCLUDE_MONGODBTOOLS=yes -t meshcentral .
|
||||
|
||||
# (optional) cleanup after docker build:
|
||||
> cd ..
|
||||
> rm -rf MeshCentral/
|
||||
```
|
||||
|
||||
> | Argument | Description |
|
||||
> | :--- | :--- |
|
||||
> | -f docker/Dockerfile | Path/Name of the Dockerfile |
|
||||
> | --force-rm | Always remove intermediate containers |
|
||||
> | -t meshcentral | Name and optionally a tag in the 'name:tag' format |
|
||||
|
||||
### Optional build arguments
|
||||
> | Argument | Description |
|
||||
> | :--- | :--- |
|
||||
> | INCLUDE_MONGODBTOOLS=yes | Includes mongodb-tools (mongodump, ...) in the image |
|
||||
> | DISABLE_MINIFY=yes | Disables the minification of files |
|
||||
> | DISABLE_TRANSLATE=yes | Disables the translation of files |
|
||||
|
||||
@ -1,103 +1,213 @@
|
||||
FROM --platform=$BUILDPLATFORM node:22-alpine AS builder
|
||||
### STAGE 1 BUILDING.
|
||||
FROM node:lts-alpine3.22 AS builder
|
||||
|
||||
# Any value inside one of the disable ARGs will be accepted.
|
||||
ARG DISABLE_EXTRACT="yes"
|
||||
ARG DISABLE_MINIFY="yes"
|
||||
ARG DISABLE_TRANSLATE="yes"
|
||||
# NODE_OPTIONS="--max_old_space_size=4096"
|
||||
# If your process gets OOM killed, perhaps the above will help.
|
||||
|
||||
RUN mkdir -p /opt/meshcentral/meshcentral
|
||||
WORKDIR /opt/meshcentral
|
||||
COPY ./ /opt/meshcentral/meshcentral/
|
||||
WORKDIR /opt/meshcentral
|
||||
|
||||
ARG DISABLE_MINIFY=""
|
||||
ARG DISABLE_TRANSLATE=""
|
||||
|
||||
|
||||
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; \
|
||||
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; \
|
||||
# Check the Docker build arguments and if they are empty do the task.
|
||||
RUN if [ -n "$DISABLE_EXTRACT" ] || [ -n "$DISABLE_MINIFY" ] || [ -n "$DISABLE_TRANSLATE" ]; then \
|
||||
echo -e "----------\nPREPARING ENVIRONMENT...\n----------"; \
|
||||
cd meshcentral && \
|
||||
npm install html-minifier-terser@7.2.0 jsdom@26.0.0 esprima@4.0.1 && \
|
||||
cd translate && \
|
||||
case "$DISABLE_EXTRACT" in \
|
||||
false|no|FALSE|NO) \
|
||||
echo -e "----------\nSTARTING THE EXTRACTING PROCESS...\n----------"; \
|
||||
node translate.js extractall;; \
|
||||
*) \
|
||||
echo "Setting EXTRACT as disabled.";; \
|
||||
esac && \
|
||||
case "$DISABLE_MINIFY" in \
|
||||
false|no|FALSE|NO) \
|
||||
echo -e "----------\nSTARTING THE MINIFYING PROCESS...\n----------"; \
|
||||
node translate.js minifyall;; \
|
||||
*) \
|
||||
echo "Setting MINIFY as disabled.";; \
|
||||
esac && \
|
||||
case "$DISABLE_TRANSLATE" in \
|
||||
false|no|FALSE|NO) \
|
||||
echo -e "----------\nSTARTING THE TRANSLATING PROCESS...\n----------"; \
|
||||
node translate.js translateall;; \
|
||||
*) \
|
||||
echo "Setting TRANSLATE as disabled.";; \
|
||||
esac; \
|
||||
npm uninstall html-minifier-terser jsdom esprima; \
|
||||
fi
|
||||
# Possible more updated alternative? @minify-html/node@0.15.0 -> https://www.npmjs.com/package/@minify-html/node
|
||||
|
||||
# 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
|
||||
RUN rm -rf /opt/meshcentral/meshcentral/docker /opt/meshcentral/meshcentral/node_modules /opt/meshcentral/meshcentral/docs
|
||||
|
||||
# first extractall if need too
|
||||
RUN if [ -z "$DISABLE_MINIFY" ] || [ -z "$DISABLE_TRANSLATE" ]; then cd meshcentral/translate && node translate.js extractall; fi
|
||||
### STAGE 2 PRECOMPILE DEPS MODULE
|
||||
|
||||
# minify files
|
||||
RUN if [ -z "$DISABLE_MINIFY" ]; then cd meshcentral/translate && node translate.js minifyall; fi
|
||||
FROM alpine:3.22 AS dep-compiler
|
||||
|
||||
# translate
|
||||
RUN if [ -z "$DISABLE_TRANSLATE" ]; then cd meshcentral/translate && node translate.js translateall; fi
|
||||
RUN apk update && \
|
||||
echo -e "----------\nINSTALLING ALPINE PACKAGES...\n----------"; \
|
||||
apk add --no-cache --update \
|
||||
bash gcc g++ jq make nodejs npm python3 tzdata
|
||||
|
||||
# cleanup
|
||||
RUN if [ -z "$DISABLE_MINIFY" ] || [ -z "$DISABLE_TRANSLATE" ]; then cd meshcentral && npm remove html-minifier jsdom esprima; fi
|
||||
RUN rm -rf /opt/meshcentral/meshcentral/docker
|
||||
RUN rm -rf /opt/meshcentral/meshcentral/node_modules
|
||||
COPY --from=builder /opt/meshcentral/meshcentral /opt/meshcentral/meshcentral
|
||||
WORKDIR /opt/meshcentral/meshcentral
|
||||
|
||||
RUN jq '.dependencies += {"modern-syslog": "1.2.0", "telegram": "2.26.22"}' package.json > temp.json && mv temp.json package.json \
|
||||
&& npm i --package-lock-only \
|
||||
&& npm ci
|
||||
|
||||
FROM --platform=$TARGETPLATFORM alpine:3.21
|
||||
### STAGE 3 RUNTIME
|
||||
|
||||
#Add non-root user, add installation directories and assign proper permissions
|
||||
RUN mkdir -p /opt/meshcentral/meshcentral
|
||||
FROM alpine:3.22 AS runtime
|
||||
|
||||
# meshcentral installation
|
||||
WORKDIR /opt/meshcentral
|
||||
|
||||
RUN apk update \
|
||||
&& apk add --no-cache --update tzdata nodejs npm bash python3 make gcc g++ \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
RUN npm install -g npm@latest
|
||||
|
||||
ARG INCLUDE_MONGODBTOOLS=""
|
||||
ARG PREINSTALL_LIBS="false"
|
||||
# # Copy prepared app from builder stage
|
||||
COPY --from=dep-compiler /opt/meshcentral/meshcentral /opt/meshcentral/meshcentral
|
||||
|
||||
# environment variables
|
||||
ENV NODE_ENV="production"
|
||||
ENV CONFIG_FILE="config.json"
|
||||
ENV NODE_ENV="production" \
|
||||
CONFIG_FILE="/opt/meshcentral/meshcentral-data/config.json" \
|
||||
DYNAMIC_CONFIG="false"
|
||||
|
||||
# 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"
|
||||
ENV ALLOWPLUGINS="false"
|
||||
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"
|
||||
# environment variables for the above defined MeshCentral Config.json. Can be done like that following: https://docs.docker.com/reference/dockerfile/#env
|
||||
ENV ALLOW_PLUGINS="false" \
|
||||
ALLOW_NEW_ACCOUNTS="false" \
|
||||
ALLOWED_ORIGIN="false" \
|
||||
IFRAME="false" \
|
||||
REGEN_SESSIONKEY="false" \
|
||||
WEBRTC="false" \
|
||||
LOCAL_SESSION_RECORDING="true" \
|
||||
MINIFY="true" \
|
||||
HOSTNAME="localhost" \
|
||||
REVERSE_PROXY="" \
|
||||
REVERSE_PROXY_TLS_PORT="443" \
|
||||
TRUSTED_PROXY="" \
|
||||
ARGS=""
|
||||
|
||||
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
|
||||
# Database
|
||||
# Multi-variable declaration to reduce layers.
|
||||
ENV USE_MONGODB="false" \
|
||||
USE_POSTGRESQL="false" \
|
||||
USE_MARIADB="false"
|
||||
|
||||
RUN if ! [ -z "$INCLUDE_MONGODBTOOLS" ]; then apk add --no-cache mongodb-tools; fi
|
||||
# Preinstallation args one per line due to: https://docs.docker.com/reference/dockerfile/#arg
|
||||
ARG PREINSTALL_LIBS="false"
|
||||
ARG INCLUDE_MONGODB_TOOLS="false"
|
||||
ARG INCLUDE_POSTGRESQL_TOOLS="false"
|
||||
ARG INCLUDE_MARIADB_TOOLS="false"
|
||||
|
||||
# copy files from builder-image
|
||||
COPY --from=builder /opt/meshcentral/meshcentral /opt/meshcentral/meshcentral
|
||||
COPY ./docker/startup.sh ./startup.sh
|
||||
COPY ./docker/config.json.template /opt/meshcentral/config.json.template
|
||||
# MongoDB Variables
|
||||
# The following MONGO_URL variable overwrites most other mongoDb related varialbes.
|
||||
ENV MONGO_HOST="" \
|
||||
MONGO_PORT="27017" \
|
||||
MONGO_USERNAME="" \
|
||||
MONGO_PASS="" \
|
||||
MONGO_URL=""
|
||||
|
||||
# PostgreSQL Variables
|
||||
ENV PSQL_HOST="" \
|
||||
PSQL_PORT="5432" \
|
||||
PSQL_USER="" \
|
||||
PSQL_PASS="" \
|
||||
PSQL_DATABASE=""
|
||||
|
||||
# MariaDB/MySQL Variables, Alpine Linux only provides the actual MariaDB binaries.
|
||||
ENV MARIADB_HOST="" \
|
||||
MARIADB_PORT="3306" \
|
||||
MARIADB_USER="" \
|
||||
MARIADB_PASS="" \
|
||||
MARIADB_DATABASE=""
|
||||
|
||||
WORKDIR /opt/meshcentral
|
||||
|
||||
RUN apk update && \
|
||||
echo -e "----------\nINSTALLING ALPINE PACKAGES...\n----------"; \
|
||||
apk add --no-cache --update \
|
||||
bash curl jq nodejs npm tzdata && \
|
||||
rm -rf /var/cache/* \
|
||||
/tmp/* \
|
||||
/usr/share/man/ \
|
||||
/usr/share/doc/ \
|
||||
/var/log/* \
|
||||
/var/spool/* \
|
||||
/usr/lib/debug/ && \
|
||||
npm install -g npm@latest
|
||||
|
||||
RUN case "$PREINSTALL_LIBS" in \
|
||||
true|yes|TRUE|YES) \
|
||||
cd meshcentral && \
|
||||
echo -e "----------\nPREINSTALLING LIBRARIES...\n----------"; \
|
||||
npm install ssh2@1.16.0 nodemailer@6.10.1 image-size@2.0.2 wildleek@2.0.0 otplib@12.0.1 yub@0.11.1;; \
|
||||
false|no|FALSE|NO) \
|
||||
echo "Not pre-installing libraries.";; \
|
||||
*) \
|
||||
echo -e "Invalid value for build argument INCLUDE_POSTGRESQL_TOOLS, possible values: 'yes', 'true', 'no' or 'false'"; \
|
||||
exit 1;; \
|
||||
esac
|
||||
|
||||
# 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 && \
|
||||
echo -e "----------\nPREINSTALLING MONGODB LIBRARIES...\n----------"; \
|
||||
npm install mongodb@4.17.2 @mongodb-js/saslprep@1.3.1;; \
|
||||
false|no|FALSE|NO) \
|
||||
echo "Not including MongoDB Tools.";; \
|
||||
*) \
|
||||
echo "Invalid value for build argument INCLUDE_MONGODB_TOOLS, possible values: 'yes', 'true', 'no' or 'false'"; \
|
||||
exit 1;; \
|
||||
esac
|
||||
|
||||
RUN case "$INCLUDE_POSTGRESQL_TOOLS" in \
|
||||
true|yes|TRUE|YES) \
|
||||
apk add --no-cache postgresql-client && \
|
||||
cd meshcentral && \
|
||||
echo -e "----------\nPREINSTALLING POSTGRESQL LIBRARIES...\n----------"; \
|
||||
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', 'true', 'no' or 'false'"; \
|
||||
exit 1;; \
|
||||
esac
|
||||
|
||||
RUN case "$INCLUDE_MARIADB_TOOLS" in \
|
||||
true|yes|TRUE|YES) \
|
||||
apk add --no-cache mariadb-client && \
|
||||
cd meshcentral && \
|
||||
echo -e "----------\nPREINSTALLING MARIADB/MYSQL LIBRARIES...\n----------"; \
|
||||
npm install mariadb@3.4.0 mysql2@3.11.4;; \
|
||||
false|no|FALSE|NO) \
|
||||
echo "Not including MariaDB/MySQL Tools.";; \
|
||||
*) \
|
||||
echo -e "Invalid value for build argument INCLUDE_MARIADB_TOOLS, possible values: 'yes', 'true', 'no' or 'false'"; \
|
||||
exit 1;; \
|
||||
esac
|
||||
|
||||
# install dependencies from package.json
|
||||
RUN cd meshcentral && npm install
|
||||
RUN cd meshcentral && \
|
||||
npm cache clean --force && \
|
||||
rm -rf /root/ /tmp/
|
||||
|
||||
# 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.17.2; 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.2.1 wildleek@2.0.0 otplib@12.0.1 yubikeyotp@0.2.0; fi
|
||||
# Expose needed ports
|
||||
EXPOSE 80 443
|
||||
|
||||
EXPOSE 80 443 4433
|
||||
|
||||
# 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
|
||||
|
||||
CMD ["bash", "/opt/meshcentral/startup.sh"]
|
||||
# Copy images from Git repo, place it before ending so recompilation can make good use of cache.
|
||||
COPY ./docker/entrypoint.sh /opt/meshcentral/entrypoint.sh
|
||||
COPY ./docker/config.json.template /opt/meshcentral/config.json.template
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
|
||||
CMD curl -k --fail https://localhost:443/health.ashx || exit 1
|
||||
|
||||
ENTRYPOINT ["bash", "/opt/meshcentral/entrypoint.sh"]
|
||||
|
||||
234
docker/README.md
Normal file
@ -0,0 +1,234 @@
|
||||
# MeshCentral Docker Configuration Guide
|
||||
|
||||
> [!NOTE]
|
||||
> Out of precaution, DYNAMIC_CONFIG has been disabled by default.<br>
|
||||
> The reason why is because when its enabled and a working config without corresponding environment variables gives,<br>
|
||||
> Then the container will overwrite it to a incorrect, but working state - perhaps non-working for your environment.
|
||||
|
||||
## Overview
|
||||
This document provides a comprehensive guide to setting up and configuring MeshCentral in a Docker environment.<br>
|
||||
It includes available options, security measures, and deployment instructions.
|
||||
|
||||
MeshCentral provides a couple different Docker container variants:<br>
|
||||
These variants are pulled through 3 main channels: `master` and `latest`.<br>
|
||||
If you want to target versions, you can also target individual versions; such as `1.1.53`.
|
||||
|
||||
| Variant | Image tag | Full path |
|
||||
|---------|-----------|-----------|
|
||||
| All database backends | "" (empty) | ghcr.io/ylianst/meshcentral:\<version\> |
|
||||
| No database backens (local only) | slim | ghcr.io/ylianst/meshcentral:\<version\>-slim |
|
||||
| [MongoDB](https://www.mongodb.com/) backend included | mongodb | ghcr.io/ylianst/meshcentral:\<version\>-mongodb |
|
||||
| [PostgreSQL](https://www.postgresql.org/) backend included | postgresql | ghcr.io/ylianst/meshcentral:\<version\>-postgresql |
|
||||
| [Mysql](https://www.mysql.com/)/[MariaDB](https://mariadb.org/) backend(s) included | mysql | ghcr.io/ylianst/meshcentral:\<version\>-mysql |
|
||||
|
||||
So for a quick example: if you want to get the bleeding edge code with a PostgreSQL backend: `ghcr.io/ylianst/meshcentral:master-postgresql`<br>
|
||||
So for another quick example: if you want to get a complete image at the latest released version: `ghcr.io/ylianst/meshcentral:latest`<br>
|
||||
So for another quick example: if you want to get a released version with a MongoDB backend: `ghcr.io/ylianst/meshcentral:latest-mongodb`<br>
|
||||
So for another quick example: if you want a very slim image with the latest code and only a local database: `ghcr.io/ylianst/meshcentral:master-slim`<br>
|
||||
So as a last example: if you want to get a MariaDB/MySQL backend with MeshCentral version 1.1.53: `ghcr.io/ylianst/meshcentral:1.1.53-mysql`
|
||||
|
||||
## 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 | false | Enables/disables dynamic configuration. This means config is being rechecked every container restart. False if you want to use your own `config.json` |
|
||||
| ALLOW_PLUGINS | 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. |
|
||||
| LOCAL_SESSION_RECORDING | true | Enables session recording. |
|
||||
| MINIFY | true | Minifies the JavaScript and HTML output. |
|
||||
| REGEN_SESSIONKEY | 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_URL=mongodb://username:password@mongodb:27017/meshcentral \
|
||||
-v meshcentral-data:/opt/meshcentral/meshcentral-data \
|
||||
-p 443:443 \
|
||||
ghcr.io/ylianst/meshcentral:latest # or latest-mongodb
|
||||
```
|
||||
|
||||
### Running with Docker Compose
|
||||
```yaml
|
||||
services:
|
||||
meshcentral:
|
||||
image: ghcr.io/ylianst/meshcentral:latest
|
||||
environment:
|
||||
- HOSTNAME=myserver.domain.com
|
||||
- ALLOW_NEW_ACCOUNTS=false
|
||||
- USE_MONGODB=true
|
||||
- MONGO_URL=mongodb://username:password@mongodb:27017/meshcentral
|
||||
volumes:
|
||||
- meshcentral-data:/opt/meshcentral/meshcentral-data
|
||||
- meshcentral-files:/opt/meshcentral/meshcentral-files
|
||||
- meshcentral-web:/opt/meshcentral/meshcentral-web
|
||||
- meshcentral-backups:/opt/meshcentral/meshcentral-backups
|
||||
ports:
|
||||
# You can add additional ports here in the same format. Such as for AMT or HTTP
|
||||
- "443:443"
|
||||
volumes:
|
||||
meshcentral-data:
|
||||
meshcentral-files:
|
||||
meshcentral-web:
|
||||
meshcentral-backups:
|
||||
```
|
||||
|
||||
### Using an `.env` File
|
||||
Create a `.env` file:
|
||||
```ini
|
||||
# Environment variables
|
||||
NODE_ENV=production
|
||||
CONFIG_FILE=/opt/meshcentral/meshcentral-data/config.json
|
||||
DYNAMIC_CONFIG=true
|
||||
|
||||
# MeshCentral Configuration
|
||||
ALLOW_PLUGINS=false
|
||||
ALLOW_NEW_ACCOUNTS=false
|
||||
ALLOWED_ORIGIN=false
|
||||
ARGS=
|
||||
HOSTNAME=localhost
|
||||
IFRAME=false
|
||||
LOCAL_SESSION_RECORDING=true
|
||||
MINIFY=true
|
||||
REGEN_SESSIONKEY=false
|
||||
REVERSE_PROXY=
|
||||
REVERSE_PROXY_TLS_PORT=
|
||||
WEBRTC=false
|
||||
|
||||
# MongoDB Configuration
|
||||
USE_MONGODB=false
|
||||
MONGO_HOST=
|
||||
MONGO_PORT=27017
|
||||
MONGO_USERNAME=
|
||||
MONGO_PASS=
|
||||
MONGO_URL=
|
||||
|
||||
# PostgreSQL Configuration
|
||||
USE_POSTGRESQL=false
|
||||
PSQL_HOST=
|
||||
PSQL_PORT=5432
|
||||
PSQL_USER=
|
||||
PSQL_PASS=
|
||||
PSQL_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 -f ./docker/compose.yaml --env-file .env up -d
|
||||
```
|
||||
|
||||
# Custom healthchecks at runtime
|
||||
|
||||
If you want to add a custom healthcheck post-compilation/with precompiled images, then do the following:<br>
|
||||
This all is based on [Docker documentation](https://docs.docker.com/reference/compose-file/services/).
|
||||
|
||||
Add the following lines to your compose.yaml:
|
||||
```yaml
|
||||
services:
|
||||
meshcentral:
|
||||
image: ghcr.io/ylianst/meshcentral:latest
|
||||
...
|
||||
<the rest of the compose.yaml>
|
||||
...
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-k", "--fail", "https://localhost:443/health.ashx"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
start_period: 5s
|
||||
retries: 3
|
||||
```
|
||||
|
||||
And if you ever change the port on which MeshCentral *INTERNALLY* runs on please also change the healthcheck either in your compose or self-compiled Dockerfile.<br>
|
||||
Also relevant if you change scheme, such as HTTP to HTTPS or vice versa.
|
||||
|
||||
# MeshCentral Docker Build Process
|
||||
|
||||
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`, `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:
|
||||
> While in the root git location.
|
||||
|
||||
```sh
|
||||
docker build -f docker/Dockerfile --build-arg DISABLE_MINIFY=no --build-arg DISABLE_TRANSLATE=no -t meshcentral .
|
||||
```
|
||||
22
docker/compose.yaml
Normal file
@ -0,0 +1,22 @@
|
||||
services:
|
||||
meshcentral:
|
||||
image: ghcr.io/ylianst/meshcentral:latest
|
||||
environment:
|
||||
- DYNAMIC_CONFIG=false # Show the option but disable it by default, for safety.
|
||||
- HOSTNAME=myserver.domain.com # Set the hostname in the config.json
|
||||
- ALLOW_NEW_ACCOUNTS=false # Disable creation of new accounts (except for the first user) in the config.json
|
||||
- USE_MONGODB=true # Enable the Mongo connector in the config.json
|
||||
- MONGO_URL=mongodb://username:password@mongodb:27017/meshcentral # Example MONGO_URL
|
||||
volumes:
|
||||
- meshcentral-data:/opt/meshcentral/meshcentral-data
|
||||
- meshcentral-files:/opt/meshcentral/meshcentral-files
|
||||
- meshcentral-web:/opt/meshcentral/meshcentral-web
|
||||
- meshcentral-backups:/opt/meshcentral/meshcentral-backups
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
meshcentral-data:
|
||||
meshcentral-files:
|
||||
meshcentral-web:
|
||||
meshcentral-backups:
|
||||
@ -1,8 +1,9 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json",
|
||||
"settings": {
|
||||
"plugins":{"enabled": false},
|
||||
"_mongoDb": null,
|
||||
"plugins":{
|
||||
"enabled": false
|
||||
},
|
||||
"cert": "myserver.mydomain.com",
|
||||
"_WANonly": true,
|
||||
"_LANonly": true,
|
||||
@ -15,7 +16,22 @@
|
||||
"TLSOffload": false,
|
||||
"SelfUpdate": false,
|
||||
"AllowFraming": false,
|
||||
"WebRTC": false
|
||||
"WebRTC": false,
|
||||
"_mongoDb": "",
|
||||
"_postgres": {
|
||||
"host": "",
|
||||
"port": "",
|
||||
"user": "",
|
||||
"password": "",
|
||||
"database": ""
|
||||
},
|
||||
"_mariaDB": {
|
||||
"host": "",
|
||||
"port": "",
|
||||
"user": "",
|
||||
"password": "",
|
||||
"database": ""
|
||||
}
|
||||
},
|
||||
"domains": {
|
||||
"": {
|
||||
|
||||
270
docker/entrypoint.sh
Normal file
@ -0,0 +1,270 @@
|
||||
#!/bin/bash
|
||||
|
||||
graceful_shutdown() {
|
||||
echo "Received SIGTERM from the container host. Cleaning up..."
|
||||
kill -SIGINT $meshcentral_pid
|
||||
|
||||
echo "MeshCentral process stopped. Exiting..."
|
||||
exit 0
|
||||
}
|
||||
trap graceful_shutdown SIGTERM
|
||||
|
||||
### Start MeshCentral Docker Container.
|
||||
|
||||
# Make the start more cleared when restarted.
|
||||
echo "-------------------------------------------------------------"
|
||||
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 /opt/meshcentral/config.json.template "${CONFIG_FILE}"
|
||||
fi
|
||||
|
||||
if [[ ${DYNAMIC_CONFIG,,} =~ ^(true|yes)$ ]]; then
|
||||
echo "Using Dynamic Configuration values..."
|
||||
|
||||
# BEGIN DATABASE CONFIGURATION FIELDS
|
||||
USE_MONGODB=${USE_MONGODB,,}
|
||||
if [[ $USE_MONGODB =~ ^(true|yes)$ ]]; then
|
||||
echo "Enabling MongoDB-connector..."
|
||||
|
||||
if [[ -n "$MONGO_URL" ]]; then
|
||||
echo "MONGO_URL is set, using that..."
|
||||
else
|
||||
MONGO_URL="${MONGO_URL:-$MONGO_USERNAME:$MONGO_PASS@}$MONGO_HOST:$MONGO_PORT"
|
||||
fi
|
||||
|
||||
#ESCAPED_MONGO_URL=$(echo "$MONGO_URL" | sed 's/[\/&?=:]/\\&/g')
|
||||
sed -i 's/"_mongoDb"/"mongoDb"/' "$CONFIG_FILE"
|
||||
jq --arg mongo_url "$MONGO_URL" \
|
||||
'.settings.mongoDb = $mongo_url' \
|
||||
"$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
|
||||
else
|
||||
echo "Disabling MongoDB-connector..."
|
||||
sed -i 's/"mongoDb"/"_mongoDb"/' "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
USE_POSTGRESQL=${USE_POSTGRESQL,,}
|
||||
if [[ $USE_POSTGRESQL =~ ^(true|yes)$ ]]; then
|
||||
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 "Disabling PostgreSQL-connector..."
|
||||
sed -i 's/"postgres"/"_postgres"/' "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
USE_MARIADB=${USE_MARIADB,,}
|
||||
if [[ $USE_MARIADB =~ ^(true|yes)$ ]]; then
|
||||
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 "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.
|
||||
# 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 [[ ${REGEN_SESSIONKEY,,} =~ ^(true|yes)$ ]]; then
|
||||
echo "Regenerating Session-Key because REGENSESSIONKEY is 'true' or 'yes'"
|
||||
SESSION_KEY=$(tr -dc 'A-Z0-9' < /dev/urandom | fold -w 96 | head -n 1)
|
||||
|
||||
sed -i 's/"_sessionKey"/"sessionKey"/' "$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 ]]; 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 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
|
||||
|
||||
# ALLOWPLUGINS
|
||||
ALLOW_PLUGINS=${ALLOW_PLUGINS,,}
|
||||
if [[ $ALLOW_PLUGINS =~ ^(true|false)$ ]]; then
|
||||
echo "Setting plugins... $ALLOW_PLUGINS"
|
||||
|
||||
sed -i 's/"_plugins"/"plugins"/' "$CONFIG_FILE"
|
||||
jq --argjson allow_plugins "$ALLOW_PLUGINS" \
|
||||
'.settings.plugins.enabled = $allow_plugins' \
|
||||
"$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
|
||||
else
|
||||
echo "Invalid or no ALLOWPLUGINS value given, commenting out so default applies... Value given: $ALLOW_PLUGINS"
|
||||
sed -i 's/"plugins":/"_plugins":/g' "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# WEBRTC
|
||||
WEBRTC=${WEBRTC,,}
|
||||
if [[ $WEBRTC =~ ^(true|false)$ ]]; then
|
||||
echo "Setting WebRTC... $WEBRTC"
|
||||
|
||||
sed -i 's/"_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 or no WEBRTC value given, commenting out so default applies... Value given: $WEBRTC"
|
||||
sed -i 's/"WebRTC":/"_WebRTC":/g' "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# IFRAME
|
||||
IFRAME=${IFRAME,,}
|
||||
if [[ $IFRAME =~ ^(true|false)$ ]]; then
|
||||
echo "Setting AllowFraming... $IFRAME"
|
||||
|
||||
sed -i 's/"_AllowFraming"/"AllowFraming"/' "$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 or no IFRAME value given, commenting out so default applies... Value given: $IFRAME"
|
||||
sed -i 's/"AllowFraming":/"_AllowFraming":/g' "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# trustedProxy
|
||||
if [[ -n $TRUSTED_PROXY ]]; then
|
||||
echo "Setting trustedProxy... - $TRUSTED_PROXY"
|
||||
|
||||
if [[ $TRUSTED_PROXY == "all" ]] || [[ $TRUSTED_PROXY == "true" ]]; then
|
||||
sed -i 's/"_trustedProxy"/"trustedProxy"/' "$CONFIG_FILE"
|
||||
jq --argjson trusted_proxy "true" \
|
||||
'.settings.trustedProxy = $trusted_proxy' \
|
||||
"$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
|
||||
else
|
||||
sed -i 's/"_trustedProxy"/"trustedProxy"/' "$CONFIG_FILE"
|
||||
jq --argjson trusted_proxy "$TRUSTED_PROXY" \
|
||||
'.settings.trustedProxy = $trusted_proxy' \
|
||||
"$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
|
||||
fi
|
||||
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
|
||||
|
||||
# ALLOW_NEW_ACCOUNTS
|
||||
ALLOW_NEW_ACCOUNTS=${ALLOW_NEW_ACCOUNTS,,}
|
||||
if [[ $ALLOW_NEW_ACCOUNTS =~ ^(true|false)$ ]]; then
|
||||
echo "Setting NewAccounts... $ALLOW_NEW_ACCOUNTS"
|
||||
|
||||
sed -i 's/"_NewAccounts"/"NewAccounts"/' "$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 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
|
||||
|
||||
# LOCALSESSIONRECORDING
|
||||
LOCAL_SESSION_RECORDING=${LOCAL_SESSION_RECORDING,,}
|
||||
if [[ $LOCAL_SESSION_RECORDING =~ ^(true|false)$ ]]; then
|
||||
echo "Setting localSessionRecording... $LOCAL_SESSION_RECORDING"
|
||||
|
||||
sed -i 's/"_localSessionRecording"/"localSessionRecording"/' "$CONFIG_FILE"
|
||||
jq --argjson session_recording "$LOCAL_SESSION_RECORDING" \
|
||||
'.domains[""].localSessionRecording = $session_recording' \
|
||||
"$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
|
||||
else
|
||||
echo "Invalid or no LOCALSESSIONRECORDING value given, commenting out so default applies... Value given: $LOCAL_SESSION_RECORDING"
|
||||
sed -i 's/"localSessionRecording":/"_localSessionRecording":/g' "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# MINIFY
|
||||
MINIFY=${MINIFY,,}
|
||||
if [[ $MINIFY =~ ^(true|false)$ ]]; then
|
||||
echo "Setting minify... $MINIFY"
|
||||
|
||||
sed -i 's/"_minify"/"minify"/' "$CONFIG_FILE"
|
||||
jq --argjson 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 or no MINIFY value given, commenting out so default applies... Value given: $MINIFY"
|
||||
sed -i 's/"minify":/"_minify":/g' "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# ALLOWED_ORIGIN
|
||||
ALLOWED_ORIGIN=${ALLOWED_ORIGIN,,}
|
||||
if [[ $ALLOWED_ORIGIN =~ ^(true|false)$ ]]; then
|
||||
echo "Setting allowedOrigin... $ALLOWED_ORIGIN"
|
||||
|
||||
sed -i 's/"_allowedOrigin"/"allowedOrigin"/' "$CONFIG_FILE"
|
||||
jq --argjson allowed_origin "$ALLOWED_ORIGIN" \
|
||||
'.domains[""].allowedOrigin = $allowed_origin' \
|
||||
"$CONFIG_FILE" > temp_config.json && mv temp_config.json "$CONFIG_FILE"
|
||||
else
|
||||
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
|
||||
|
||||
cat "$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"
|
||||
127
docker/readme.md
@ -1,127 +0,0 @@
|
||||
# Create folder-structure and files
|
||||
|
||||
```
|
||||
| - 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
|
||||
```
|
||||
|
||||
# Templates
|
||||
|
||||
## .env
|
||||
You can place the `config.json` file directly under `./meshcentral/data/`, or use the following `.env` file instead.
|
||||
|
||||
```ini
|
||||
NODE_ENV=production
|
||||
|
||||
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
|
||||
|
||||
# initial meshcentral-variables
|
||||
# the following options are only used if no config.json exists in the data-folder
|
||||
|
||||
# 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
|
||||
```
|
||||
|
||||
## docker-compose.yml
|
||||
|
||||
```yaml
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
meshcentral:
|
||||
restart: always
|
||||
container_name: meshcentral
|
||||
# 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
|
||||
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
|
||||
```
|
||||
|
||||
## 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
|
||||
```
|
||||
@ -1,39 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -f "meshcentral-data/${CONFIG_FILE}" ]; then
|
||||
node meshcentral/meshcentral --configfile "${CONFIG_FILE}" ${ARGS}
|
||||
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}
|
||||
fi
|
||||
15
docs/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
docs/docs/design/images/2022-05-15-12-57-36.jpg
Normal file
|
After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 223 KiB |
BIN
docs/docs/design/images/2022-05-15-13-01-56.jpg
Normal file
|
After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 139 KiB |
BIN
docs/docs/design/images/2022-05-15-13-03-25.jpg
Normal file
|
After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 150 KiB |
BIN
docs/docs/design/images/2022-05-15-13-36-01.jpg
Normal file
|
After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 137 KiB |
BIN
docs/docs/design/images/2022-05-15-13-41-26.jpg
Normal file
|
After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 80 KiB |
BIN
docs/docs/design/images/2022-05-15-13-44-41.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 24 KiB |
BIN
docs/docs/design/images/2022-05-15-13-47-26.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 28 KiB |
BIN
docs/docs/design/images/2022-05-15-13-54-44.jpg
Normal file
|
After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 97 KiB |
BIN
docs/docs/design/images/2022-05-15-13-55-28.jpg
Normal file
|
After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 103 KiB |
BIN
docs/docs/design/images/2022-05-15-13-56-09.jpg
Normal file
|
After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 134 KiB |
BIN
docs/docs/design/images/2022-05-15-13-56-46.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 11 KiB |
BIN
docs/docs/design/images/2022-05-15-13-58-06.jpg
Normal file
|
After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 228 KiB |
BIN
docs/docs/design/images/2022-05-15-13-58-29.jpg
Normal file
|
After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 238 KiB |
BIN
docs/docs/design/images/2022-05-15-13-58-56.jpg
Normal file
|
After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 244 KiB |
BIN
docs/docs/design/images/2022-05-15-13-59-54.jpg
Normal file
|
After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 294 KiB |
BIN
docs/docs/design/images/2022-05-15-14-00-21.jpg
Normal file
|
After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 263 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 38 KiB |
@ -1,55 +1,68 @@
|
||||
# Design and Architecture
|
||||
|
||||

|
||||

|
||||
|
||||
Design and Architecture Guide [as .pdf](https://meshcentral.com/docs/MeshCentral2DesignArchitecture.pdf) [as .odt](https://github.com/Ylianst/MeshCentral/blob/master/docs/MeshCentral Design & Architecture v0.0.4.odt?raw=true)
|
||||
## Video Walkthru
|
||||
## 🎬 Video Walkthru
|
||||
|
||||
<div class="video-wrapper">
|
||||
<iframe width="320" height="180" src="https://www.youtube.com/embed/MOQ0uCUs7_M" frameborder="0" allowfullscreen></iframe>
|
||||
<iframe src="https://www.youtube.com/embed/MOQ0uCUs7_M" frameborder="0" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
## Abstract
|
||||
## 🧾 Abstract
|
||||
|
||||
This document attempts to describe the architecture and design of the second version of MeshCentral on which work started in late 2016. The document covers the overview of the design, goes in details about the protocol and various decisions and trade-offs. This document is intended for anyone that wants to understand the inner workings of MeshCentral or someone that wants to make a security review of the software. The software and added documentation and tutorial videos are available at:[ https://www.meshcommander.com/meshcentral2 ](https://www.meshcommander.com/meshcentral2)
|
||||
This document attempts to describe the architecture and design of the second version of MeshCentral on which work started in late 2016. The document covers the overview of the design, goes in details about the protocol and various decisions and trade-offs. This document is intended for anyone that wants to understand the inner workings of MeshCentral or someone that wants to make a security review of the software.
|
||||
|
||||
## Introduction
|
||||
---
|
||||
> **📌 Note :**
|
||||
|
||||
> The software and added documentation and tutorial videos are available at :
|
||||
[ https://www.meshcommander.com/meshcentral2 ](https://www.meshcommander.com/meshcentral2)
|
||||
|
||||
---
|
||||
|
||||
## 📘 Introduction
|
||||
|
||||
MeshCentral is a free open source web-based remote computer management software. After over 8 years of working on the first version of MeshCentral, work as moved to version 2 which this document described. In 2010, when MeshCentral v1 was first designed, the Internet was very different. HTML5 and WebSocket did not exists, no such thing as a software container, etc. With MeshCentral version 2, a complete redesign was made to make the software much more in line with modern Internet deployment models.
|
||||
|
||||
The advent of NodeJS, WebSocket, WebRTC and other web technologies coming out in the last 10 years has really made the design of MeshCentral v2 not only possible, but quite amazing. Being able to use a single programming language across platforms to JavaScript. Being able to easily exchange objects using web socket and JSON, being able to scale with WebRTC, deploy quickly with containers, etc. Looking back at the incredible advances in web technologies lead to an almost mandatory MeshCentral redesign.
|
||||
|
||||
## Goals & Requirements
|
||||
## 🎯 Goals & Requirements
|
||||
|
||||
The goal of MeshCentral is to be the best open source remote management software in the world. Remote computer management is a big area with many different usages and requirements. To best suite this, it’s important to have software that is as flexible as possible. Additionally, there are many other goals:
|
||||
The goal of MeshCentral is to be the best open source remote management software in the world. Remote computer management is a big area with many different usages and requirements. To best suite this, it’s important to have software that is as flexible as possible.
|
||||
|
||||
- Must be quick and easy to install.
|
||||
- Must install on all major operating systems and platforms.
|
||||
- Can be deployed on small computers and the cloud.
|
||||
- Can be deployed within containers.
|
||||
- Can be deployed in many network environments.
|
||||
- Must support both software agent and Intel® AMT hardware agent.
|
||||
- Must only use open source dependencies.
|
||||
- Must provide all basic remote management features (desktop, terminal, files…)
|
||||
- Must use the network efficiently.
|
||||
- Must have a real time user interface.
|
||||
- Must be easy to use.
|
||||
- Must be fast.
|
||||
- Etc.
|
||||
Additionally, there are many other goals :
|
||||
|
||||
> - **Must be quick and easy to install.**
|
||||
> - **Must install on all major operating systems and platforms.**
|
||||
> - **Can be deployed on small computers and the cloud.**
|
||||
> - **Can be deployed within containers.**
|
||||
> - **Can be deployed in many network environments.**
|
||||
> - **Must support both software agent and Intel® AMT hardware agent.**
|
||||
> - **Must only use open source dependencies.**
|
||||
> - **Must provide all basic remote management features (desktop, terminal, files…)**
|
||||
> - **Must use the network efficiently.**
|
||||
> - **Must have a real time user interface.**
|
||||
> - **Must be easy to use.**
|
||||
> - **Must be fast.**
|
||||
> - **Etc.**
|
||||
|
||||
Basically, all the requirements you would expect from open source software that can go viral. Since this software is sponsored by Intel, it’s going to support Intel® AMT really well, making it possible to manage a remote computer regardless of its OS or power state. Intel® AMT is not required to use this software, however it’s a great fit.
|
||||
|
||||
## Design Overview
|
||||
## 🖥️ Design Overview
|
||||
|
||||
In this section, we do a very high level overview of MeshCentral’s design. MeshCentral has 3 big components: the server, the agent and the web application.
|
||||
In this section, we do a very high level overview of MeshCentral’s design. MeshCentral has 3 big components :
|
||||
|
||||

|
||||
- *The server*,
|
||||
- *The agent and*
|
||||
- *The web application*.
|
||||
|
||||

|
||||
|
||||
There is of course more software that support these 3 components like the Windows Server Installer, ClickOnce application, MeshCentral Discovery Tool and more. These will be covered later. Most of the document will focus on these 3 main components. Another component that is significant but not part of the software itself is Intel® AMT (Intel® Active Management Technology). MeshCentral supports Intel AMT that acts like an optional hardware based agent for MeshCentral.
|
||||
|
||||
When it comes to programming languages used, MeshCentral is mostly built with JavaScript with the agent having significant portable C code. This makes things pretty simple since the browser, server and agents can share some of the code. More importantly, JavaScript is great at parsing JSON and so, the main protocol used between the components is JSON over Web Socket.
|
||||
|
||||

|
||||

|
||||
|
||||
It’s important to note that while JavaScript is used in all 3 components, the JavaScript runtime is very different. The JavaScript written to run within a browser sandbox uses different calls than the one running in NodeJS on the server or on the agent with DukTape.
|
||||
|
||||
@ -57,57 +70,68 @@ This is probably a good time to introduce DukTape [(https://www.duktape.org/)](h
|
||||
|
||||
Another interesting design decision is that MeshCentral makes almost no use of RESTful API’s. Instead, almost everything is done using WebSocket. This allows JSON objects to be exchanged fully asynchronously. There is no pushing the refresh button or polling as events are sent by all actors in real time.
|
||||
|
||||
## MeshCentral server
|
||||
## 🗄️ MeshCentral server
|
||||
|
||||
The MeshCentral server is a NodeJS application that is published on NPM at: [https://www.npmjs.com/package/meshcentral](https://www.npmjs.com/package/meshcentral) Many administrators can get started quickly using “npm install meshcentral” once NodeJS is installed. MeshCentral will work on Node 6.x and higher.
|
||||
The MeshCentral server is a NodeJS application that is published on NPM at : [https://www.npmjs.com/package/meshcentral](https://www.npmjs.com/package/meshcentral) Many administrators can get started quickly using “npm install meshcentral” once NodeJS is installed. MeshCentral will work on Node 6.x and higher.
|
||||
|
||||
## Dependencies
|
||||
## 📦 Dependencies
|
||||
|
||||
The server makes use of the following dependencies on NPM. These are all automatically installed by NPM when installing MeshCentral.
|
||||
|
||||
Can be found in the file: `MeshCentralServer.njsproj`
|
||||
Can be found in the file : `MeshCentralServer.njsproj`
|
||||
|
||||
The main takeaway is that MeshCentral is mostly an ExpressJS application. This is not a complete list of dependencies as many of these packages have their own dependencies creating a large tree. The security of these packages is a concern and all of the dependency tree is a concern. In addition to the dependencies that are “hard coded”, there are a few more that are installed only when needed. These are:
|
||||
The main takeaway is that MeshCentral is mostly an ExpressJS application. This is not a complete list of dependencies as many of these packages have their own dependencies creating a large tree. The security of these packages is a concern and all of the dependency tree is a concern. In addition to the dependencies that are “hard coded”, there are a few more that are installed only when needed. These are :
|
||||
|
||||
### node-windows
|
||||
|
||||
**greenlock, le-store-certbot, le-challenge-fs**: Installed on all Windows install. Allows background service install:
|
||||
- **greenlock, le-store-certbot, le-challenge-fs** :
|
||||
|
||||
**le-acme-core**: Installed only when Let’s Encrypt must be used:
|
||||
> Installed on all Windows install. Allows background service install:
|
||||
|
||||
**mongojs**: Installed when MongoDB is in used.
|
||||
- **le-acme-core** :
|
||||
|
||||
**nodemailer**: Installed when SMTP server support is in used.
|
||||
> Installed only when Let’s Encrypt must be used:
|
||||
|
||||
- **mongojs** :
|
||||
|
||||
> Installed when MongoDB is in used.
|
||||
|
||||
- **nodemailer** :
|
||||
|
||||
> Installed when SMTP server support is in used.
|
||||
|
||||
MeshCentral will run `npm install` automatically when any of these optional modules are needed but not currently available.
|
||||
|
||||
## Understanding the different modes: LAN, WAN and Hybrid
|
||||
## 🎬 Understanding the different modes: LAN, WAN and Hybrid
|
||||
|
||||
|
||||
<div class="video-wrapper">
|
||||
<iframe width="320" height="180" src="https://www.youtube.com/embed/gx5Fh3pQOns" frameborder="0" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
## Code files and folders
|
||||
## 📁 Code files and folders
|
||||
|
||||
Someone would think the server is rather simple when taking a look at the MeshCentral server code files. At a high level, the entire server has 3 folders, 3 text files and a manageable number of .js files that are fairly self-descriptive. Here is a list of the source files and folders.
|
||||
|
||||
### Folders
|
||||
|
||||
`agents`: Compiled agents, install scripts, tools and agent JavaScript.
|
||||
`agents`: Compiled agents, install scripts, tools and agent JavaScript.
|
||||
|
||||
`public`: Static web elements such as images, CSS, HTML and more.
|
||||
`public`: Static web elements such as images, CSS, HTML and more.
|
||||
|
||||
`views`: Main web application, login screen and messenger app.
|
||||
`views`: Main web application, login screen and messenger app.
|
||||
|
||||
### Configuration & text files
|
||||
|
||||
`package.json`: Description of the MeshCentral package on NPM.
|
||||
|
||||
`sample-config.json`: A sample “config.json” file to get started.
|
||||
|
||||
`readme.txt`: Readme file published with the MeshCentral package.
|
||||
|
||||
### Code files
|
||||
|
||||
```
|
||||
```bash
|
||||
amtevents.js | Used to decode Intel AMT WSMAN events.
|
||||
amtmanager.js | Used to handle Intel AMT/CIRA things.
|
||||
amtprovisioningserver.js | Used to Provision Intel AMT on a Local Network.
|
||||
@ -150,7 +174,15 @@ Someone would think the server is rather simple when taking a look at the MeshCe
|
||||
|
||||
```
|
||||
|
||||
At a high level, the MeshCentral.js file will get the server started. By default, it will start the webserver.js on port 443, redirectserver.js on port 80 and mpssrver.js on port 4433. The webserver.js file will create a meshuser.js or meshagent.js instance each time a user or agent connects. The other files support various usages, but this is the basic working on the server.
|
||||
At a high level, the MeshCentral.js file will get the server started.
|
||||
|
||||
By default, it will start :
|
||||
|
||||
- `webserver.js` on port `443`,
|
||||
- `redirectserver.js` on port `80` and
|
||||
- `mpssrver.js` on port `4433`.
|
||||
|
||||
The `webserver.js` file will create a `meshuser.js` or `meshagent.js` instance each time a user or agent connects. The other files support various usages, but this is the basic working on the server.
|
||||
|
||||
### Server database
|
||||
|
||||
@ -158,23 +190,23 @@ One of the big design decision on the server is its database. We want something
|
||||
|
||||
By default, MeshCentral will just create and use a NeDB database, but can be configured to use MongoDB. The internal code path for both databases are almost exactly identical so the “db.js” file handles both, almost the same way and the exact database in use is completely abstracted from the rest of the server code.
|
||||
|
||||
## Certificates
|
||||
## 🔐 Certificates
|
||||
|
||||
MeshCentral makes use of many certificates to accomplish many security tasks. When first running the server or an agent, both of these actors will generate certificates. The agent will generate one or two certificates on the first run and the server will generate four certificates.
|
||||
|
||||

|
||||

|
||||
|
||||
In this section we review what certificates are created, what are their uses and how they are stored. Most administrators using MeshCentral will not need a deep understanding of this section to run the server, however, a basic understanding of this section can help understand how to best protect the server’s critical security assets.
|
||||
|
||||
### Server Certificates
|
||||
|
||||
As indicated above, the MeshCentral server creates four certificates when it first runs. It uses ForgeJS to perform certificate creation and all four certificates below are saved in the “meshcentral-data” folder. The four certificates are:
|
||||
As indicated above, the MeshCentral server creates four certificates when it first runs. It uses ForgeJS to perform certificate creation and all four certificates below are saved in the `meshcentral-data` folder. The four certificates are:
|
||||
|
||||
#### Server root
|
||||
|
||||
`root-cert-public.crt`
|
||||
|
||||
This is a self-signed root certificate that is used only to issue the 3 next certificates. This certificate can be useful when it’s installed as a root of trust in some situations. For example, when Intel AMT connects to the MPS server on port 4433, it will correctly connect only if this root certificate is loaded into Intel AMT as a trusted certificate. Browser can also be setup to trust this root certificate in order to create a trusted connection between a browser and the servers HTTPS port. This certificate is RSA3072 unless the option “--fastcert" is used, in that case a RSA2048 certificate is generated.
|
||||
This is a self-signed root certificate that is used only to issue the 3 next certificates. This certificate can be useful when it’s installed as a root of trust in some situations. For example, when Intel AMT connects to the MPS server on port `4433`, it will correctly connect only if this root certificate is loaded into Intel AMT as a trusted certificate. Browser can also be setup to trust this root certificate in order to create a trusted connection between a browser and the servers HTTPS port. This certificate is RSA3072 unless the option `--fastcert` is used, in that case a RSA2048 certificate is generated.
|
||||
|
||||
#### MPS certificate
|
||||
|
||||
@ -186,27 +218,31 @@ This is a TLS certificate signed by the root above used as a TLS server certific
|
||||
|
||||
`webserver-cert-public.crt`
|
||||
|
||||
This is the default certificate used to secure the HTTPS port 443. It is signed by the root above and is the certificate users will first see then connecting the browser to the server. Often, users will need to ignore the browser security warning. This certificate is RSA3072 unless the option “--fastcert" is used, in that case a RSA2048 certificate is generated. In production environments, this certificate is replaced with a real certificate. There are many ways to change this certificate for a more appropriate certificate in production environments:
|
||||
This is the default certificate used to secure the HTTPS port `443`. It is signed by the root above and is the certificate users will first see then connecting the browser to the server. Often, users will need to ignore the browser security warning. This certificate is RSA3072 unless the option `--fastcert` is used, in that case a RSA2048 certificate is generated. In production environments, this certificate is replaced with a real certificate.
|
||||
|
||||
- You can replace the “webserver-cert-\*” files in the “meshcentral-data” folder.
|
||||
- You can use Let’s Encrypt which will override this certificate automatically.
|
||||
- You can use a reverse-proxy in front of the server with “--tlsoffload".
|
||||
There are many ways to change this certificate for a more appropriate certificate in production environments :
|
||||
|
||||
- You can replace the `webserver-cert-\*` files in the `meshcentral-data` folder.
|
||||
|
||||
- You can use Let’s Encrypt which will override this certificate automatically.
|
||||
|
||||
- You can use a reverse-proxy in front of the server with `--tlsoffload`.
|
||||
|
||||
#### Agent certificate
|
||||
|
||||
`agentserver-cert-public.crt`
|
||||
|
||||
This certificate is used to authenticate the server to agents. It’s signed by the root above and when installing an agent, the hash of this certificate is given to the agent so that it can connect back to the server securely. This certificate is RSA3072 unless the option “--fastcert" is used, in that case a RSA2048 certificate is generated.
|
||||
This certificate is used to authenticate the server to agents. It’s signed by the root above and when installing an agent, the hash of this certificate is given to the agent so that it can connect back to the server securely. This certificate is RSA3072 unless the option `--fastcert` is used, in that case a RSA2048 certificate is generated.
|
||||
|
||||
The “meshcentral-data” folder contains critical server information including private keys therefore, it’s important that it be well protected. It’s important to backup the “meshcentral-data” folder and keep the backup in a secure place. If, for example the “agent certificate” on the server is lost, there is no hope for agents ever be able to connect back to this server. All agents will need to be re-installed with a new trusted certificate.
|
||||
The `meshcentral-data` folder contains critical server information including private keys therefore, it’s important that it be well protected. It’s important to backup the `meshcentral-data` folder and keep the backup in a secure place. If, for example the “agent certificate” on the server is lost, there is no hope for agents ever be able to connect back to this server. All agents will need to be re-installed with a new trusted certificate.
|
||||
|
||||
If someone re-installs a server, placing the “meshcentral-data” folder back with these certificates should allow the server to resume normal operations and accept connections for Intel AMT and agents as before.
|
||||
If someone re-installs a server, placing the `meshcentral-data` folder back with these certificates should allow the server to resume normal operations and accept connections for Intel AMT and agents as before.
|
||||
|
||||
### Agent Certificates
|
||||
|
||||
The mesh agent generates one or two RSA certificates when it first starts. On smaller IoT devices such as a Raspberry Pi, this can take a little while to do and the CPU will spike to 100% during this time. This is normal and only occurs the first time the agent runs.
|
||||
|
||||

|
||||

|
||||
|
||||
The certificates are generated a little differently depending on the platform. On Windows, the Mesh Agent will use Microsoft cryptographic providers to harder the agent root cert. If available, the agent will use the platform TPM to harden the certificate. On other platforms, only one certificate is generated and used for both agent authentication to the server and WebRTC session authentication.
|
||||
|
||||
@ -218,13 +254,13 @@ This certificate is the root trust of the agent. The SHA384 hash of this certifi
|
||||
|
||||
This is a certificate signed by the agent root above. It’s currently only used by WebRTC to perform dTLS authentication to a remote browser. This certificate does not need to be signed by a trusted CA for WebRTC purposes since the hash of the certificate will be sent to the browser using a trusted path. If the agent root certificate is not hardened using platform cryptography, the secondary certificate is not created and the agent root cert is used for all purposes.
|
||||
|
||||
A possible attack would occur if someone were to be able to access the agent root certificate. They could impersonate the agent to the server. Agents don’t have any rights to perform management operations on the server or other agents, but by impersonating a agent, a rogue agent would pretend to be an office computer to which administrator would login with their username & password, especially when the root is not hardened. Some care should be taken to protect the “meshagent.db” file and to not give important information to untrusted agents.
|
||||
A possible attack would occur if someone were to be able to access the agent root certificate. They could impersonate the agent to the server. Agents don’t have any rights to perform management operations on the server or other agents, but by impersonating a agent, a rogue agent would pretend to be an office computer to which administrator would login with their username & password, especially when the root is not hardened. Some care should be taken to protect the `meshagent.db` file and to not give important information to untrusted agents.
|
||||
|
||||
## TLS Security
|
||||
## 🔒 TLS Security
|
||||
|
||||
MeshCentral makes heavy use of Transport Layer Security (TLS) and datagram-TLS (dTLS) to authenticate and encrypt network traffic between the browser, server and agent. Configuring TLS settings correctly is essential to making sure communications are secure and to minimize attacks on open ports.
|
||||
|
||||
Probably the most important TLS configuration is for the MeshCentral server ports 443 and 4433. These two ports are exposed to the Internet and so, should be setup as securely as possible.
|
||||
Probably the most important TLS configuration is for the MeshCentral server ports `443` and `4433`. These two ports are exposed to the Internet and so, should be setup as securely as possible.
|
||||
|
||||
### MeshCentral HTTPS port 443
|
||||
|
||||
@ -241,15 +277,15 @@ TLS\_ECDHE\_RSA\_WITH\_AES\_128\_CBC\_SHA (0xc013)
|
||||
|
||||
Note that these cipher suites are all perfect forward secrecy (PFS) suites and are considered cryptographically secure as of the writing of this document. When the server is deployed on the Internet,[ https://ssllabs.com ](https://ssllabs.com/)gives the server an A rating with no known vulnerabilities and no weak ciphers detected.
|
||||
|
||||

|
||||

|
||||
|
||||
SSL Labs confirms that all major browsers should be able to connect correctly to this server.
|
||||
|
||||
### MeshCentral MPS port 4433
|
||||
|
||||
The Manageability Presence Server (MPS) port 4433 is used for incoming Intel AMT CIRA connections. By default it uses a TLS certificate that is signed by a self-signed root certificates. This port is not intended to be connected to by typical browsers, only Intel AMT should connect to this port. Note that the TLS certificate generated by MeshCentral for port 4433 is RSA 2048bits, this is because older Intel AMT firmware don’t support RSA 3072. Because the port is not secured using a trusted certificate, SSL Labs will not rate the security of this server.
|
||||
The Manageability Presence Server (MPS) port `4433` is used for incoming Intel AMT CIRA connections. By default it uses a TLS certificate that is signed by a self-signed root certificates. This port is not intended to be connected to by typical browsers, only Intel AMT should connect to this port. Note that the TLS certificate generated by MeshCentral for port `4433` is RSA 2048bits, this is because older Intel AMT firmware don’t support RSA 3072. Because the port is not secured using a trusted certificate, SSL Labs will not rate the security of this server.
|
||||
|
||||

|
||||

|
||||
|
||||
This is fully expected. Note that SSL Labs will not test servers that are not on port 443. To perform a test like this MeshCentral must be set temporarily with the MPS port set to 443 and the normal HTTPS port set to a different value.
|
||||
|
||||
@ -271,9 +307,9 @@ TLS\_RSA\_WITH\_AES\_128\_CBC\_SHA (0x2f)
|
||||
|
||||
```
|
||||
|
||||
The suites starting with “TLS\_RSA\_” don’t have perfect forward secrecy (PFS) and so, are considered weak by SSL Labs. However, these are generally the suites that are supported by Intel AMT.
|
||||
The suites starting with `TLS\_RSA\_` don’t have perfect forward secrecy (PFS) and so, are considered weak by SSL Labs. However, these are generally the suites that are supported by Intel AMT.
|
||||
|
||||
## Agent to server handshake
|
||||
## 🛰️ Agent to server handshake
|
||||
|
||||
One interesting aspect of MeshCentral’s design is how the agent connects to the server. We wanted a way for the agent to connect to the server that would be similar to how browsers connect to web servers. This allows for a large number of agents to connect just like if a large number of browsers where connecting. All of the infrastructure that helps web server’s scale would be put to use in the same way for agent connections. For example: TLS offload hardware, load balancers, reverse-proxies, web server scaling, etc. could all be put to use. It also makes the server easier to setup because only one port (HTTPS 443) is needed for both users and agents.
|
||||
|
||||
@ -283,7 +319,7 @@ The public facing web certificate of the server can change frequently. For examp
|
||||
|
||||
To handle all this, the agent performs a TLS connection to the server and will first see the web certificate of the server. It will then exchange a set of web socket binary messages to the server to perform a secondary authentication with the server.
|
||||
|
||||

|
||||

|
||||
|
||||
The secondary check allows the agent to confirm that this server does own the private key of the private certificate expected by the agent. The agent caches the hash of the “outer” web certificate. When re-connecting, if the agent sees the same outer web certificate, it will skip the secondary check. For obvious security raisons, it’s important that the agent not accept any management messages until the secondary check is completed or skipped.
|
||||
|
||||
@ -291,42 +327,44 @@ To prevent man-in-the-middle attacks, the secondary check also “pins” the ou
|
||||
|
||||
The agent connection design allows for reverse-proxies and TLS offload hardware. The agent will first connect a TLS session to the offload hardware. Clear traffic flows between the offload hardware and the server which will perform the secondary check if needed.
|
||||
|
||||

|
||||

|
||||
|
||||
To makes all this work, the MeshCentral server must be able to fetch the hash of the outer web certificate from the reverse proxy. In this case, the server does not need the private key to the web certificate. Note that when the outer web certificate is updated, the server may have to perform many secondary checks at the same time causing a server slowdown during this time. To help with this, MeshCentral will offload the RSA signing operation to many slave processes (as many as the CPU core count on the server) to speed this up. In addition, native NodeJS RSA signing is used (not ForgeJS).
|
||||
|
||||
The details of the secondary certificate check look like the diagram below. To boost speed, the exchange is fully asynchronous and both sides send the first message as soon as the TLS connection completes.
|
||||
|
||||

|
||||

|
||||
|
||||
Note that these messages are binary (not JSON). The agent must be able to connect to the server independently of the JavaScript that is running in DukTape. So this exchange is handled by native C code in the agent. Binary message 1 is sent immediately after the TLS connection is setup. Both sides will send binary message 2 when message 1 is received and message 3 when message 2 is received.
|
||||
|
||||
In addition, there are two extra messages of interest that can be sent by the agent right at the start. The agent may send the server message number 4 if the secondary check can be skipped and may send binary message number 5 indicating what server hash it expects to verify. Message number 5 is interesting because a server may have many “identities” at the same time, and so, the server will use message number 5 in order to use the right Agent Server certificate.
|
||||
|
||||
In order to be as secure as possible, all hashes use SHA384 and certificates are RSA3072 and nonces are generated on both sides using a cryptographic random source. The server and agent signatures are computed like this:
|
||||
In order to be as secure as possible, all hashes use SHA384 and certificates are RSA3072 and nonces are generated on both sides using a cryptographic random source.
|
||||
|
||||

|
||||
The server and agent signatures are computed like this :
|
||||
|
||||

|
||||
|
||||
While the server will often skip its RSA signature operation due to the agents caching the outer web certificate, the server must perform an RSA verify to each agent connection. This can’t be skipped but is needed to authenticate the agent.
|
||||
|
||||
Once connected, the trust relationship between the server and the agent is one-way. That is, the server has management rights on the agent, but the agent does not have any right on the server. This is important since the agent does not, by default, have any credentials to the server. Any agent can connect to the server and claim to be part of a device group.
|
||||
|
||||
## Browser to agent relay and WebRTC
|
||||
## 🌍 Browser to agent relay and WebRTC
|
||||
|
||||
Browsers and agents often need to communicate to each other. Data sessions are used for desktop, terminal, file transfers, etc. and must be setup securely.
|
||||
|
||||
To setup a session between a browser and the agent, the server will send a URL to both sides to connect to. The URL is generated by the server and includes a unique connection token. It is sent to both the browser and agent using the web socket control channel and a JSON message. Both sides perform a websocket connection to the target URL and the server will “pipe” both sessions together to act as a passive relay. For security, the agent will only accept connections to the URL given by the server if the server has the same outer web certificate as its control connection. Also note that in this mode, the session is not end-to-end encrypted. The server is performing a TLS decrypt and re-encrypt and the traffic cost is high as each byte of data has to be received and sent again.
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
The relay server is just websocket server that will wait for connections with session tokens. When two connection with the same connection token arrive, the server makes sure that at least one of the two connections is an authenticated user, it then sends the character “c” on both sides to inform both parties that the relay is starting and then pipes both sessions together. Once the session is started, the browser and agent are free to send messages to each other. Note that when the server sends the relay URL to the agent, it also sends to the agent the user’s permissions flags. This may be used by the agent to limit what the user can do on this session.
|
||||
The relay server is just websocket server that will wait for connections with session tokens. When two connection with the same connection token arrive, the server makes sure that at least one of the two connections is an authenticated user, it then sends the character `c` on both sides to inform both parties that the relay is starting and then pipes both sessions together. Once the session is started, the browser and agent are free to send messages to each other. Note that when the server sends the relay URL to the agent, it also sends to the agent the user’s permissions flags. This may be used by the agent to limit what the user can do on this session.
|
||||
|
||||
With this design, the flow control between the browser and agent is simple, each session gets its own end-to-end connection and the server will apply appropriate TCP back pressure on both sides as needed.
|
||||
|
||||
A unique feature of MeshCentral is its use of WebRTC. WebRTC was introduced in major browsers as a way to allow browsers to directly communicate to each other and perform audio/video streaming. The mesh agent has a WebRTC data-only stack that is custom built for this project in C code. It’s compatible with Chrome and Firefox implementations and once a session is set up, allows data to flow directly from the browser to the agent, bypassing the server.
|
||||
|
||||

|
||||

|
||||
|
||||
The use of WebRTC allows MeshCentral to scale better, to offer a faster user experience and lower hosting costs all at the same time. However, WebRTC is not easy, especially when you must maintain the C code for it and have to keep up with browser implementations, but the benefits are clear.
|
||||
|
||||
@ -334,7 +372,7 @@ To setup WebRTC, browsers typically use STUN and TURN servers to get traffic thr
|
||||
|
||||
To perform the switch-over, both browser and agent will exchange WebRTC control messages over the newly established web socket relay session.
|
||||
|
||||

|
||||

|
||||
|
||||
In order to differentiate session traffic from WebRTC control traffic, the browser and agent agree to send WebRTC setup traffic using web socket text fragments. All other session traffic is sent using binary fragments. The agent has a special API allowing a session to be piped for a single fragment type. So we can perform a remote desktop session to the agent while trying to setup WebRTC at the same time.
|
||||
|
||||
@ -342,32 +380,54 @@ The browser will kick off the WebRTC setup sending the initial WebRTC offer with
|
||||
|
||||
On the agent side, the new WebRTC session inherits the user access rights of the web socket. Currently, the web socket channel is still maintained open. While it’s not strickly needed, the web socket session terminates more cleanly than WebRTC and so, oddly its closure is used to signal the end of the WebRTC session.
|
||||
|
||||
## Messenger
|
||||
## 💬 Messenger
|
||||
|
||||
MeshCentral includes its own messaging web application it can be used to chat, transfer files and optionally used for audio and video chat. It’s used to support two different usages: User-to-user and user-to-computer communication. In the first usage, two users that are connected to the same MeshCentral server at the same time can chat. If you are a MeshCentral administrator, you can see the list of currently logged in users and hit the chat button to launch a chat invitation. If accepted, the Messenger is open on both sides and the session starts. Alternatively, while managing a remote computer, an administrator can hit the chat button to cause the remote computer to open a web browser to the chat application.
|
||||
MeshCentral includes its own messaging web application it can be used to chat, transfer files and optionally used for audio and video chat. It’s used to support two different usages :
|
||||
|
||||
- *User-to-user and*
|
||||
|
||||
- *user-to-computer communication.*
|
||||
|
||||
In the first usage, two users that are connected to the same MeshCentral server at the same time can chat. If you are a MeshCentral administrator, you can see the list of currently logged in users and hit the chat button to launch a chat invitation. If accepted, the Messenger is open on both sides and the session starts. Alternatively, while managing a remote computer, an administrator can hit the chat button to cause the remote computer to open a web browser to the chat application.
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
The chat app is standalone web application that is served by the MeshCentral server using a connection token and title in the URL. Once loaded in its own web frame, the messenger web application will get the connection token and title from the URL and proceed to connect to the URL using web socket. The same web socket relay that is used for browser-to-agent connections is also used in this case for browser-to-browser connections. The server relay acts the same and pipes both sessions together after sending the character “c” to both sides. At this point, the messenger application will show the remote user as connected and chat and file transfers can start. File transfers are just a set of binary messages sent over the web socket session with lots of JSON control messages.
|
||||
The chat app is standalone web application that is served by the MeshCentral server using a connection token and title in the URL. Once loaded in its own web frame, the messenger web application will get the connection token and title from the URL and proceed to connect to the URL using web socket. The same web socket relay that is used for browser-to-agent connections is also used in this case for browser-to-browser connections. The server relay acts the same and pipes both sessions together after sending the character `c` to both sides. At this point, the messenger application will show the remote user as connected and chat and file transfers can start. File transfers are just a set of binary messages sent over the web socket session with lots of JSON control messages.
|
||||
|
||||
Once the web socket session is setup, the messenger application will then attempt to perform a switch over to WebRTC. Both web application start by selecting a random number (not cryptographic) and the highest number will initiate the WebRTC offer. The other party will answer and both sides will trade interface candidates as they are discovered. If successful, the web socket session are flushed and the traffic is switched over to WebRTC. Because the switchover is done cleanly, it can occur while in the middle of a file transfer without the file being corrupted.
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
Finally, the web application will determine if the local computer is attached to a microphone and if it has a camera. If so, these options are offered in the chat window and audio/video chat is available for use. The chat app allows for one way setup of audio & video sessions. This is typically what is needed in support scenarios where the audio/video session is one-way.
|
||||
|
||||
The messenger web application will setup a separate WebRTC connection for audio/video in each direction but the code is present to augment the WebRTC control channel with audio/video which is a bit more efficient but more testing is needed before defaulting to this mode.
|
||||
|
||||
## Additional Resources
|
||||
## 💡 Additional Resources
|
||||
|
||||
In addition to this document, there are a growing set of MeshCentral resources at: [https://www.meshcommander.com/meshcentral2.](https://www.meshcommander.com/meshcentral2) This includes an Installer’s documents, a User’s Guide and plenty of YouTube tutorial videos. For developers, it’s best to start on the MeshCentral GitHub repository at:[ https://github.com/Ylianst/MeshCentral](https://github.com/Ylianst/MeshCentral). If any issues are found, it’s best to create a new issue in GitHub or mail [ylianst@gmail.com](mailto:ylianst@gmail.com)
|
||||
In addition to this document, there are a growing set of MeshCentral resources at :
|
||||
|
||||
## Conclusion
|
||||
- **[https://www.meshcommander.com/meshcentral2.](https://www.meshcommander.com/meshcentral2)** :
|
||||
|
||||
This includes an Installer’s documents, a User’s Guide and plenty of YouTube tutorial videos.
|
||||
|
||||
For developers, it’s best to start on the MeshCentral GitHub repository at :
|
||||
|
||||
- **[ https://github.com/Ylianst/MeshCentral](https://github.com/Ylianst/MeshCentral)**
|
||||
|
||||
If any issues are found, it’s best to create a new issue in GitHub or mail [ylianst@gmail.com](mailto:ylianst@gmail.com)
|
||||
|
||||
## 🏁 Conclusion
|
||||
|
||||
MeshCentral is a free, open source and powerful remote management solution that is cross- platform. In this document, we have covered the goals, overview, design and some details of the software. It’s hoped that this document will encourage developers to take a look at MeshCentral for more usages and review its security in detail. MeshCentral’s use of modern web technologies make it a unique and amazing solution for remote management of computers. As with any good software, MeshCentral will continue to be updated and evolve.
|
||||
|
||||
## License
|
||||
|
||||
MeshCentral and this document are both opens source and licensed using Apache 2.0, the full license can be found at [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
## PDF and ODT handout(s).
|
||||
|
||||
[MeshCentral Guide](https://meshcentral.com/docs/MeshCentral2UserGuide.pdf)
|
||||
|
||||
MeshCmd Guide [as .pdf](https://meshcentral.com/docs/MeshCmdUserGuide.pdf) [as .odt](https://github.com/Ylianst/MeshCentral/blob/master/docs/MeshCentral User's Guide v0.2.9.odt?raw=true)
|
||||
@ -1,56 +1,99 @@
|
||||
# Contribute to MeshCentral
|
||||
# Contribute to MeshCentral
|
||||
|
||||
## Contributing to MeshCentral via GitHub Pull Request
|
||||
---
|
||||
## 📤 Contributing to MeshCentral via GitHub Pull Request
|
||||
|
||||
If you're looking to contribute beyond translations, such as updating documentation or enhancing the software by adding features or fixing bugs, the process involves several key steps:
|
||||
If you're looking to contribute beyond translations, such as updating documentation or enhancing the software by adding features or fixing bugs, the process involves several key steps :
|
||||
|
||||
1. **Fork the Repository:** Start by forking the [MeshCentral](https://github.com/Ylianst/MeshCentral) repository on GitHub. This creates a copy of the repository under your own GitHub account, allowing you to make changes without affecting the original project.
|
||||
1. **Fork the Repository :**
|
||||
|
||||
> Start by forking the [MeshCentral](https://github.com/Ylianst/MeshCentral) repository on GitHub.
|
||||
|
||||
> This creates a copy of the repository under your own GitHub account, allowing you to make changes without affecting the original project.
|
||||
|
||||
2. **Make Your Changes**
|
||||
- In your forked repository, create a new branch to keep your changes organized. This helps in managing different contributions separately.
|
||||
- Make the necessary changes in your repository. This could involve updating documentation files or modifying code to add new features or fix bugs.
|
||||
|
||||
3. **Review Your Changes:** Before submitting your work, carefully review the changes you’ve made. Check the "Files Changed" section on GitHub to ensure that all modifications are intended and correctly implemented.
|
||||
> - In your forked repository, create a new branch to keep your changes organized. This helps in managing different contributions separately.
|
||||
|
||||
> - Make the necessary changes in your repository. This could involve updating documentation files or modifying code to add new features or fix bugs.
|
||||
|
||||
3. **Review Your Changes :**
|
||||
|
||||
> Before submitting your work, carefully review the changes you’ve made. Check the "Files Changed" section on GitHub to ensure that all modifications are intended and correctly implemented.
|
||||
|
||||
4. **Submit a Pull Request**
|
||||
- Once your changes are ready and reviewed, submit a pull request (PR) from your branch to the `master` branch of the main MeshCentral repository.
|
||||
- When creating the pull request, provide a clear and detailed description of what changes have been made and why. This helps maintainers understand the purpose of your contributions.
|
||||
|
||||
5. **Wait for Review:** After submitting your pull request, wait for a project maintainer to review your contribution. Review time can vary depending on the complexity of the changes and the availability of the maintainers.
|
||||
> - Once your changes are ready and reviewed, submit a pull request (PR) from your branch to the `master` branch of the main MeshCentral repository.
|
||||
> - When creating the pull request, provide a clear and detailed description of what changes have been made and why. This helps maintainers understand the purpose of your contributions.
|
||||
|
||||
6. **Respond to Feedback:** The maintainer may request further modifications or provide feedback on your pull request. Be prepared to make additional changes based on their suggestions to ensure that your contribution meets the project’s standards and requirements.
|
||||
5. **Wait for Review :**
|
||||
|
||||
7. **Final Steps:** Once your pull request is approved and merged by a maintainer, your contributions will be incorporated into the MeshCentral project. Congratulations, and thank you for helping improve MeshCentral!
|
||||
> After submitting your pull request, wait for a project maintainer to review your contribution. Review time can vary depending on the complexity of the changes and the availability of the maintainers.
|
||||
|
||||
6. **Respond to Feedback :**
|
||||
|
||||
> The maintainer may request further modifications or provide feedback on your pull request. Be prepared to make additional changes based on their suggestions to ensure that your contribution meets the project’s standards and requirements.
|
||||
|
||||
7. **Final Steps :**
|
||||
|
||||
> Once your pull request is approved and merged by a maintainer, your contributions will be incorporated into the MeshCentral project. Congratulations, and thank you for helping improve MeshCentral!
|
||||
|
||||
---
|
||||
|
||||
## Contribute to MeshCentral's Multilingual Support
|
||||
## 🗣️ Contribute to MeshCentral's Multilingual Support
|
||||
|
||||
To make MeshCentral multilingual, your contributions are crucial. Follow these steps to translate the interface into various languages.
|
||||
|
||||
1. **Remove Local Translations:** Delete `translate.json` from your `meshcentral-data` folder. This file contains your local copy of translations, which may become outdated as new features and texts are added.
|
||||
1. **Remove Local Translations :**
|
||||
|
||||
2. **Access MeshCentral:** Ensure you are logged into MeshCentral.
|
||||
3. **Open Translation Tool:** Visit `https://YOURMESHCENTRALSERVER.COM/translator.htm` to access the translation interface.
|
||||
4. **Choose a Language:** Select the language you wish to translate from the list provided.
|
||||
> Delete `translate.json` from your `meshcentral-data` folder. This file contains your local copy of translations, which may become outdated as new features and texts are added.
|
||||
|
||||
5. **Translate Text:** Use the search function or scroll through the list to find text segments you want to translate. Utilize the "show no translations only" checkbox to filter untranslated texts.
|
||||
6. **Enter Translations:** For each text segment, enter your translation in the bottom box (not the top one) and click `SET (F1)`.
|
||||
7. **Repeat Translation:** Continue translating by repeating steps 5 and 6 for other texts as desired.
|
||||
2. **Access MeshCentral :**
|
||||
|
||||
> Ensure you are logged into MeshCentral.
|
||||
|
||||
3. **Open Translation Tool:**
|
||||
|
||||
> Visit `https://YOURMESHCENTRALSERVER.COM/translator.htm` to access the translation interface.
|
||||
|
||||
4. **Choose a Language :**
|
||||
|
||||
> Select the language you wish to translate from the list provided.
|
||||
|
||||
5. **Translate Text :**
|
||||
|
||||
> Use the search function or scroll through the list to find text segments you want to translate. Utilize the "show no translations only" checkbox to filter untranslated texts.
|
||||
|
||||
6. **Enter Translations :**
|
||||
|
||||
> For each text segment, enter your translation in the bottom box (not the top one) and click `SET (F1)`.
|
||||
|
||||
7. **Repeat Translation :** Continue translating by repeating steps 5 and 6 for other texts as desired.
|
||||
|
||||
8. **Save and Apply Translations**
|
||||
- Click `SAVE TO SERVER (F3)` to save your translations to `meshcentral-data/translate.json` locally in your MeshCentral server.
|
||||
- Optionally, click `SAVE TO FILE (F4)` to download the `translate.json` file for offline review or sharing.
|
||||
|
||||
9. **Deploy Translations:** Click `TRANSLATE SERVER` and allow some time for the process to complete (approximately 5-15 minutes depending on server specifications). This command line output will indicate when the translation is complete.
|
||||

|
||||
> - Click `SAVE TO SERVER (F3)` to save your translations to `meshcentral-data/translate.json` locally in your MeshCentral server.
|
||||
> - Optionally, click `SAVE TO FILE (F4)` to download the `translate.json` file for offline review or sharing.
|
||||
|
||||
10. **Finalize Changes:** It’s crucial to restart MeshCentral to ensure that the translated files are picked up correctly.
|
||||
11. **Share your translations:** Once a language translation is complete, take the latest `translation.json` and share it by emailing it to the maintainer (Ylianst, `ylianst@gmail.com`) or by submitting it to the MeshCentral GitHub repository via a pull request.
|
||||
9. **Deploy Translations :**
|
||||
|
||||
> Click `TRANSLATE SERVER` and allow some time for the process to complete (approximately 5-15 minutes depending on server specifications). This command line output will indicate when the translation is complete.
|
||||
|
||||
> 
|
||||
|
||||
10. **Finalize Changes :**
|
||||
|
||||
> It’s crucial to restart MeshCentral to ensure that the translated files are picked up correctly.
|
||||
|
||||
11. **Share your translations :**
|
||||
|
||||
> Once a language translation is complete, take the latest `translation.json` and share it by emailing it to the maintainer (Ylianst, `ylianst@gmail.com`) or by submitting it to the MeshCentral GitHub repository via a pull request.
|
||||
|
||||
---
|
||||
|
||||
#### Additional Information:
|
||||
- If you make any changes to `default.handlebars`, run the translate server to propagate these modifications to the language-specific handlebar files located in `node_modules/meshcentral/views/translations`.
|
||||
!!! note
|
||||
Additional Information :
|
||||
|
||||
If you make any changes to `default.handlebars`, run the translate server to propagate these modifications to the language-specific handlebar files located in `node_modules/meshcentral/views/translations`.
|
||||
|
||||
By following these steps, you help MeshCentral support any language you choose, making it more accessible worldwide. By sharing your translations with us, you also help make these languages available to other users, improving the community and extending the software's reach.
|
||||
|
||||
@ -4,60 +4,68 @@
|
||||
|
||||
MeshCentral is a full computer management web site. With MeshCentral, you can run your own web server to remotely manage and control computers on a local network or anywhere on the internet. Once you get the server started, create device group and download and install an agent on each computer you want to manage. A minute later, the new computer will show up on the web site and you can take control of it. MeshCentral includes full web-based remote desktop, terminal and file management capability.
|
||||
|
||||
For more information, [visit MeshCentral.com](https://www.meshcentral.com/).
|
||||
For more information, [visit MeshCentral.com](https://meshcentral.com).
|
||||
|
||||
## Social Media
|
||||
## 🌐 Social Media
|
||||
|
||||
[YouTube](https://www.youtube.com/channel/UCJWz607A8EVlkilzcrb-GKg/videos)
|
||||
 [YouTube](https://www.youtube.com/channel/UCJWz607A8EVlkilzcrb-GKg/videos)
|
||||
 [Reddit](https://www.reddit.com/r/MeshCentral/)
|
||||
 [Telegram](https://t.me/meshcentral)
|
||||
 [Discord](https://discord.gg/wF9UT3Vjdj)
|
||||
 [BlueSky](https://bsky.app/profile/meshcentral.bsky.social)
|
||||
 [BlogSpot](https://meshcentral2.blogspot.com/)
|
||||
|
||||
[Reddit](https://www.reddit.com/r/MeshCentral/)
|
||||
## 📚 Documentation
|
||||
|
||||
[BlueSky](https://bsky.app/profile/meshcentral.bsky.social)
|
||||
The [User's Guide](meshcentral/index.md) contains information every administrator should know including usage, the server configuration file, databases, TLS offloading, Lets Encrypt, IP Filtering, Email setup, embedding, server port aliasing, reverse proxy setup, multi factor authentication, branding & terms of use, HashiCorp Vault support, and SSO.
|
||||
|
||||
[BlogSpot](https://meshcentral2.blogspot.com/)
|
||||
The [Installation Guide](install/install.md) has detailed instructions for installing the MeshCentral Server on Windows 8.1, Windows 10, Windows 2012 R2, Amazon Linux 2, Raspberry Pi, Microsoft Azure, Google Cloud, Ubuntu 18, Ubuntu 16 and OpenBSD.
|
||||
|
||||
## Documentation
|
||||
The [Design and Architecture Guide](design/index.md) is a short document that includes information on the design overview, dependencies, source code descriptions of each file, certificates, TLS security, the agent to server handshake, browser to agent relay and WebRTC and the messenger service.
|
||||
|
||||
The [User's Guide](meshcentral) contains information every administrator should know including usage, the server configuration file, databases, TLS offloading, Lets Encrypt, IP Filtering, Email setup, embedding, server port aliasing, reverse proxy setup, multi factor authentication, branding & terms of use, HashiCorp Vault support, and SSO.
|
||||
## 📺 Video Tutorials
|
||||
|
||||
The [Installation Guide](install/install2.md) has detailed instructions for installing the MeshCentral Server on Windows 8.1, Windows 10, Windows 2012 R2, Amazon Linux 2, Raspberry Pi, Microsoft Azure, Google Cloud, Ubuntu 18, Ubuntu 16 and OpenBSD.
|
||||
You can watch many tutorial videos on the [MeshCentral YouTube Channel](https://www.youtube.com/channel/UCJWz607A8EVlkilzcrb-GKg/videos). Here are some essential ones to get you started :
|
||||
|
||||
The [Design and Architecture Guide](design) is a short document that includes information on the design overview, dependencies, source code descriptions of each file, certificates, TLS security, the agent to server handshake, browser to agent relay and WebRTC and the messenger service.
|
||||
**[MeshCentral - Installation](https://www.youtube.com/results?search_query=MeshCentral+Installation)**
|
||||
Installing MeshCentral on **Windows**, **Linux**, and **macOS**.
|
||||
|
||||
## Video Tutorials
|
||||
|
||||
You can watch many tutorial videos on the [MeshCentral YouTube Channel](https://www.youtube.com/channel/UCJWz607A8EVlkilzcrb-GKg/videos). Two videos to get started involve installation and basic usages.
|
||||
**[MeshCentral - Basics](https://www.youtube.com/results?search_query=MeshCentral+Basics)**
|
||||
Learn how to install the agent and use remote **desktop**, **terminal**, and **file access** features.
|
||||
|
||||
Installing MeshCentral on Windows, Linux and macOS.
|
||||
[MeshCentral - Installation](https://www.youtube.com/watch?v=GsQbWZmRRAU)
|
||||
|
||||
Basic Usages including installing the agent and remote desktop, terminal and file access.
|
||||
[MeshCentral - Basics](https://www.youtube.com/watch?v=D9Q7M7PdTg0)
|
||||
**[MeshCentral - Two Factor Authentication](https://www.youtube.com/results?search_query=MeshCentral+Two+Factor+Authentication)**
|
||||
Secure your MeshCentral instance with **two-factor authentication**.
|
||||
|
||||
MeshCentral support for two-factor authentication.
|
||||
[MeshCentral - Two Factor Authentication](https://www.youtube.com/watch?v=luLZKcma9l0)
|
||||
|
||||
How to setup MeshCentral with the NGINX reverse proxy.
|
||||
[MeshCentral - NGINX Reverse Proxy](https://www.youtube.com/watch?v=YSmiLyKSX2I)
|
||||
**[MeshCentral - NGINX Reverse Proxy](https://www.youtube.com/results?search_query=MeshCentral+NGINX+Reverse+Proxy)**
|
||||
Configure MeshCentral with an **NGINX reverse proxy** for better security and scalability.
|
||||
|
||||
Installing and using the MeshCentral Android agent.
|
||||
[MeshCentral - Android](https://www.youtube.com/watch?v=wi1HYdW00Bk)
|
||||
|
||||
Using MeshCentral Router to port map TCP connections.
|
||||
[MeshCentral - Basics](https://www.youtube.com/watch?v=BubeVRmbCRM)
|
||||
**[MeshCentral - Android](https://www.youtube.com/results?search_query=MeshCentral+Android)**
|
||||
Install and use the **MeshCentral Android agent** for mobile device management.
|
||||
|
||||
## Feedback
|
||||
|
||||
If you encounter a problem or have a suggestion to improve the product, you may file an [issue report](https://github.com/Ylianst/MeshCentral/issues/)
|
||||
**[MeshCentral - Basics](https://www.youtube.com/results?search_query=MeshCentral+Router+Port+Mapping)**
|
||||
Use **MeshCentral Router** to **port map TCP connections** securely.
|
||||
|
||||
|
||||
## 💬 Feedback
|
||||
|
||||
If you encounter a problem or have a suggestion to improve the product, you may file an [GitHub Issue](https://github.com/Ylianst/MeshCentral/issues/).<br>
|
||||
If you are filing a problem report, you should include:
|
||||
|
||||
* The version of the software you are using
|
||||
* The Operating System and version
|
||||
* The observed output
|
||||
* The expected output
|
||||
* Any troubleshooting you took to resolve the issue yourself
|
||||
* Any other similar reports~~
|
||||
* The version of the software you are using.
|
||||
> For example: 1.1.46
|
||||
* The Operating System and version.
|
||||
> For example: Debian 12
|
||||
* Any troubleshooting you took to resolve the issue yourself.
|
||||
> For example: Reinstalling MeshCentral (including OS)
|
||||
* Any other similar reports.
|
||||
> For example: other GitHub issues.
|
||||
* The observed output.
|
||||
* The expected output.
|
||||
|
||||
If you are having issues with the following other products, you should file a report on their respective issue pages
|
||||
[MeshAgent](https://github.com/Ylianst/MeshAgent/issues)
|
||||
|
||||
16
docs/docs/install/abstract.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Installation
|
||||
|
||||
## 🧾 Abstract
|
||||
|
||||
These guides are specifically intended to help users install and configure MeshCentral.<br>
|
||||
Once installed, you can take a look at the MeshCentral user’s guide,<br>
|
||||
for information on how to configure MeshCentral for your specific use.<br>
|
||||
In this document, we will look at installing MeshCentral on different operating systems like:
|
||||
|
||||
And remember! The `config.json` is case insensitive in its keys.
|
||||
|
||||
- 📢 **[Quick-start](./quickstart.md)**
|
||||
|
||||
- 🧐 **[Advanced Information](./advanced.md)**
|
||||
|
||||
- 🪟 **[Windows-specific](./windows.md)**
|
||||
91
docs/docs/install/advanced.md
Normal file
@ -0,0 +1,91 @@
|
||||
# 📦 NPM Installation for Advanced Users
|
||||
|
||||

|
||||
|
||||
## Prerequisites and Verification
|
||||
|
||||
Before beginning the installation, ensure **Node.js** and **NPM** (Node Package Manager) are installed on your host operating system.
|
||||
|
||||
If your server is behind an HTTP/HTTPS proxy, you may need to configure NPM's proxy settings.
|
||||
|
||||
### 1\. Verify Node.js and NPM
|
||||
|
||||
Open your command-line terminal (CMD/PowerShell on Windows, or Shell on Linux) and run the following commands to check the installed versions:
|
||||
|
||||
* **Node.js:**
|
||||
```shell
|
||||
node -v
|
||||
```
|
||||
* **NPM:**
|
||||
```shell
|
||||
npm -v
|
||||
```
|
||||
|
||||
-----
|
||||
|
||||
### 2\. Configure Proxy Settings (If Applicable)
|
||||
|
||||
If your server requires a proxy to access the internet, you must set the proxy configurations for NPM. **Skip this step if not needed.**
|
||||
|
||||
```shell
|
||||
# Set HTTP proxy
|
||||
npm config set proxy http://proxy.com:88
|
||||
# Set HTTPS proxy
|
||||
npm config set https-proxy http://proxy.com:88
|
||||
```
|
||||
|
||||
-----
|
||||
|
||||
## MeshCentral Installation
|
||||
|
||||
### 3\. Install MeshCentral
|
||||
|
||||
Create a dedicated directory for the installation, change into it, and use NPM to install the MeshCentral package.
|
||||
|
||||
**Recommendation:** On Linux, use the `/opt` directory.
|
||||
|
||||
> ⚠️ **Important:** Do not use `sudo` when executing the `npm install meshcentral` command.
|
||||
|
||||
```shell
|
||||
# Create the directory
|
||||
mkdir -p /opt/meshcentral
|
||||
# Move into the directory
|
||||
cd /opt/meshcentral
|
||||
# Install MeshCentral
|
||||
npm install meshcentral
|
||||
```
|
||||
|
||||
-----
|
||||
|
||||
### 4\. Start the Server
|
||||
|
||||
Once the download is complete, start the MeshCentral server.
|
||||
|
||||
> ⚠️ **Crucial:** **Do not** `cd` into the `node_modules/meshcentral` directory to run the server. Running it from the directory **above** `node_modules` is required for features like auto-install and self-update to function correctly.
|
||||
|
||||
```shell
|
||||
node node_modules/meshcentral [arguments]
|
||||
```
|
||||
|
||||
> **LAN-Only Mode:** If you run the command without arguments, MeshCentral will default to **LAN-only mode**, meaning you can only manage computers on the local network.
|
||||
|
||||
-----
|
||||
|
||||
### 5\. Configure for WAN/Internet Access (Optional)
|
||||
|
||||
To manage computers over the internet (**WAN** or **Hybrid Mode**), your server needs a **static IP** or a **DNS record** that resolves to its public address. This is how remote mesh agents "call home."
|
||||
|
||||
While command-line parameters exist, it's **highly recommended to use a configuration file** for persistent settings.
|
||||
|
||||
Here are examples of starting the server and generating initial certificates for a public address:
|
||||
|
||||
```shell
|
||||
# Using a domain name
|
||||
node node_modules/meshcentral --cert servername.domain.com
|
||||
# Using an IP address
|
||||
node node_modules/meshcentral --cert 1.2.3.4
|
||||
```
|
||||
|
||||
> **Note:** The first time you run in WAN or Hybrid Mode, MeshCentral will generate necessary **certificates**, which may take a few minutes.
|
||||
|
||||
Once running, immediately create your **admin account** by navigating to `https://127.0.0.1` (or your public hostname) in a web browser.
|
||||
109
docs/docs/install/container.md
Normal file
@ -0,0 +1,109 @@
|
||||
# 🐳 Container (OCI-specification).
|
||||
|
||||
[Open Container Initiative](https://opencontainers.org/)
|
||||
|
||||
The following section explains possible ways to install MeshCentral locally with the use of Docker or Podman.
|
||||
For the syntax, docker will be used as default. This is done because podman also supports this syntax.<br>
|
||||
|
||||
🔗 References:
|
||||
|
||||
- [Docker](https://www.docker.com/)
|
||||
- [Podman](https://podman.io/)
|
||||
|
||||
!!!warning
|
||||
Do not use the built-in MeshCentral update functionality (when using containers).<br>
|
||||
Update the container the 'docker way', by updating the image itself.
|
||||
|
||||
### 🏷️ Basic Tags:
|
||||
|
||||
| Tag-name | Explanation |
|
||||
|--------|-----|
|
||||
| `master` | This tag belongs to the image which is built on every new commit to the main branch, therefor it has the latest code. |
|
||||
| `latest` | This tag takes the latest released version of MeshCentral. |
|
||||
| `1.1.51` | You can also specify the specific MeshCentral release with its tag, for example: `ghcr.io/ylianst/meshcentral:1.1.43` |
|
||||
|
||||
### All Tags
|
||||
|
||||
All master tags below follow the master branch of MeshCentral, the latest and version numbered versions follow the releases.
|
||||
|
||||
| Tag-name | Explanation |
|
||||
| -------- | ----------- |
|
||||
| `master-slim` | Docker image with no database packages present, which makes it the most lean. Uses NeDB. |
|
||||
| `master-mongodb` | Docker image with the MongoDB packages installed. |
|
||||
| `master-postgresql` | Docker image with the PostgreSQL packages installed |
|
||||
| `master-mysql` | Docker image with the MySQL packages installed |
|
||||
| `1.1.51-slim` and `latest-slim` | Docker image with no database packages present, which makes it the most lean. Uses NeDB. |
|
||||
| `1.1.51-mongodb` and `latest-mongodb` | Docker image with the MongoDB packages installed. |
|
||||
| `1.1.51-postgresql` and `latest-postgresql` | Docker image with the PostgreSQL packages installed. |
|
||||
| `1.1.51-mysql` and `latest-mysql` | Docker image with the MySQL packages installed. |
|
||||
|
||||
---
|
||||
> **📌 Note:**
|
||||
Refer to [this page](https://github.com/Ylianst/MeshCentral/pkgs/container/meshcentral) for more information on the container status.
|
||||
---
|
||||
|
||||
## 🐋 Docker/Podman
|
||||
|
||||
For single-machine setups such as Docker and Podman.
|
||||
|
||||
### Pulling the image:
|
||||
|
||||
To pull the container image use the following container registry.
|
||||
|
||||
```sh
|
||||
docker pull ghcr.io/ylianst/meshcentral:latest
|
||||
```
|
||||
|
||||
### Docker CLI:
|
||||
|
||||
If you want to run the container from the Terminal, you can use the following command:
|
||||
|
||||
```sh linenums="1"
|
||||
docker run -d \
|
||||
--name meshcentral \
|
||||
--restart unless-stopped \
|
||||
-p 80:80 \
|
||||
-p 443:443 \
|
||||
-v data:/opt/meshcentral/meshcentral-data \
|
||||
-v user_files:/opt/meshcentral/meshcentral-files \
|
||||
-v backup:/opt/meshcentral/meshcentral-backups \
|
||||
-v web:/opt/meshcentral/meshcentral-web \
|
||||
ghcr.io/ylianst/meshcentral:latest
|
||||
```
|
||||
|
||||
### Docker Compose:
|
||||
|
||||
If you want to use a docker compose yaml file, please refer to the example below.
|
||||
|
||||
```yaml linenums="1"
|
||||
services:
|
||||
meshcentral:
|
||||
image: ghcr.io/ylianst/meshcentral:latest
|
||||
environment:
|
||||
- DYNAMIC_CONFIG=false # Show the option but disable it by default, for safety.
|
||||
volumes:
|
||||
- meshcentral-data:/opt/meshcentral/meshcentral-data
|
||||
- meshcentral-files:/opt/meshcentral/meshcentral-files
|
||||
- meshcentral-web:/opt/meshcentral/meshcentral-web
|
||||
- meshcentral-backups:/opt/meshcentral/meshcentral-backups
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
meshcentral-data:
|
||||
meshcentral-files:
|
||||
meshcentral-web:
|
||||
meshcentral-backups:
|
||||
```
|
||||
|
||||
Refer to [the Dockerfile](https://github.com/Ylianst/MeshCentral/blob/5032755c2971955161105922e723461385a6c874/docker/Dockerfile#L70-L123) for its environment variables.
|
||||
|
||||
## ☸️ Kubernetes
|
||||
|
||||
###
|
||||
|
||||
> Using YAML deployment files.
|
||||
|
||||
## 📚 Extra sources
|
||||
|
||||
> [Github Docker Resources](https://github.com/Ylianst/MeshCentral/tree/master/docker)
|
||||
52
docs/docs/install/database/local.md
Normal file
@ -0,0 +1,52 @@
|
||||
# This section will go into how to configure a local database as backend.
|
||||
|
||||
Following [the schema](https://github.com/Ylianst/MeshCentral/blob/master/meshcentral-config-schema.json) we make the following changes to our `config.json`.<br>
|
||||
Some requires keys have been omitted to further the focus on database configuration. Don't remove these as well.
|
||||
|
||||
By default MeshCentral uses NeDB so therefor to change that to another database type, do the following:
|
||||
|
||||
---
|
||||
|
||||
### MeshCentral Cheatsheet:
|
||||
|
||||
Sqlite3:
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json",
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
"settings": {
|
||||
"sqlite3": {
|
||||
"name": "meshcentral-db"
|
||||
}
|
||||
},
|
||||
"domains": {
|
||||
"": {
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
}
|
||||
},
|
||||
"_letsencrypt": {
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Acebase:
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json",
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
"settings": {
|
||||
"acebase": {
|
||||
"sponsor": false
|
||||
}
|
||||
},
|
||||
"domains": {
|
||||
"": {
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
}
|
||||
},
|
||||
"_letsencrypt": {
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
}
|
||||
}
|
||||
```
|
||||
84
docs/docs/install/database/mariadb.md
Normal file
@ -0,0 +1,84 @@
|
||||
# This section will go into how to configure MySQL/MariaDB as a database backend.
|
||||
|
||||
Following [the schema](https://github.com/Ylianst/MeshCentral/blob/master/meshcentral-config-schema.json) we make the following changes to our `config.json`.<br>
|
||||
Some requires keys have been omitted to further the focus on database configuration. Don't remove these as well.
|
||||
|
||||
---
|
||||
|
||||
### MeshCentral Cheatsheet:
|
||||
|
||||
Database specific:
|
||||
|
||||
MariaDB:
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json",
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
"settings": {
|
||||
"mariaDB": {
|
||||
"host": "my-mariadb-hostname",
|
||||
"port": "3306",
|
||||
"user": "my-mariadb-user",
|
||||
"password": "my-mariadb-password",
|
||||
"database": "meshcentral-database"
|
||||
}
|
||||
},
|
||||
"domains": {
|
||||
"": {
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
}
|
||||
},
|
||||
"_letsencrypt": {
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Mysql:
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json",
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
"settings": {
|
||||
"mySQL": {
|
||||
"host": "my-mysql-hostname",
|
||||
"port": "3306",
|
||||
"user": "my-mysql-user",
|
||||
"password": "my-mysql-password",
|
||||
"database": "meshcentral-database"
|
||||
}
|
||||
},
|
||||
"domains": {
|
||||
"": {
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
}
|
||||
},
|
||||
"_letsencrypt": {
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### MariaDB/MySQL Cheatsheet:
|
||||
|
||||
```bash
|
||||
mariadb -u root -p
|
||||
```
|
||||
or
|
||||
```bash
|
||||
mysql -u root -p
|
||||
```
|
||||
|
||||
```sql
|
||||
-- Create the database
|
||||
CREATE DATABASE meshcentral;
|
||||
|
||||
-- Create the user (restricting login to localhost)
|
||||
CREATE USER 'meshcentral'@'localhost' IDENTIFIED BY 'my-very-secure-password';
|
||||
|
||||
-- Grant privileges
|
||||
GRANT ALL PRIVILEGES ON meshcentral.* TO 'meshcentral'@'localhost';
|
||||
|
||||
-- Apply changes
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
28
docs/docs/install/database/mongodb.md
Normal file
@ -0,0 +1,28 @@
|
||||
# This section will go into how to configure MongoDB as a database backend.
|
||||
|
||||
Following [the schema](https://github.com/Ylianst/MeshCentral/blob/master/meshcentral-config-schema.json) we make the following changes to our `config.json`.<br>
|
||||
Some requires keys have been omitted to further the focus on database configuration. Don't remove these as well.
|
||||
|
||||
---
|
||||
|
||||
### MeshCentral Cheatsheet:
|
||||
|
||||
MongoDB is configured using the MongoDB connection string.
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json",
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
"settings": {
|
||||
"mongoDb": "mongodb://localhost:27017/meshcentral"
|
||||
},
|
||||
"domains": {
|
||||
"": {
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
}
|
||||
},
|
||||
"_letsencrypt": {
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
}
|
||||
}
|
||||
```
|
||||
57
docs/docs/install/database/postgresql.md
Normal file
@ -0,0 +1,57 @@
|
||||
# This section will go into how to configure PostgreSQL as a database backend.
|
||||
|
||||
Following [the schema](https://github.com/Ylianst/MeshCentral/blob/master/meshcentral-config-schema.json) we make the following changes to our `config.json`.<br>
|
||||
Some requires keys have been omitted to further the focus on database configuration. Don't remove these as well.
|
||||
|
||||
---
|
||||
|
||||
### MeshCentral Cheatsheet:
|
||||
|
||||
The postgres installation inside `settings` is rather straightforward if you are familiar with it on MeshCentral its side.
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/Ylianst/MeshCentral/master/meshcentral-config-schema.json",
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
"settings": {
|
||||
"postgres": {
|
||||
"host": "my-postgresql-hostname",
|
||||
"port": "5432",
|
||||
"user": "my-postgresql-user",
|
||||
"password": "my-postgresql-password",
|
||||
"database": "meshcentral-database"
|
||||
}
|
||||
},
|
||||
"domains": {
|
||||
"": {
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
}
|
||||
},
|
||||
"_letsencrypt": {
|
||||
"__comment__": "Omitted these keys to focus on the database",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> More options are available if needed. Refer to the schema above.
|
||||
|
||||
### Postgres Cheatsheet
|
||||
|
||||
```bash
|
||||
# Log into the server
|
||||
psql -U postgres
|
||||
```
|
||||
|
||||
```sql
|
||||
|
||||
-- Create the database user
|
||||
postgres=# CREATE USER meshcentral WITH PASSWORD 'your-very-strong-password';
|
||||
CREATE ROLE
|
||||
|
||||
-- Create the database and set the above user as owner
|
||||
postgres=# CREATE DATABASE meshcentral OWNER meshcentral;
|
||||
CREATE DATABASE
|
||||
|
||||
-- Exit the database
|
||||
postgres=# exit
|
||||
```
|
||||
BIN
docs/docs/install/images/2022-05-16-23-45-01.jpg
Normal file
|
After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 358 KiB |
BIN
docs/docs/install/images/2022-05-16-23-47-10.jpg
Normal file
|
After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 216 KiB |
BIN
docs/docs/install/images/2022-05-16-23-47-36.jpg
Normal file
|
After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 179 KiB |
BIN
docs/docs/install/images/2022-05-16-23-53-08.jpg
Normal file
|
After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
BIN
docs/docs/install/images/2022-05-17-00-01-10.jpg
Normal file
|
After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 341 KiB |
BIN
docs/docs/install/images/2022-05-17-00-01-52.jpg
Normal file
|
After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 326 KiB |
BIN
docs/docs/install/images/2022-05-17-00-02-25.jpg
Normal file
|
After Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 282 KiB |
BIN
docs/docs/install/images/2022-05-17-00-03-59.jpg
Normal file
|
After Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 173 KiB |
BIN
docs/docs/install/images/2022-05-17-00-19-19.jpg
Normal file
|
After Width: | Height: | Size: 80 KiB |