Skip to main content
MQTT Explorer supports running as a web application served by a Node.js server, providing browser-based access without installation. This mode is ideal for remote access, team collaboration, and embedded deployments.

Overview

Browser mode transforms MQTT Explorer from an Electron desktop app into a web application:
  • Server: Node.js Express server with Socket.io for WebSocket communication
  • Frontend: React application bundled with webpack
  • Transport: WebSocket RPC replaces Electron IPC
  • Authentication: Built-in user authentication with bcrypt password hashing

Docker Deployment

Deploy browser mode with Docker containers (recommended)

Manual Setup

Run directly with Node.js for development or custom deployments

Quick Start

Production Deployment

1

Install Dependencies

Requires Node.js 20 or higher:
npm install -g yarn
yarn install
2

Build Application

yarn build:server
This command:
  • Compiles TypeScript backend (npx tsc)
  • Bundles frontend with webpack (webpack --mode production)
  • Creates optimized production build in dist/ and app/build/
3

Configure Credentials

Set authentication credentials via environment variables:
export MQTT_EXPLORER_USERNAME=admin
export MQTT_EXPLORER_PASSWORD=your_secure_password
export NODE_ENV=production
4

Start Server

yarn start:server
Server starts on http://localhost:3000 by default.

Architecture

Client-Server Communication

Browser mode uses Socket.io WebSockets for real-time bidirectional communication:
// Electron Mode (Desktop)
Electron IPCMain ProcessRenderer Process

// Browser Mode (Web)
Socket.io WebSocketNode.js ServerBrowser Client
Both modes implement the same EventBusInterface, allowing application code to work seamlessly in both environments without modification.

Event Bus Abstraction

The event bus provides a unified API:
  • subscribe(event, handler) - Listen for events from server
  • send(event, data) - Send request to server
  • request(event, data) - Send request and wait for response
  • on(event, handler) - Register event handler on server

WebSocket RPC Protocol

Communication uses a request-response pattern:
// Client Request
{
  "event": "mqtt/connect",
  "requestId": "uuid-v4",
  "data": {
    "host": "mqtt.example.com",
    "port": 1883
  }
}

// Server Response
{
  "requestId": "uuid-v4",
  "success": true,
  "data": {
    "connectionId": "conn-123"
  }
}

Authentication

Authentication Modes

Default mode with username/password authentication.

Environment Variables

export MQTT_EXPLORER_USERNAME=admin
export MQTT_EXPLORER_PASSWORD=your_secure_password
yarn start:server

Auto-Generated Credentials

If no credentials are provided, they’re auto-generated on first startup:
============================================================
Generated new credentials:
Username: user-abc123
Password: 123e4567-e89b-12d3-a456-426614174000
============================================================
Please save these credentials. They will be persisted to:
/path/to/data/credentials.json
============================================================
Credentials are saved to data/credentials.json and reused on subsequent starts.

Security Features

Browser mode implements multiple layers of authentication security:
  • Password Hashing: bcrypt with 10 rounds
  • Timing Attack Protection: Constant-time string comparison for usernames
  • Rate Limiting: Maximum 5 failed attempts per IP per 15 minutes
  • Session Tracking: Failed attempts tracked per client IP
  • No Credential Logging: In production mode, credentials are not logged

Configuration

Server Configuration

Environment VariableDefaultDescription
PORT3000Port the server listens on
NODE_ENV-Set to production for production deployments
ALLOWED_ORIGINS*Comma-separated list of allowed CORS origins
UPGRADE_INSECURE_REQUESTSfalseEnable CSP upgrade-insecure-requests (HTTPS only)
X_FRAME_OPTIONSfalseEnable X-Frame-Options: SAMEORIGIN header

Port Configuration

PORT=8080 yarn start:server

CORS Configuration

In production, configure specific allowed origins:
# Single origin
export ALLOWED_ORIGINS=https://mqtt-explorer.example.com

# Multiple origins
export ALLOWED_ORIGINS=https://app1.example.com,https://app2.example.com

yarn start:server
In production with NODE_ENV=production, wildcard CORS is automatically disabled for security.

AI Assistant Configuration

Enable AI-powered MQTT topic analysis:
Environment VariableDefaultDescription
LLM_PROVIDERopenaiAI provider: openai or gemini
OPENAI_API_KEY-OpenAI API key (provider-specific)
GEMINI_API_KEY-Google Gemini API key (provider-specific)
LLM_API_KEY-Generic API key (works with either provider)
LLM_NEIGHBORING_TOPICS_TOKEN_LIMIT500Token limit for context in AI queries

Example with OpenAI

export LLM_PROVIDER=openai
export OPENAI_API_KEY=sk-proj-xxxxxxxxxxxxxxxxxxxx
export LLM_NEIGHBORING_TOPICS_TOKEN_LIMIT=500
yarn start:server

Security Architecture

The backend proxies all LLM API requests:
  • ✅ API keys remain server-side only
  • ✅ Keys never embedded in client bundles
  • ✅ Keys never transmitted to frontend
  • ✅ Backend controls all LLM access
  • ✅ Communication via secure WebSocket RPC
If no LLM environment variables are set, the AI Assistant feature is completely hidden from users.

Data Storage

In browser mode, all data is stored server-side:
PathContent
data/credentials.jsonUser authentication credentials
data/settings.jsonApplication settings and preferences
data/certificates/Uploaded SSL/TLS certificates
data/uploads/File uploads

Certificate Upload

Certificates are uploaded through the browser using HTML5 File API:
  1. User selects certificate files via file input
  2. Files are read client-side as base64
  3. Base64 data is stored in connection configuration
  4. Certificates are used when establishing MQTT connections
Maximum certificate file size is 16KB. Larger files will be rejected.

Features & Limitations

Browser Mode Advantages

No Installation

Access from any browser without installing software

Cross-Platform

Works on any device with a modern browser

Remote Access

Deploy on a server for remote team access

Multi-User

Support authentication for multiple users (future)

Browser Mode Limitations

Some desktop features are not available in browser mode:
FeatureDesktopBrowserNotes
File System Access✅ Direct❌ LimitedServer-side only
Native Dialogs✅ Yes❌ NoUses HTML file input
Auto-Updates✅ Yes❌ NoManual server updates
System Tray✅ Yes❌ NoDesktop-only feature
Multiple Windows✅ Yes✅ YesUse browser tabs

Production Deployment

Security Requirements

1

HTTPS/TLS Encryption

Always use HTTPS in production to protect credentials and MQTT data in transit.Deploy behind a reverse proxy like nginx or Apache:
server {
    listen 443 ssl http2;
    server_name mqtt-explorer.example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
2

Set Secure Credentials

Never use auto-generated credentials in production:
export MQTT_EXPLORER_USERNAME=your_secure_username
export MQTT_EXPLORER_PASSWORD=$(openssl rand -base64 32)
export NODE_ENV=production
3

Configure CORS

Specify exact allowed origins:
export ALLOWED_ORIGINS=https://mqtt-explorer.example.com
4

Enable Security Headers

When behind HTTPS reverse proxy:
export UPGRADE_INSECURE_REQUESTS=true
export X_FRAME_OPTIONS=true

HTTP Security Headers

The server uses helmet.js to set security headers:
  • Content Security Policy (CSP) - Prevents XSS attacks
  • HTTP Strict Transport Security (HSTS) - Forces HTTPS (production only)
  • X-Content-Type-Options - Prevents MIME sniffing
  • X-Frame-Options - Prevents clickjacking (when enabled)
  • X-XSS-Protection - Legacy XSS protection

File Upload Security

The server implements protections against malicious uploads:
  • Maximum file size: 16MB (configurable)
  • Path traversal protection: Filename sanitization
  • Isolated directories: Files stored in isolated paths
  • Real path validation: Prevents directory escapes

Debugging

Enable Debug Logging

Enable detailed Socket.IO connection and lifecycle debugging:
DEBUG=mqtt-explorer:socketio* yarn start:server

Debug Namespaces

  • mqtt-explorer:socketio - General Socket.IO events and metrics
  • mqtt-explorer:socketio:connect - Client connection events
  • mqtt-explorer:socketio:disconnect - Client disconnection and cleanup
  • mqtt-explorer:socketio:subscriptions - Subscription lifecycle tracking
  • mqtt-explorer:socketio:connections - MQTT connection ownership

Example Output

mqtt-explorer:socketio:connect Client connected: abc123de
mqtt-explorer:socketio [connect] clients=1 subscriptions=8 mqttConns=0 | socket[abc123de]: subs=8 conns=0
mqtt-explorer:socketio:connections Connection my-mqtt owned by socket abc123de (total: 1)
mqtt-explorer:socketio:disconnect Client disconnected: abc123de
mqtt-explorer:socketio:subscriptions Removed 8 subscriptions for socket abc123de
mqtt-explorer:socketio [disconnect] clients=0 subscriptions=0 mqttConns=0

Troubleshooting

  1. Check the console output for generated credentials:
    yarn start:server 2>&1 | grep -A 5 "Generated new credentials"
    
  2. Clear browser session storage:
    // In browser console
    sessionStorage.clear()
    location.reload()
    
  3. Restart server to regenerate credentials:
    rm data/credentials.json
    yarn start:server
    
  1. Check server is running:
    curl http://localhost:3000
    
  2. Check browser console for Socket.io errors:
    • Open DevTools (F12)
    • Look for WebSocket connection errors
    • Check Network tab for failed requests
  3. Verify firewall rules allow port 3000:
    sudo ufw status
    sudo ufw allow 3000/tcp
    
  4. Test WebSocket connection:
    wscat -c ws://localhost:3000/socket.io/
    
  • Verify certificate file is under 16KB
  • Ensure certificate is in PEM format
  • Check browser console for JavaScript errors
  • Verify sufficient disk space in data/certificates/
Memory usage scales with:
  • Number of connected clients
  • Number of active MQTT connections
  • Volume of MQTT messages
Monitor memory:
# Check Node.js memory
ps aux | grep node

# Increase heap size if needed
NODE_OPTIONS="--max-old-space-size=4096" yarn start:server

Build Scripts Reference

From package.json:
{
  "scripts": {
    "start:server": "npx tsc && node dist/src/server.js",
    "build:server": "npx tsc && (cd app && npx webpack --config webpack.browser.config.mjs --mode production)",
    "dev:server": "npm-run-all --parallel dev:server:*",
    "dev:server:app": "(cd app && npx webpack-dev-server --config webpack.browser.config.mjs --mode development --progress)",
    "dev:server:backend": "tsc && node dist/src/server.js"
  }
}

Next Steps

Docker Deployment

Deploy browser mode with Docker for easier management

Security Guide

Learn about security best practices and hardening

Build docs developers (and LLMs) love