Introduction#
The LEAF (Lab Equipment Adapter Framework) system allows you to process data streams acquired from various equipment and sensors using an adapter interface. The messages are broadcasted through MQTT and can be further processed by any kind of backend.
MAPLE - The Backend Platform#
MAPLE (Modular Architecture for Processing, Logging, and Evaluation) is the official backend companion to LEAF. It handles data storage, processing, and visualization with a modular, extensible architecture.
The backend can have many responsibilities, such as:
Storing time-series data streams
Processing and transforming data
Visualizing data in real-time dashboards
Providing secure data access for analysis
Managing containerized services
MAPLE is composed of several integrated components, including an MQTT broker, flow engine, time-series database, and dashboarding tools. The architecture is designed to be modular and extensible, allowing you to add additional components as needed.
Be aware that this is just an example of a typical backend architecture. For production use, it is recommended to set up a more robust infrastructure with security, backup, and redundancy.
Network Architecture#
The backend uses a dual-network architecture for security and isolation:
Backend Network: Internal network for service-to-service communication
TimescaleDB (port 5432 - internal only)
Redis (port 6379 - internal only)
Service initialization and health checks
Secure internal data processing
Frontend Network: Network for user-facing services and external access
Landing page (port 80)
Grafana (port 3000)
Node-RED (port 1880)
pgAdmin (port 5050)
Portainer (port 9000)
MQTTX Web (port 8090)
LEAF application (port 8887)
Bridge Networks: Services that span both networks
VerneMQ (MQTT broker) - connects backend services to external clients
Node-RED - processes data from backend and provides web interface
Architecture#
The backend is composed of the following components:
Landing Page: Nginx-based web interface providing unified access to all services via http://localhost
VerneMQ: High-performance MQTT broker for IoT messaging
MQTTX Web: Web-based MQTT client for browsing, testing, and debugging MQTT topics
Node-RED: Visual workflow automation and data processing engine
Telegraf: Metrics collection and processing agent for time-series data
TimescaleDB: PostgreSQL-based time-series database optimized for sensor data
Grafana: Data visualization and dashboarding platform
pgAdmin: Web-based database management interface for TimescaleDB
Redis: In-memory key-value store for caching and session management
Portainer: Container management interface for Docker operations
LEAF Application: Web interface for managing LEAF adapters and devices
Keep in mind that the backend is highly modular and can be extended with additional components as needed. The current setup is just an example of a typical backend architecture. Be aware that the backend by default is running on a single device with generated passwords for security and is currently without backup, and redundancy mechanisms. For production use, it is recommended to set up a more robust infrastructure.
Getting Started#
To get started with MAPLE, follow these steps:
Prerequisites#
Docker Engine 20.10+
Docker Compose 2.0+ (or docker-compose 1.29+)
4GB+ RAM available for containers
Ports available (default): 80, 1880, 1883, 3000, 5050, 8080, 8090, 8883, 8887, 8889, 9000
All ports are configurable via
.envfile if defaults conflict with existing services
Installation#
Clone the repository:
git clone <https://gitlab.com/LabEquipmentAdapterFramework/leaf-backend> cd leaf-backend
Generate secure passwords and start all services:
# Step 1: Generate secure passwords and port configuration (auto-detects hostname) docker compose run --rm password-generator > .env # Step 2: (Optional) Customize configuration # The script auto-detects your hostname and uses default ports. # For custom domains or ports, edit: nano .env # - Change HOSTNAME to your domain (e.g., server.example.com) # - Change any port numbers if defaults conflict with existing services # Step 3: Start all services docker compose up -d
View your credentials:
cat .env
The password generator automatically detects your device’s hostname and sets up default ports for all services. Services will be accessible at http://your-hostname/, with individual services at their configured ports.
The setup will automatically:
Generate secure passwords for all services (including bcrypt hash for Portainer)
Configure default ports for all services (customizable in
.env)Configure all services with proper networking
Create dedicated database users (telegraf_user, nodered_user, readonly_user)
Start all services with proper dependencies and health checks
Use Docker volumes for persistent data (avoiding permission issues)
Generate a dynamic landing page with correct port links
Accessing Services#
Once started, you can access services via the landing page. Replace localhost with your server’s hostname or IP address as needed:
Main Landing Page:
The landing page provides a dynamic visual dashboard with links to all MAPLE services
Port numbers automatically update based on your
.envconfigurationThis is your main entry point to the platform!
Individual Services (Default Ports):
LEAF Application: http://localhost:8887
Grafana Dashboard: http://localhost:3000
Node-RED: http://localhost:1880
pgAdmin: http://localhost:5050
Portainer: http://localhost:9000
MQTTX Web: http://localhost:8090
VerneMQ Status: http://localhost:8889/status
MQTT Protocol Ports:
MQTT: tcp://localhost:1883
MQTT over TLS: tcp://localhost:8883
MQTT WebSocket: ws://localhost:8080
Note: All credentials are stored in your
.envfile. Usecat .envto view them.
For Production: The
HOSTNAMEvariable is auto-detected from your device’s hostname. If you need to use a custom domain name (e.g.,data.example.com), edit theHOSTNAMEvariable in your.envfile before starting services. This ensures services generate correct URLs and redirects.
Configuring Custom Ports#
If the default ports conflict with existing services on your system, you can easily customize them:
Available Port Configuration:
LANDING_PORT=80 # Landing page (default: 80)
MQTT_PORT=1883 # MQTT protocol (default: 1883)
MQTT_TLS_PORT=8883 # MQTT over TLS (default: 8883)
MQTT_WS_PORT=8080 # MQTT WebSocket (default: 8080)
MQTT_METRICS_PORT=8889 # VerneMQ status (default: 8889)
MQTTX_WEB_PORT=8090 # MQTTX Web client (default: 8090)
NODERED_PORT=1880 # Node-RED interface (default: 1880)
PGADMIN_PORT=5050 # pgAdmin interface (default: 5050)
GRAFANA_PORT=3000 # Grafana dashboards (default: 3000)
LEAF_PORT=8887 # LEAF application (default: 8887)
PORTAINER_PORT=9000 # Portainer management (default: 9000)
To change ports:
Edit your
.envfile:nano .envModify any port values:
# Example: Change Grafana from port 3000 to 3001 GRAFANA_PORT=3001 # Example: Change landing page from port 80 to 8080 LANDING_PORT=8080
Restart the affected services:
docker compose up -d grafana landing # Or restart everything: docker compose down && docker compose up -d
The landing page will automatically display the new port numbers.
Dynamic Landing Page: The landing page uses environment variable substitution to automatically update all service links when you change ports. Simply restart the
landingservice after editing.envand your dashboard will reflect the new configuration.
Service Management#
Common Docker Compose commands:
# Start all services in detached mode
docker compose up -d
# Stop all services
docker compose down
# View service status
docker compose ps
# View logs for all services
docker compose logs -f
# View logs for specific service
docker compose logs -f grafana
# Restart a specific service (e.g., TimescaleDB)
docker compose restart timescaledb
# Update containers
docker compose pull && docker compose up -d