Self host Meshcentral with docker, traefik and mongodb

One of my friends (non-tech dude) have a signage side hustle where he have screens + android devices that shows localized ads. He is trying to transition from a paid signage service that is eating too much of his revenue to use other, preferable free options. I've been impressed by how has solved this problem so far by using google drive as file delivery, google apps script for logic and a free apk as signage software. But these android boxes aren't necessarily the most reliable, so he need a way to remotely access these devices. TeamViewer was used earlier, but that was still somewhat expensive.

After talking to him I offered to look for a free alternative and found Meshcentral, an open source, multi-platform, self-hosted program for remote device management. Perfect.

The problem

I have a VPS running so I told him will try to set it up and just have it running there for him.

  1. Meshcentral needs to run in docker
  2. Meshcentral needs to be behind my existing Traefik reverse proxy
  3. Need to be able to connect to devices (obviously)

I will not go into detail, but just provide the solution. The only preq is docker/docker-compose.

Taefik setup

I USE VERSION 2.0 BECAUSE THIS CONFIG IS A COUPLE YEARS OLD AND ICBA TO UPDATE IT TO THE NEWEST VERSION

This is a plain Traefik config with docker-compose with https upgrade and automatic certification generation via letsencrypt.

# docker-compose-traefik.yml
version: "3"
services:
     traefik:
          image: traefik:v2.0
          restart: always
          container_name: traefik
          ports:
               - "80:80" # http
               - "443:443" # https
          command:
               ## Provider Settings - https://docs.traefik.io/providers/docker/#provider-configuration ##
               - --providers.docker=true # Set docker as the provider for traefik
               - --providers.docker.exposedbydefault=false # You need to whitelist containers that will be exposed to traefik
               - --providers.file.filename=/dynamic.yaml # Referring to the https upgrade middleware file
               - --providers.docker.network=web # Use the docker network web for communication between traefik and containser
               ## Entrypoints Settings - https://docs.traefik.io/routing/entrypoints/#configuration ##
               - --entrypoints.web.address=:80 # Define an entrypoint for port :80 named web (this can be whatever)
               - --entrypoints.web-secured.address=:443 # Define an entrypoint for https on port :443 named web-secured (this can be whatever)
               ## Certificate Settings (Let's Encrypt) -  https://docs.traefik.io/https/acme/#configuration-examples ##
               - --certificatesresolvers.mytlschallenge.acme.tlschallenge=true
               - --certificatesresolvers.mytlschallenge.acme.email=YOUREMAILHERE # Your email
               - --certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json
          volumes:
               - ./letsencrypt:/letsencrypt # Volume for certs (TLS)
               - /var/run/docker.sock:/var/run/docker.sock # Volume for docker admin
               - ./dynamic.yaml:/dynamic.yaml # Volume for dynamic conf file, **ref: line 14
          networks:
               - web # Tell the container that it has access to this network

networks:
     web:
          external: true
# dynamic.yml
# Middleware for redirect to https
http:
     middlewares:
          redirect:
               redirectScheme:
                    scheme: https

To run traefik in the background run the command

docker-compose -f docker-compose-traefik.yml up -d

Meshcentral set up

Everything you need to set up meshcentral in docker is in this MeshCentral repo. If you follow this, you will have a running meshcentral, but not behind a reverse proxy.

Since we are not autogenerating the config, this is what we will create the minimum folder structure we need for meshcentral.

| - meshcentral/        # this folder contains the persistent data
  | - data/config.json  # MeshCentral config file
| - docker-compose-meshcentral.yml # Compose file
| - .env

We do not really need the .env file, we can inline it inside the compose file. But I like to seperate the concerns. The only function the .env file is to initiate the database.

# .env
NODE_ENV=production

# initial mongodb-variables
MONGO_INITDB_ROOT_USERNAME=mongodbadmin
MONGO_INITDB_ROOT_PASSWORD=mongodbpasswd
// meshcentral/data/config.json
{
     "$schema": "http://info.meshcentral.com/downloads/meshcentral-config-schema.json",
     "settings": {
          "plugins": { "enabled": false },
          "mongoDb": "mongodb://USERNAME:PASSWORD@mongodb:27017",
          "_WANonly": true,
          "_LANonly": true,
          "_sessionKey": "WHATEVER PASSORD",
          "TLSOffload": true, // Since we are generating cert with traefik we tell meshcentral to not se TLS
          "SelfUpdate": false,
          "AllowFraming": false,
          "WebRTC": false,
          "Cert": "mesh.example.com", // <-- Change: This is the same as the hostname for
          "Port": 4430,
          "AliasPort": 443,
          "RedirPort": 800,
          "_redirAliasPort": 80,
          "TlsOffload": "111.22.333.444" // <-- Change: IP of your server / VPS
     },
     "domains": {
          "": {
               "_title": "Title1",
               "_title2": "Title 2",
               "minify": true,
               "NewAccounts": true,
               "localSessionRecording": false,
               "_userNameIsEmail": true,
               "certUrl": "mesh.example.com", // <-- Change, same as Cert in settings
               "agentConfig": ["webSocketMaskOverride=1"] // This is what enables websockets for remote access
          }
     }
}
# docker-compose-meshcentral.yml
version: "3"

networks:
     meshcentral-tier:
          driver: bridge
     web:
          external: true

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:
               - 8086:4430
          volumes: # The volumes will be created automaticly if they do not exists. The only directory that should exist when installing fresh is is meshcentral/data
               # 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-backup
               # location for site customization files
               - ./meshcentral/web:/opt/meshcentral/meshcentral-web
          labels:
               - "traefik.enable=true" # Tells Traefik to proxy this container
               - "traefik.http.routers.mesh-web.rule=Host(`mesh.kentare.no`)" # Domain name for http rule
               - "traefik.http.routers.mesh-web.entrypoints=web" # Define the entrypoint for http
               - "traefik.http.routers.mesh-web.middlewares=redirect@file" # This is the  middleware to redirect to https
               - "traefik.http.routers.mesh-secured.rule=Host(`mesh.kentare.no`)" # Domain name for  https rule
               - "traefik.http.routers.mesh-secured.entrypoints=web-secured" # Define the entrypoint for https
               - "traefik.http.routers.mesh-secured.service=mesh-secured" # Define new service named mesh secured on the route
               - "traefik.http.services.mesh-secured.loadbalancer.server.port=4430" # Tell traefik explicitly to use port 4430, traefik did not do this automatically in this case.
               - "traefik.http.routers.mesh-secured.tls.certresolver=mytlschallenge" # How to create certs

          networks:
               - meshcentral-tier
               - web

How to run

  1. Clone or fork this repo: https://github.com/kentare/meshcentral-mongodb-docker-traefik
  2. Edit in this order:
    .env
    ,
    docker-compose-traefik.yml
    ,
    docker-compose-meshcentral.yml
    , and
    meshcentral/data/config.json
  3. Run traefik
    docker-compose -f docker-compose-traefik.yml up -d
  4. Run MeshCentral
    docker-compose -f docker-compose-meshcentral up -d
  5. Go to
    mesh.example.com
    (replace with your url) and create a user. The first user you create will have admin access.

Do you need to know more about Meshcentral you can download the user guide or you can visit the MeshCentral website.

Conclusion

I connected successfully to my laptop from my PC and the remote access is running smoothly. I will also set up a meshcentral server to use myself to help family members when they need IT support from me.

  1. Meshcentral needs to run in docker ✔️
  2. Meshcentral needs to be behind my existing Traefik reverse proxy ✔️
  3. Need to be able to connect to devices (obviously) ✔️