Skip to content

Introduction

The LEAF (Lightweight 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.

OAK (Open Architecture for Knowledge) 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

OAK 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.

This docker-compose setup is a quick way to run OAK locally for evaluation or development - not a toy. The platform underneath has a genuinely production-oriented design: management-based access control enforced at the database level, least-privilege service accounts scoped per component (see Database Access), and real authentication on every service, including the flow editor. What this specific quick-start deployment doesn’t include out of the box is TLS, a real secrets manager, automated backups, or redundancy - those are operational concerns to add before pointing it at production traffic, not gaps in the architecture itself.

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)
    • Service initialization and health checks
    • Secure internal data processing
  • Frontend Network: Network for user-facing services and external access

    • Landing page (port 80) - the only service on this network alone
  • Bridge Networks: Services that span both networks (they all need direct backend access to TimescaleDB, plus a user-facing web interface or external client connections)

    • VerneMQ (port 1883/8883/8080/8889) - connects backend services to external MQTT clients
    • Node-RED (port 1880) - processes data from backend and provides a web interface
    • Grafana (port 3000) - dashboards read from TimescaleDB directly
    • LEAF Portal (port 8888) - web interface, reads/writes TimescaleDB directly

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
  • Node-RED: Visual workflow automation and data processing engine
  • TimescaleDB: PostgreSQL-based time-series database optimized for sensor data
  • Grafana: Data visualization and dashboarding platform
  • LEAF Portal: Multi-tenant web interface for managing organisations, departments, users, and API tokens - see the Portal documentation

To get started with OAK, follow these steps:

  • 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, 8080, 8883, 8888, 8889
    • All ports are configurable via .env file if defaults conflict with existing services
  1. Clone the repository:

    Terminal window
    git clone https://gitlab.com/leaf-framework/oak.git
    cd oak
  2. Generate secure passwords and start all services:

    Terminal window
    # 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:

    Terminal window
    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
  • Configure default ports for all services (customizable in .env)
  • Configure all services with proper networking
  • Create dedicated database users (nodered_user, nodered_auth_svc, readonly_user, grafana_svc, vernemq_svc)
  • 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

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 OAK 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: Most credentials (Grafana admin, MQTT, database roles) are stored in your .env file - use cat .env to view them. The Node-RED editor is the exception: it logs in with an existing LEAF portal superadmin account (email + password), not a .env credential - see Node-RED editor authentication.

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.

If the default ports conflict with existing services on your system, you can easily customize them:

Available Port Configuration:

Terminal window
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)
NODERED_PORT=1880 # Node-RED interface (default: 1880)
GRAFANA_PORT=3000 # Grafana dashboards (default: 3000)
PORTAL_PORT=8888 # LEAF Portal (default: 8888)

To change ports:

  1. Edit your .env file:

    Terminal window
    nano .env
  2. Modify any port values:

    Terminal window
    # 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:

    Terminal window
    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.

Common Docker Compose commands:

Terminal window
# 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