A lightweight, native Lua 5.1 bot for remote router management over the Matrix protocol. Designed specifically for OpenWrt, providing a secure, efficient, and memory-safe way to control your router from any Matrix client.
Key Features:
- Native OpenWrt Integration: Built on robust OpenWrt C-bindings (
ubus,uci,iwinfo,cjson, etc.) for minimal CPU footprint, zero-allocation performance, and deep system interaction. - Web UI Configuration: Fully integrated with OpenWrt's LuCI web interface. Configure tokens, rooms, and services directly from your browser.
- Remote Control: Monitor system metrics (uptime, RAM) and public WAN IP. Manage services (restart/reload), network interfaces (up/down), Wi-Fi radios (toggle/reload), Wake-on-LAN (WOL), and view detailed network clients (DHCP, ARP, IPv6, Wi-Fi) directly from chat.
- Dual Transport Architecture: Choose between a high-security E2EE version (via SSH) or a lightweight HTTP-only version.
- Standalone Sender: The CLI notification script (
matrix_send) can be used independently in your crontabs or custom scripts to push alerts to Matrix (with auto-fallback from E2EE to HTTP). - Security-First: Unauthorized access attempts trigger instant security alerts to a dedicated Admin Room. Managed natively by
procd.
Compatibility: Successfully tested on OpenWrt 25.12.5 using Xiaomi Mi Router 3G (and expected to work seamlessly on all newer 25.x releases).
Click here to view instructions
Register a dedicated Matrix account for the bot on your homeserver (e.g. @matrixbot:your-matrix-domain.tld). Do not use your personal account.
If you don't have an access token for your bot account, you can generate one using curl or wget from any terminal.
[!TIP] Unsure about your Matrix API URL?
Replaceyour-matrix-domain.tldwith the domain from your@matrixbot:your-matrix-domain.tldID.
Openhttps://your-matrix-domain.tld/.well-known/matrix/clientin a browser and copy thebase_url.
Set your credentials as environment variables (remember to replace the placeholders with your actual values):
MATRIX_URL='https://synapse.your-matrix-domain.tld'
BOT_USER='@matrixbot:your-matrix-domain.tld'
BOT_PASS='Ch4nge-Th1s_BotPa$sw0rd!'Then run one of the following commands:
Using curl:
curl -s -X POST "${MATRIX_URL}/_matrix/client/v3/login" \
-H "Content-Type: application/json" \
-d "{\"type\":\"m.login.password\",\"user\":\"${BOT_USER}\",\"password\":\"${BOT_PASS}\"}"Or using wget:
wget -q -O - --header="Content-Type: application/json" \
--post-data="{\"type\":\"m.login.password\",\"user\":\"${BOT_USER}\",\"password\":\"${BOT_PASS}\"}" \
"${MATRIX_URL}/_matrix/client/v3/login"Copy the access_token field from the response. It usually starts with syt_ or mct_.
[!NOTE] E2EE Method: If you are using
matrix-cli, you can also find theaccess_tokenin yoursession.jsonfile on the external host.
Create (or reuse) the following rooms in your Matrix client:
| Room | Purpose | Variable |
|---|---|---|
| Command rooms | Where you send commands to the bot. Can be E2EE-encrypted or plaintext. | rooms |
| Admin Alert room | Where the bot sends security alerts (unauthorized access). Does not accept commands. | admin_room |
Invite the bot account to all rooms. Get room IDs from your client (usually under Room Settings → Advanced) — they look like !AbCdEfGhIj:matrix-example.tld or the newer domain-less format !0xRqYq5IIruJFFcCLhkzepUfk5m2InboNUkXe3ZTqPs.
The easiest way to install the bot is by adding our custom APK repository. This allows for seamless installations and future updates via the standard OpenWrt package manager.
Execute these commands sequentially via SSH on your OpenWrt router:
- Download and install the public key:
wget -O /etc/apk/keys/underhax-owrt.rsa.pub https://underhax.github.io/matrix-bot-openwrt/underhax-owrt.rsa.pub
- Add the repository to custom feeds:
echo 'https://underhax.github.io/matrix-bot-openwrt/packages/packages.adb' >> /etc/apk/repositories.d/customfeeds.list
- Update the package index and install:
apk update && apk add matrixbot luci-app-matrixbot
Run these commands sequentially in your Image Builder root directory:
- Download the public key:
wget -O keys/underhax-owrt.rsa.pub https://underhax.github.io/matrix-bot-openwrt/underhax-owrt.rsa.pub
- Remove existing entry to avoid duplicates (optional):
sed -i '/underhax.github.io\/matrix-bot-openwrt/d' repositories - Add the repository:
echo 'https://underhax.github.io/matrix-bot-openwrt/packages/packages.adb' >> repositories
Click here to view manual installation instructions
To install the packages manually, you need to download them into your router's /tmp directory.
Using curl:
cd /tmp && \
TAG=$(curl -sSL "https://api.github.com/repos/underhax/matrix-bot-openwrt/releases/latest" | grep '"tag_name":' | head -n 1 | awk -F'"' '{print $4}') && \
curl -sSL -O "https://github.com/underhax/matrix-bot-openwrt/releases/download/${TAG}/matrixbot-${TAG#v}-r1.apk" && \
curl -sSL -O "https://github.com/underhax/matrix-bot-openwrt/releases/download/${TAG}/luci-app-matrixbot-${TAG#v}-r1.apk"Or using wget:
cd /tmp && \
TAG=$(wget -qO- "https://api.github.com/repos/underhax/matrix-bot-openwrt/releases/latest" | grep '"tag_name":' | head -n 1 | awk -F'"' '{print $4}') && \
wget -q "https://github.com/underhax/matrix-bot-openwrt/releases/download/${TAG}/matrixbot-${TAG#v}-r1.apk" && \
wget -q "https://github.com/underhax/matrix-bot-openwrt/releases/download/${TAG}/luci-app-matrixbot-${TAG#v}-r1.apk"Method B: Manual Download & SCP
- Download the latest release packages (
matrixbot-*.apkandluci-app-matrixbot-*.apk) to your computer from the Releases page. - Transfer them to your router (e.g. via
scpinto/tmp/).
Once the files are in /tmp, connect to your router via SSH (if you haven't already) and run the following to install and clean up:
wget -qO /etc/apk/keys/underhax-owrt.rsa.pub https://underhax.github.io/matrix-bot-openwrt/underhax-owrt.rsa.pub
apk update && \
cd /tmp && \
apk add matrixbot-*.apk luci-app-matrixbot-*.apk && \
rm -f matrixbot-*.apk luci-app-matrixbot-*.apkIf you are a developer or want to test the latest main branch, refer to our detailed Manual Testing Guide.
The recommended way to configure the bot is through the OpenWrt Web GUI.
- Open your router's LuCI web interface in your browser. (Note: If the menu doesn't appear immediately after installation, log out and log back in to clear the LuCI cache).
- Navigate to Services → Matrix Bot.
- Fill in your Matrix URL, Access Token, Bot User, Admin User, and Room IDs. (See Obtaining an Access Token if you are unsure about your Matrix URL).
- If using E2EE, enable it and provide your SSH credentials.
- Configure optional features such as Start Delay (to wait for network on boot), Allowed Services (for the
restartcommand), WOL PC MAC, WOL Interfaces, and Wi-Fi preferences. - Click Save & Apply. The
procddaemon will automatically reload the bot with the new settings.
Alternatively, you can edit /etc/config/matrixbot manually via SSH and run service matrixbot reload.
Recommended for privacy. Uses End-to-End Encryption (E2EE) via an SSH tunnel to an external host running matrix-cli.
- External Host: A VPS, Raspberry Pi, or Docker container running
matrix-clilogged into the bot account. - Key Setup: Generate an SSH key on your router (
ssh-keygen -t ed25519 -f /root/.ssh/router-matrix) and add the public key to your external host. - Verification: After configuring the bot in LuCI, you must save the remote host's signature securely before enabling the service:
ssh -i "$(uci -q get matrixbot.e2ee.ssh_key)" -p "$(uci -q get matrixbot.e2ee.ssh_port)" \ -o StrictHostKeyChecking=accept-new \ -o UserKnownHostsFile=/etc/matrix_bot_known_hosts \ -o BatchMode=yes \ -o ConnectTimeout=10 \ "$(uci -q get matrixbot.e2ee.ssh_user)@$(uci -q get matrixbot.e2ee.ssh_host)" exit 2>&1 && \ printf "Host key saved.\n" && chmod 600 /etc/matrix_bot_known_hosts
Communicates directly with the Matrix API. Best for unencrypted rooms or when you cannot maintain an external host.
- No external host required.
- The Matrix access token is passed securely in memory to native transports, preventing credential leaks in process lists.
Once the bot is running and invited to your rooms, send commands as the Admin User in the command room.
Send help or start to get the full command list from the bot itself.
| Command | Description |
|---|---|
| SYSTEM | |
uptime |
Router uptime and load average |
memory |
RAM usage in MB (total / used / free) |
meminfo |
Detailed /proc/meminfo |
wan_ip |
Public WAN IP address (multi-fallback resolution) |
| NETWORK | |
clients |
Full network report: Wi-Fi + wired clients |
wifi_clients |
Wi-Fi associated clients |
wired_clients |
Wired LAN clients |
| SERVICES | |
restart <service> |
Restart a whitelisted service (e.g. restart dnsmasq) |
reload nginx |
Test Nginx config, then reload if valid |
| INTERFACES | |
ifup <iface> |
Bring up a UCI interface (e.g. ifup wan) |
ifdown <iface> |
Bring down a UCI interface |
| WI-FI | |
wifi / wifi_info |
Wi-Fi information |
wifi_up_2_4 / wifi_down_2_4 |
Enable/Disable 2.4 GHz radio (radio0) |
wifi_up_5 / wifi_down_5 |
Enable/Disable 5 GHz radio (radio1) |
wifi_reload_2_4 / wifi_reload_5 |
Reload 2.4 GHz or 5 GHz radio |
| WOL | |
wol <MAC> |
Send WOL magic packet to any MAC (format: AA:BB:CC:DD:EE:FF) |
wol_pc |
Send WOL magic packet to pre-configured PC |
The CLI script can be used independently for your own system alerts or crontab notifications.
Auto-Fallback (E2EE → HTTP):
/usr/bin/matrix_send --room-id '!RoomID:server.tld' 'Alert: WAN link is down!'Note: You can force a transport by passing --ssh-only or --http-only.
Example: OpenWrt Hotplug Script (/etc/hotplug.d/iface/97-get_ip)
#!/bin/sh
# Send a Matrix notification when the WAN interface comes up
# ipv4=$(ifstatus wan | jsonfilter -e '@["ipv4-address"][0].address')
[ "$ACTION" = "ifup" -a "$INTERFACE" = "wan" ] && {
(
sleep 30
ipv4=$(curl --interface "$INTERFACE" -s 4.ipquail.com/ip)
/usr/bin/matrix_send "<b>WAN is UP</b> <br>IPv4: <code>$ipv4</code>"
) &
}
exit 0- Process Isolation: Native Lua modules are loaded dynamically. No slow shell
fork()calls. - Single admin: only
Admin Usercan issue commands. Any other sender triggers an immediate alert to theAdmin Alert Room. - Strict Validation: Service names, network interface names, MAC addresses, IP addresses, domains, ports, Matrix User IDs, tokens, and Room IDs are all validated against strict Lua patterns before execution, entirely preventing command injection.
- SSH Verification: SSH Verification: Enforces StrictHostKeyChecking=yes with a dedicated known_hosts file. Strict owner/mode checks (chmod 600/400) on SSH keys prevent MITM attacks.
- Logs: View real-time activity via OpenWrt's system log:
logread -e matrixbot -f. - Debug Mode: Enable "Debug Logging" in LuCI (or set
option debug '1'in/etc/config/matrixbot) to see verbose HTTP payloads, JSON parsing errors, and UBUS debugging output. - E2EE Checks: If E2EE fails, manually verify SSH connectivity from the router to your
matrix-clihost using the key defined in LuCI.