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 .env file if defaults conflict with existing services

Installation#

  1. Clone the repository:

    git clone <https://gitlab.com/LabEquipmentAdapterFramework/leaf-backend>
    cd leaf-backend
    
  2. 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
    
  3. 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:

  • http://localhost/ (or http://your-hostname/)

  • The landing page provides a dynamic visual dashboard with links to all MAPLE services

  • Port numbers automatically update based on your .env configuration

  • This is your main entry point to the platform!

Individual Services (Default Ports):

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 .env file. Use cat .env to view them.

For Production: The HOSTNAME variable is auto-detected from your device’s hostname. If you need to use a custom domain name (e.g., data.example.com), edit the HOSTNAME variable in your .env file 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:

  1. Edit your .env file:

    nano .env
    
  2. Modify 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
    
  3. Restart the affected services:

    docker compose up -d grafana landing
    # Or restart everything: docker compose down && docker compose up -d
    
  4. 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 landing service after editing .env and 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

For more information about#