A UniFi-class controller for OpenWrt mesh networks.
Adopt, configure, visualize, troubleshoot and upgrade every OpenWrt router in your home from one fast, modern web app.
Note
Status: early development. The foundation (M0) and read-only adoption (M1) are done; observability (M2) is under way. Track progress in docs/STATUS.md and docs/ROADMAP.md.
OpenWrt is the best firmware you can run on a router. Running several OpenWrt routers as one home mesh is harder: you SSH into each one, hand-edit UCI files, keep Wi-Fi, roaming and mesh settings consistent by yourself, and never get a single view of what is connected where. uniwrt brings the single-pane-of-glass experience of commercial controllers to OpenWrt, without lock-in and without the cloud.
- Adopt in minutes. Watch your existing nodes read-only first. Add new devices with zero-touch firmware images, a bench adoption port, or a one-line bootstrap.
- Mesh made easy. batman-adv over encrypted 802.11s, with automatic failover between wired and wireless backhaul and VLANs carried across the mesh.
- Seamless roaming. 802.11r/k/v with controller-distributed neighbor reports, plus band and AP steering.
- Automatic RF planning. Channel, width and transmit power chosen from real scans and node-to-node measurements, with an explainable score and coordinated changes.
- Options-based ISP setup. Presets such as Lumen/Quantum Fiber IPoE (VLAN 201), PPPoE, 6rd or DHCPv6-PD, plus a live connectivity test before anything is committed.
- See everything. A live animated topology, which client is on which node, a roaming timeline, a spectrum view and a floor-plan coverage heatmap.
- Troubleshoot fast. Searchable logs aggregated from every node, metrics, events and alerts. Run ping, traceroute, iperf3 or a packet capture from any node. A per-client "connection doctor" and a WAN quality monitor round it out.
- Safe changes. Every change is reviewed as a per-node diff and applied as a transaction. If a node loses contact, it rolls back automatically. Full revision history.
- Rolling upgrades. Firmware is built with each node's exact package set (Attended Sysupgrade). Nodes upgrade one at a time, from the edge of the mesh to the gateway, with health checks between steps.
- Never SSH again. DHCP, DNS, firewall, port forwards, WireGuard, SQM, DDNS and schedules. A built-in browser terminal and raw UCI editor cover the rare edge case.
- Tiny and fast. One static Rust binary with the UI embedded, shipped as a
FROM scratchimage for amd64, 386, arm/v7 and arm64.
flowchart LR
user["Browser<br/>SolidJS UI"] -- "HTTPS + WebSocket" --> api
subgraph ctl["uniwrt controller (FROM scratch container)"]
api["API + auth"] --> engine["Engine<br/>node actors, live state, jobs"]
engine --> db[("SQLite")]
syslog["Syslog ingest"] --> db
end
engine -- "SSH: ephemeral ucode agent" --> gw["Gateway<br/>OpenWrt"]
engine -- "SSH" --> ap1["Mesh AP"]
engine -- "SSH" --> ap2["Mesh AP"]
gw -. mesh backhaul .-> ap1
ap1 -. mesh backhaul .-> ap2
gw -- "remote syslog" --> syslog
engine -- "HTTPS" --> asu["OpenWrt Attended Sysupgrade"]
- The controller keeps one SSH session open per node and runs an ephemeral ucode agent over it. (ucode is the scripting runtime built into OpenWrt.) The agent speaks JSON-RPC and pushes events in real time. It installs nothing permanent and works on every CPU architecture.
- The controller owns the desired state. It renders each node's UCI config, diffs it against the node, and applies it as a transaction. A dead-man timer on the node rolls the change back if the controller can't confirm it.
- Logs arrive through the agent, which follows each node's log with no change on the node, or through OpenWrt's built-in remote syslog when it is configured; other devices can send syslog too. Firmware images come from OpenWrt's Attended Sysupgrade service.
Details: docs/ARCHITECTURE.md.
docker run -d --name uniwrt --restart unless-stopped \
--network host -v uniwrt-data:/data \
ghcr.io/robertzas/uniwrt:latestThen open https://<host>:8443 and create the admin account. For safety, setup is open only during the first 10 minutes after a start without users; if you miss it, restart the container. Host networking is recommended because it makes discovery and log ingest simple. With bridge networking, publish 8443/tcp and 5514/tcp+udp instead, and on the first run name the host's address for the certificate (-e UNIWRT_TLS_NAMES=192.168.1.10).
The controller makes its own local CA, limited to local names and private addresses. Download it from https://<host>:8443/api/v1/tls/ca.crt, check its SHA-256 against the one the log prints, and trust it on your devices: the certificate warnings are then gone for good. Secrets (SSH keys, passwords) are encrypted under /data/master.key; back that file up apart from the data, or keep it outside the volume with UNIWRT_MASTER_KEY_FILE. Behind a reverse proxy that terminates TLS, let it reach port 8080 and list it in UNIWRT_TRUSTED_PROXIES. To keep the data in a host directory rather than the named volume, make that directory writable by UID 65532 first (chown 65532:65532 <dir>).
To try it without a network of your own, add -e UNIWRT_DEMO=1 (or run uniwrt serve --demo). That simulates a gateway, 3 mesh access points and 30 clients that roam, come and go, and now and then reboot an access point. The last access point waits under Devices → Discovered for you to adopt it (its root password is demo). Demo mode keeps its own database and deletes it at exit; log in as demo, password demo.
| Supported | |
|---|---|
| Controller host | Any Linux container host: x86_64, x86 (i686), arm32 (armv7), arm64 |
| Managed nodes | OpenWrt 25.12 (primary target) and 24.10 (best effort), on any CPU architecture |
| Scale | Designed for 1–50 nodes and up to 1,000 clients; tuned on a gateway plus 3 APs |
| Doc | Contents |
|---|---|
| PRODUCT | Vision, scope, principles, capability catalog |
| ARCHITECTURE | Components, node protocol, data flow, persistence, budgets |
| ROADMAP · STATUS | Milestones and work packages · current progress |
| DECISIONS | Accepted decisions and open options |
| features/ | Specs: adoption, WAN/ISP, networks, Wi-Fi & RF, mesh, observability, lifecycle, UI, security |
| dev/ | Conventions, build & release, testing |
| AGENTS.md | Working agreement for AI coding agents |
uniwrt is in early development, and issues and ideas are welcome. Start with docs/dev/CONVENTIONS.md. Commits follow Conventional Commits, and every push to main ships a release. Building from source needs rustup, bun, just and Docker: just setup installs the cargo tools, just dev runs the backend with a live-reloading UI, and just check runs everything CI gates on. Details are in docs/dev/BUILD.md.
Licensed under either the Apache License 2.0 or the MIT license, at your option. Unless you explicitly state otherwise, any contribution you intentionally submit for inclusion in this work, as defined in the Apache-2.0 license, is dual-licensed as above, without any additional terms or conditions.
uniwrt is an independent project, not affiliated with Ubiquiti Inc. or the OpenWrt project. UniFi is a trademark of Ubiquiti Inc.