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 - The Backend Platform
Section titled “OAK - The Backend Platform”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.
Network Architecture
Section titled “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)
- 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
Architecture
Section titled “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
- 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
Getting Started
Section titled “Getting Started”To get started with OAK, follow these steps:
Prerequisites
Section titled “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, 8080, 8883, 8888, 8889
- All ports are configurable via
.envfile if defaults conflict with existing services
- All ports are configurable via
Installation
Section titled “Installation”-
Clone the repository:
Terminal window git clone https://gitlab.com/leaf-framework/oak.gitcd oak -
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 servicesdocker compose up -d -
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
Accessing Services
Section titled “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 OAK services
- Port numbers automatically update based on your
.envconfiguration - This is your main entry point to the platform!
Individual Services (Default Ports):
- LEAF Portal: http://localhost:8888
- Grafana Dashboard: http://localhost:3000
- Node-RED: http://localhost:1880
- VerneMQ Status: http://localhost:8889
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
.envfile - usecat .envto view them. The Node-RED editor is the exception: it logs in with an existing LEAF portal superadmin account (email + password), not a.envcredential - see Node-RED editor authentication.
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
Section titled “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)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:
-
Edit your
.envfile:Terminal window nano .env -
Modify any port values:
Terminal window # Example: Change Grafana from port 3000 to 3001GRAFANA_PORT=3001# Example: Change landing page from port 80 to 8080LANDING_PORT=8080 -
Restart the affected services:
Terminal window 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
Section titled “Service Management”Common Docker Compose commands:
# Start all services in detached modedocker compose up -d
# Stop all servicesdocker compose down
# View service statusdocker compose ps
# View logs for all servicesdocker compose logs -f
# View logs for specific servicedocker compose logs -f grafana
# Restart a specific service (e.g., TimescaleDB)docker compose restart timescaledb
# Update containersdocker compose pull && docker compose up -d