A lightweight web interface providing browser-based access to MeshCore mesh network.
mc-webui is a Flask-based web application providing browser-based access to MeshCore mesh network. It communicates directly with your LoRa device (via USB, BLE, or TCP) using the meshcore Python library, eliminating the need for SSH/terminal access. Tested on Heltec V3 and Heltec V4.
- Mobile-first design - Responsive UI optimized for small screens, with desktop sidebar for wide screens
- Channel management - Create, join, share (QR code), and switch between encrypted channels
- Direct Messages (DM) - Private messaging with searchable contact selector, delivery tracking, configurable retry strategy, and multi-path routing
- Smart notifications - Unread message counters per channel with cross-device sync
- Contact management - Manual approval, add via URI/QR, filtering, protection, ignoring, blocking, batch operations, and cleanup tools
- Global search - Full-text search across all messages (channels and DMs) with FTS5 backend
- Database - Fast and reliable SQLite storage for messages, contacts, and configurations
- Contact map - View contacts and own device on OpenStreetMap (Leaflet) with last seen info
- Message archives - Automatic daily archiving with browse-by-date selector
- Interactive Console - Full MeshCore command suite via WebSocket — repeater, contact, device, and channel management
- Device dashboard - Device info, statistics, and contact sharing (QR code / URI)
- Dark/Light theme - Toggle between dark and light UI themes
- Settings - Configurable DM retry parameters, message retention, quote length, and theme
- System Log - Real-time log viewer with streaming
- Database backup - Create, list, and download database backups from the UI
- @Mentions autocomplete - Type @ to see contact suggestions with fuzzy search
- Echo tracking - "Heard X repeats" with repeater IDs for sent messages, all route paths for incoming messages with deterministic payload matching (persisted across restarts)
- MeshCore Analyzer - View packet details on analyzer.letsmesh.net directly from channel messages
- DM delivery tracking - ACK-based delivery confirmation with SNR, route, and hop count details
- Multi-device support - Database file named after device public key for easy multi-device setups
- PWA support - Browser notifications and installable app (experimental)
- Full offline support - Works without internet (local Bootstrap, icons, emoji picker)
For detailed feature documentation, see the User Guide.
1. Meshcore Device (tested on Heltec V4)
- Flash the device at https://flasher.meshcore.co.uk/. Choose the
Companion USBrole. - Configure the device with the Meshcore mobile app (from Google Play Store / App Store): Name, Location (optional), Preset
2. Linux Server
- Docker and Docker Compose installed (installation guide)
- Git installed (only needed for Option B: From Source)
Important Notes:
- Powered by direct meshcore library integration (v2 architecture)
- No manual directory setup needed - all data stored in
./data/inside the project directory - Uses a single-container architecture with a fast SQLite database
The quickest way to get started — no git clone, no building required.
Available image tags:
mawoj/mc-webui:latest— stable release (frommainbranch)mawoj/mc-webui:dev— latest development version (fromdevbranch)
Images are also mirrored to GitHub Container Registry: ghcr.io/marekwo/mc-webui
-
Create a project directory
mkdir ~/mc-webui && cd ~/mc-webui
-
Create
docker-compose.ymlcat > docker-compose.yml << 'EOF' services: mc-webui: image: mawoj/mc-webui:latest container_name: mc-webui restart: unless-stopped ports: - "${FLASK_PORT:-5000}:${FLASK_PORT:-5000}" device_cgroup_rules: - 'c 188:* rmw' - 'c 166:* rmw' cap_add: - NET_ADMIN - NET_RAW volumes: - "${MC_CONFIG_DIR:-./data}:/data:rw" - "/dev:/dev" - "/var/run/dbus:/var/run/dbus" environment: - MC_SERIAL_PORT=${MC_SERIAL_PORT:-auto} - MC_DEVICE_NAME=${MC_DEVICE_NAME:-MeshCore} - MC_CONFIG_DIR=/data - MC_TCP_HOST=${MC_TCP_HOST:-} - MC_TCP_PORT=${MC_TCP_PORT:-5555} - MC_BLE_ADDRESS=${MC_BLE_ADDRESS:-} - MC_BACKUP_ENABLED=${MC_BACKUP_ENABLED:-true} - MC_BACKUP_HOUR=${MC_BACKUP_HOUR:-2} - MC_BACKUP_RETENTION_DAYS=${MC_BACKUP_RETENTION_DAYS:-7} - FLASK_HOST=${FLASK_HOST:-0.0.0.0} - FLASK_PORT=${FLASK_PORT:-5000} - FLASK_DEBUG=${FLASK_DEBUG:-false} - TZ=${TZ:-UTC} env_file: - path: .env required: false healthcheck: test: ["CMD", "curl", "-f", "http://localhost:5000/health"] interval: 30s timeout: 10s retries: 3 start_period: 15s EOF
-
Create
.envfile (optional)In most cases, no
.envfile is needed! The defaults work automatically:MC_SERIAL_PORT=auto— auto-detects your USB deviceMC_DEVICE_NAME=auto— auto-detects device name
If you want to set your timezone or override defaults:
echo "TZ=Europe/Warsaw" > .env
Troubleshooting: Multiple USB devices or detection fails
Check available serial devices:
ls /dev/serial/by-id/
If you see multiple devices, add to your
.env:MC_SERIAL_PORT=/dev/serial/by-id/usb-Espressif_Systems_heltec_...
-
Verify Serial Device Permissions (if needed)
sudo usermod -aG dialout $USER # Log out and log back in for changes to take effect
-
Start mc-webui
docker compose up -d
This will:
- Pull the pre-built mc-webui image from Docker Hub
- Create
./data/directory structure automatically - Start the mc-webui container
-
Verify installation
docker compose ps
The container should show
Upstatus. Check logs if needed:docker compose logs -f
-
Access the web interface
Open your browser and navigate to:
http://<your-server-ip>:5000To find your server IP:
hostname -I | awk '{print $1}' -
Initial Configuration (In Web UI)
- Main page loads with chat interface on "Public" channel
- Wait for initial sync (1-2 minutes)
- Optional: Enable manual contact approval in Contact Management
Choose this option if you want to modify the code, contribute, or run the dev branch.
-
Clone the repository
cd ~ git clone https://github.com/MarekWo/mc-webui cd mc-webui
-
Create configuration file
cp .env.example .env
In most cases, no changes are needed! The defaults work automatically:
MC_SERIAL_PORT=auto- auto-detects your USB deviceMC_DEVICE_NAME=auto- auto-detects device name from meshcli
Optionally edit
.envto set your timezone:TZ=Europe/WarsawTroubleshooting: Multiple USB devices or detection fails
Check available serial devices:
ls /dev/serial/by-id/
If you see multiple devices, edit
.envand setMC_SERIAL_PORTexplicitly:MC_SERIAL_PORT=/dev/serial/by-id/usb-Espressif_Systems_heltec_...
-
Verify Serial Device Permissions (if needed)
sudo usermod -aG dialout $USER # Log out and log back in for changes to take effect
-
Build and run
python3 -m app.version freeze docker compose up -d --build
This will:
- Download base images (Python, Alpine Linux)
- Install the
meshcorePython library - Create
./data/directory structure automatically - Start the mc-webui container
-
Verify installation
docker compose ps
The container should show
Upstatus. Check logs if needed:docker compose logs -f
-
Access the web interface
Open your browser and navigate to:
http://<your-server-ip>:5000To find your server IP:
hostname -I | awk '{print $1}' -
Initial Configuration (In Web UI)
- Main page loads with chat interface on "Public" channel
- Wait for initial sync (1-2 minutes)
- Optional: Enable manual contact approval in Contact Management
- View messages - Main page shows chat history with auto-refresh every 10 seconds
- Send messages - Type in the text field and press Enter (135 bytes for channels, 150 bytes for DM)
- Switch channels - Use the dropdown in navbar
- Direct Messages - Access via menu (☰) → "Direct Messages"
- Manage contacts - Access via menu (☰) → "Contact Management"
- Console - Access via menu (☰) → "Console" for MeshCore commands
- Search - Access via menu (☰) → "Search" for full-text message search
- Settings - Access via menu (☰) → "Settings" for DM retry and other configuration
For complete usage instructions, see the User Guide.
Pull the latest image and restart:
cd ~/mc-webui
docker compose pull
docker compose up -dTo switch between stable and dev, change the image tag in docker-compose.yml:
- Stable:
image: mawoj/mc-webui:latest - Development:
image: mawoj/mc-webui:dev
The easiest way to update mc-webui:
cd ~/mc-webui
./scripts/update.shThe script automatically pulls changes, freezes the version, and rebuilds containers.
Optional: Create a global alias for quick updates
Add to your ~/.bashrc or ~/.zshrc:
alias mcupdate='~/mc-webui/scripts/update.sh'Then reload your shell (source ~/.bashrc) and update anytime with:
mcupdateIf you prefer to run commands manually:
cd ~/mc-webui
git pull
python3 -m app.version freeze
docker compose up -d --buildThe python3 -m app.version freeze command captures the current Git version (date + commit hash) for display in the app menu.
The dev branch contains new features that are still being tested:
cd ~/mc-webui
git checkout dev
./scripts/update.shTo return to the stable version:
cd ~/mc-webui
git checkout main
./scripts/update.shYou can enable one-click updates directly from the mc-webui menu. This requires installing a small webhook service on the host machine.
Install the updater service:
cd ~/mc-webui
sudo ./scripts/updater/install.shThe installer will:
- Create a systemd service
mc-webui-updater - Start a webhook server on port 5050 (localhost only)
- Enable automatic startup on boot
Usage:
- Click the refresh button (↻) next to the version in the menu
- If an update is available, an "Update" button appears
- Click "Update" to trigger the update remotely
- The app will automatically reload when the update completes
Useful commands:
# Check service status
systemctl status mc-webui-updater
# View logs
journalctl -u mc-webui-updater -f
# Uninstall
sudo ~/mc-webui/scripts/updater/install.sh --uninstallSecurity note: The webhook listens only on localhost. The Docker container connects to it via the Docker bridge network.
| Document | Description |
|---|---|
| User Guide | Complete feature documentation |
| Architecture | Technical details, API reference |
| Troubleshooting | Common issues and solutions |
| Docker Installation | How to install Docker on Debian/Ubuntu |
| Container Watchdog | Auto-restart for unhealthy containers |
| DM Delivery & Retry Logic | How DM delivery confirmation and retry strategies work |
| Bluetooth Pairing Guide | How to pair MeshCore devices via BLE on Linux |
- Environment Setup & Docker Architecture (single-container, direct device access)
- Backend Basics (REST API, SQLite database, meshcore library integration)
- Frontend Chat View (Bootstrap UI, message display, quote/reply)
- Message Sending (Send form, reply, quote with configurable length)
- Intelligent Auto-refresh (10s checks, UI updates only when needed)
- Contact Management (Approval, add via URI/QR, filtering, protection, ignore/block, batch operations, cleanup)
- Channel Management (Create, join, share via QR, delete with auto-cleanup)
- Public Channels (# prefix support, auto-key generation)
- Message Archiving (Daily archiving with browse-by-date selector)
- Smart Notifications (Unread counters per channel and total)
- Direct Messages (DM) - Searchable contact selector, delivery tracking, configurable retry, multi-path routing
- Global Message Search - Full-text search across channels and DMs (FTS5)
- Message Content Enhancements - Mention badges, clickable URLs, image previews
- @Mentions Autocomplete - Type @ to get contact suggestions with fuzzy search
- PWA Notifications (Experimental) - Browser notifications and app badge counters
- Full Offline Support - Local Bootstrap libraries and Service Worker caching
- Interactive Console - Full MeshCore command suite (repeater, contact, device, channel management)
- Contact Map - View contacts and own device on OpenStreetMap (Leaflet)
- Echo Tracking - "Heard X repeats" badge for sent channel messages
- MeshCore Analyzer - Packet analysis links on channel messages (analyzer.letsmesh.net)
- DM Delivery Tracking - ACK-based delivery checkmarks with SNR/route details
- Device Dashboard - Device info, statistics, and contact sharing (QR/URI)
- Settings Modal - DM retry parameters, message retention, and dark/light theme
- System Log - Real-time log viewer with streaming
- Database Backup - Create, list, and download backups from the UI
- Desktop Sidebar - Channel/contact sidebar for wide screens (tablet/desktop)
- Dark/Light Theme - Toggle between dark and light UI themes
- Multi-device Support - Database file named after device public key
- Performance Optimization - Frontend and backend improvements
- Enhanced Testing - Unit and integration tests
Important: This application is designed for trusted local networks only and has no authentication. Do not expose it to the internet without implementing proper security measures.
This is an open-source project. Contributions are welcome!
- All code, comments, and documentation must be in English
- Follow the existing code style
- Test your changes with real hardware if possible
If you appreciate what I am doing you can buy me a coffee :)
Thanks!


























