Pairing Bluetooth Low Energy (BLE) devices like Heltec (running MeshCore or Meshtastic) with a headless Linux server can sometimes be tricky due to security negotiations. Follow this guide to ensure a stable and successful connection for the mc-webui application.
Before touching the Linux terminal, you must configure your MeshCore device to use a fixed PIN. This prevents authentication timeouts and makes headless pairing much easier.
- Connect to your MeshCore device via the mobile app or web interface.
- Go to the Bluetooth Settings.
- Set the pairing mode to use a Fixed PIN (Passkey).
- Enter a memorable 6-digit PIN (e.g.,
123456). - Save the configuration and let the device reboot.
Linux's default Bluetooth stack (BlueZ) needs to be optimized for Bluetooth Low Energy (BLE).
- Edit the main Bluetooth configuration file:
sudo nano /etc/bluetooth/main.conf
- Find the
[General]section and add or modify the following lines to force LE mode and speed up connections:ControllerMode = le FastConnectable = true
- Save the file and restart the Bluetooth service:
sudo systemctl restart bluetooth
Note for Proxmox/VM Users: If you are passing a physical USB Bluetooth dongle to a Virtual Machine, do not use USB 3.0 passthrough. It causes packet drops and timeouts (Opcode failed errors). Always force USB 2.0. Example Proxmox command:
qm set <VMID> -usb0 host=<VENDOR_ID>:<PRODUCT_ID>,usb3=0
Use the built-in bluetoothctl tool to discover, pair, and trust your device.
- Open the Bluetooth control utility:
bluetoothctl
- Enable the keyboard display agent (this tells Linux to ask you for the PIN):
[bluetooth]# agent KeyboardDisplay [bluetooth]# default-agent - Turn on the Bluetooth scan to find your device:
[bluetooth]# scan le - Wait until your device appears in the list and note its MAC address (e.g.,
AC:A7:04:08:66:A1 MeshCore-demo mc-webui). - Initiate the pairing process using the MAC address:
[bluetooth]# pair AC:A7:04:08:66:A1 - The terminal will prompt you for the passkey:
[agent] Enter passkey (number in 0-999999):Enter the Fixed PIN you configured earlier (e.g.,123456) and press Enter. - You should see
Pairing successful.
This is the most crucial step. You must "trust" the device so that mc-webui can automatically connect to it in the future without requiring the PIN again.
- In the
bluetoothctlprompt, type:[bluetooth]# trust AC:A7:04:08:66:A1 - You should see
trust succeeded. - You can now safely exit the utility:
[bluetooth]# exit
Your MeshCore device is now permanently paired, trusted, and ready to communicate with the mc-webui server!
Do NOT use bluetoothctl info <MAC> to check connection state — it auto-connects to trusted devices, which steals the connection from the mc-webui container.
Instead, use hcitool which only reads status without triggering a connection:
hcitool conExpected output when connected:
Connections:
< LE AC:A7:04:08:66:A1 handle 65 state 1 lm CENTRAL AUTH ENCRYPT
If mc-webui is stuck in a "Failed to connect to device / Retrying..." loop:
- Check if something else holds the connection:
hcitool con
- If a connection exists, disconnect it:
bluetoothctl disconnect AC:A7:04:08:66:A1
- Restart the container:
cd ~/mc-webui && docker compose restart mc-webui
- Verify (wait ~15s for retry):
hcitool con curl -s http://localhost:5000/api/status | python3 -m json.tool
A BLE peripheral can only be connected to one central at a time. If bluetoothctl, another app, or a mobile phone is connected, the container will fail. Always disconnect other clients before starting mc-webui.