TP-Link Omada, UniFi, Ruijie, Grandstream, Cambium, OpenWrt and generic RADIUS.

SimpliFi — router & controller vendors

Module M2 (MikroTik is module M1 — see its own notes). Every vendor is a driver implementing App\Services\Routers\Contracts\RouterDriver (ARCHITECTURE.md §7.1), registered in config('simplifi.router_drivers'). The same steps are shown in the app on each device page (Captive portal setup) and on Routers & Controllers › Watch Tutorial (tenant.devices.guide).

Common to every vendor

  • Portal URL — each device has its own captive-portal entry, Device::portalUrl() (/portal/d/{uuid} on the workspace host), shown with a copy button on the device page. Set it as the hotspot's external portal / splash page.
  • Walled garden / pre-authentication — customers must reach the portal and the payment pages before they are online: the workspace host (from the portal URL), *.paystack.com, *.paystack.co, *.hubtel.com and fonts.bunny.net (listed on the device page).
  • RADIUS — server = RADIUS_SERVER_HOST (device page), auth port 1812, accounting 1813, the device's shared secret (reveal on click), accounting on with 5-minute interim updates. See docs/RADIUS.md for the FreeRADIUS server itself.
  • After payment / voucher / free trial the portal asks the driver for a loginAction. Controller vendors are authorised server-side (done); RADIUS vendors get a browser step that logs the client in on the hotspot with the generated username/password. Login addresses coming from the hotspot's redirect are only followed when they point at a private/LAN IP, the device's own host / public IP / hotspot DNS name, or a host listed in the device's Extra login hosts.

Capability matrix

✅ supported · ⚠️ partial / see notes · ❌ not available

Omada UniFi Ruijie / Reyee Grandstream GWN Cambium OpenWrt / Coova / pfSense Generic RADIUS
Connection modes controller controller radius radius radius radius radius
Grant access after payment ✅ extPortal/auth ✅ authorize-guest ✅ RADIUS user ✅ RADIUS user ✅ RADIUS user ✅ RADIUS user ✅ RADIUS user
Automatic login on the device ✅ server-side ✅ server-side ⚠️ only with a login URL¹ ✅ EXCAP redirect ✅ POST to AP ✅ Coova / openNDS / pfSense ⚠️ link-login or login URL¹
Time limit ✅ ✅ minutes ✅ Session-Timeout + Expiration ✅ ✅ ✅ ✅ (if the NAS honours Session-Timeout)
Speed limit ⚠️ controller 6.2.10+ ✅ up/down kbps ⚠️ if WISPr is honoured ✅ WISPr ✅ WISPr (WIFI_ALLIANCE_MAX_*) ✅ WISPr ⚠️ vendor dependent
Burst ❌⁵ ❌⁵ ❌⁵ ❌⁵ ❌⁵ ❌⁵ ⚠️ MikroTik-compatible only⁵
FUP throttle (continue at reduced speed) ❌⁶ ❌⁶ ⚠️ next re-auth⁷ ⚠️⁷ ⚠️⁷ ⚠️⁷ ⚠️⁷
PPPoE usage (per-subscriber counters) ❌⁸ ❌⁸ ⚠️ accounting⁹ ⚠️⁹ ⚠️⁹ ⚠️⁹ ⚠️⁹
Data cap ⚠️ controller 6.2.10+ ✅ MB ❌² ❌² ❌² ✅ ChilliSpot-Max-Total-Octets ⚠️ MikroTik-compatible only
Revoke / disconnect ⚠️ re-authorise for 1 s³ ✅ unauthorize-guest ⚠️ next login refused⁴ ⚠️⁴ ⚠️⁴ ⚠️⁴ ⚠️⁴
Health ⚠️ controller version ✅ version, uptime, clients ⚠️ last accounting ⚠️ last accounting ⚠️ last accounting ⚠️ last accounting ⚠️ last accounting
Live clients ✅ with Open API ✅ stat/sta ✅ radacct ✅ radacct ✅ radacct ✅ radacct ✅ radacct
Access points list ✅ with Open API ✅ stat/device ❌ ❌ ❌ ❌ ❌
Package sync not needed not needed not needed not needed not needed not needed not needed
Polled by devices:poll ✅ ✅ — — — — —
  1. Without a login address the customer sees their username/password and types it on the device's own login page.
  2. The vendor ignores RADIUS data-limit attributes; SimpliFi still records usage from accounting.
  3. The documented External Portal API has no "unauthorise" call; SimpliFi re-authorises the client for one second. If a controller version keeps the longer grant, unauthorise manually in Hotspot Manager › Authorized Clients.
  4. RADIUS revoke deletes the user, so the next login fails; an active session lasts until its Session-Timeout (a Disconnect-Request needs UDP from the RADIUS box, not cPanel).
  5. Burst only exists in the burst fields of Mikrotik-Rate-Limit (and in RouterOS queues). Controllers take a single up/down number, and WISPr-Bandwidth-Max-Up/Down has no burst at all, so a package's burst settings are simply not sent: these devices get the plan rate. MikroTik routers do support it — see docs/MIKROTIK.md §"Speed: burst and fair use".
  6. Omada's and UniFi's documented APIs cannot change the rate of a client that is already authorised. SimpliFi therefore does not claim Capability::FUP_THROTTLE for them: a package set to "continue at reduced speed" falls back to its stop behaviour on these devices and the reason is written to wifi_sessions.meta.fup.message, so the ISP sees why instead of being promised a feature their gear lacks.
  7. The reduced rate is written to radreply (Mikrotik-Rate-Limit + WISPr, and the data-limit attributes are removed so the NAS does not cut the customer off instead). The NAS reads those attributes when it authenticates a user, and shared cPanel hosting cannot send a RADIUS Disconnect-Request / CoA, so the new rate takes effect at the customer's next re-authentication — immediately on reconnect, or when Session-Timeout elapses. Until then they stay online at the full rate. MikroTik in RADIUS mode is the exception: SimpliFi also kicks the session through cloud sync, which forces the re-authentication at once. See docs/RADIUS.md §2.
  8. These are controller-managed access points: they do not terminate PPPoE at all, so there are no subscriber counters to read and nothing to slow down. SimpliFi claims neither Capability::PPPOE nor Capability::PPPOE_USAGE for them. If a PPPoE subscriber is pointed at such a device, pppoe:usage leaves them at full speed and writes the reason to pppoe_accounts.meta.fup.message — a monthly subscription is never cut off instead.
  9. A NAS integrated through RADIUS writes acctinputoctets / acctoutputoctets / acctsessiontime for whatever authenticates, PPPoE usernames included, so pppoe:usage can read the counters (Capability::PPPOE_USAGE) if the ISP actually runs PPPoE on the device — SimpliFi does not provision PPPoE secrets on these vendors. How fresh the numbers are is decided by the NAS's Acct-Interim-Interval, and with accounting switched off there is no PPPoE usage at all. The reduced rate is written to radreply and applies at the subscriber's next re-dial; the live session is deliberately not disconnected. See docs/RADIUS.md §2.2. MikroTik is the full-featured case in every mode (docs/MIKROTIK.md §"PPPoE usage").

Works with the Omada software controller 5.0.15+, OC200/OC300 and the Omada Cloud-Based Controller. Reference: "API and Code Sample for External Portal Server" (5.0.15 – 6.2.0, 6.2.10+).

  1. Settings › Authentication › Portal: create a portal for the hotspot SSID, Authentication Type = External Portal Server, Custom Portal Server = the device's portal URL.
  2. Hotspot Manager › Operators: create a hotspot operator (not the admin account) — its username/password go into SimpliFi.
  3. Access Control › Pre-Authentication Access: allow the walled-garden hosts above.
  4. In SimpliFi: controller URL (https://host:8043 for the software controller, https://host for OC200/OC300/cloud), controller ID (omadacId, the ID in the URL after you sign in), site name, operator credentials, Controller version.
  5. Optional Open API app (Settings › Platform Integration › Open API, client-credentials mode, site privileges) → client ID / secret in SimpliFi to list access points and connected clients.
  6. Save, then Test connection (reads /api/info and signs in as the operator).

How it works: the EAP redirects to the portal with clientMac, apMac, ssidName, radioId, site, t, redirectUrl (gateways: clientMac, gatewayMac, vid, site, t, redirectUrl). After payment SimpliFi calls POST /{omadacId}/api/v2/hotspot/login then POST /{omadacId}/api/v2/hotspot/extPortal/auth (Csrf-Token header + session cookie) with authType 4 and time = time allowed. Units: controller 5.0.15–6.2.0 = microseconds, 6.2.10+ = milliseconds (choose Controller version); 6.2.10+ also receives downloadRateLimitKbps, uploadRateLimitKbps and totalTrafficLimitBytes. The vendor documents time both as "time allowed" (sample code) and "expiration time" (field table); SimpliFi sends a duration by default — if clients are cut off right after paying, switch Authorisation time to Expiry timestamp.

Ubiquiti UniFi (controller)

UniFi Network Application (classic, https://host:8443) or a UniFi OS console (UDM/UDR/UCG/Cloud Key Gen2+, https://host). References: ubntwiki UniFi API, Art-of-WiFi UniFi API client.

  1. Settings › Profiles › Guest Hotspot (or Hotspot Manager › Portal on newer versions): Authentication: External Portal Server, enter the portal host/IP.
  2. Pre-Authorization Access: allow the walled-garden hosts above.
  3. Enable the guest hotspot on the customer SSID.
  4. Create a local account without 2FA (a Hotspot role is enough) → SimpliFi username/password.
  5. In SimpliFi: controller URL, site ID (usually default), console type (auto-detect works for most), then Test connection.

How it works: the AP redirects guests to …/guest/s/{site}/?id=<client mac>&ap=<ap mac>&t=…&url=…&ssid=…. SimpliFi signs in (/api/login, or /api/auth/login + /proxy/network prefix + X-CSRF-Token on UniFi OS) and calls cmd/stamgr authorize-guest with minutes, up/down (kbps), bytes (MB) and ap_mac; revoke = unauthorize-guest. Clients from stat/sta, APs from stat/device, health from stat/sysinfo + stat/health.

Ruijie / Reyee (RADIUS)

Ruijie Cloud's open API (/service/api/…, appid/secret → access_token) is not publicly documented for external-portal authorisation or client control, so SimpliFi integrates through RADIUS only.

  1. Ruijie Cloud › Configuration › Authentication: for the SSID choose an external / captive portal that authenticates with RADIUS; portal URL = the device's portal URL.
  2. RADIUS server = SimpliFi's (device page), shared secret, accounting on.
  3. Allowed URLs (walled garden): the hosts above.
  4. In SimpliFi: NAS IP = the public IP of the Ruijie gateway / EG; optional Portal login URL if your portal setup posts credentials to the device.

Customers buy on the SimpliFi portal and receive a username/password; if the redirect carries no login address they type them on the Ruijie login page.

Grandstream GWN (RADIUS + External Captive Portal API)

Reference: Grandstream External Captive Portal API Guide (AP firmware 1.0.11.8+).

  1. GWN.Cloud / GWN Manager › Captive Portal › Policy: Splash Page = External, external portal URL = the device's portal URL.
  2. Authentication type: RADIUS Server — SimpliFi's server, ports 1812/1813, the shared secret, PAP.
  3. Pre Authentication Rules: allow the walled-garden hosts.
  4. Attach the policy to the SSID. In SimpliFi: NAS IP = the public IP the APs' RADIUS traffic comes from.

How it works: the AP redirects with login_url, ap_mac, client_mac, orig_url, ssid; after payment the portal redirects the browser to <login_url>?username=…&password=…&redirect=…; the AP then asks RADIUS (Session-Timeout and WISPr bandwidth are honoured). If login_url is a public host name, add it to Extra login hosts.

Cambium cnPilot / cnMaestro (RADIUS + external hotspot)

Reference: Cambium "Guest Access Portal Integration — cnPilot E400/E500/ePMP1000 Hotspot".

  1. cnMaestro / cnPilot › WLAN › Guest Access: Portal mode External Hotspot, external portal URL = the device's portal URL, success action redirect to original URL.
  2. WLAN RADIUS: SimpliFi's server, ports, shared secret, accounting; NAS-ID as entered in SimpliFi.
  3. Walled garden / whitelist: the hosts above.

How it works: the AP redirects with ga_ap_mac, ga_nas_id, ga_srvr, ga_cmac, ga_Qv, ga_orig_url; after payment the browser POSTs ga_user / ga_pass to http://<ga_srvr>:880/cgi-bin/hotspot_login.cgi (HTTPS: port 444, choose AP login protocol), with the redirect parameters (including the opaque ga_Qv) echoed back. ga_srvr must be a LAN IP or the device's host / public IP. cnMaestro's REST API is not used (its reference is not public), so access points are not listed.

OpenWrt / CoovaChilli / openNDS / pfSense (RADIUS)

CoovaChilli (/etc/chilli/config or chilli.conf):

HS_UAMSERVER / uamhomepage   = <portal URL>
HS_RADIUS / radiusserver1    = <RADIUS server>
HS_RADSECRET / radiussecret  = <shared secret from the device page>
HS_UAMSECRET / uamsecret     = <copy into SimpliFi "CoovaChilli UAM secret">
HS_UAMALLOW / uamallowed     = <walled-garden hosts>

Chilli redirects with res=notyet&uamip&uamport&challenge&called&mac&ip&nasid&userurl; after payment SimpliFi redirects to http://uamip:uamport/logon?username=…&response=<CHAP>&userurl=… (or password=<PAP> when Login method = PAP), computed exactly like hotspotlogin.cgi (challenge hashed with the UAM secret). Data caps use ChilliSpot-Max-Total-Octets.

openNDS (FAS level 0): set fasremotefqdn/faspath to the portal; the redirect carries tok, gatewayaddress, authdir, redir, and SimpliFi sends the browser to http://<gatewayaddress>/<authdir>/?tok=…&redir=…. openNDS does not use RADIUS, so session length is openNDS's own sessiontimeout and SimpliFi cannot revoke it.

pfSense captive portal (RADIUS authentication): upload a portal page that forwards to SimpliFi, for example

<meta http-equiv="refresh" content="0; url=https://<portal URL>?portal_action=$PORTAL_ACTION$&zone=$PORTAL_ZONE$&redirurl=$PORTAL_REDIRURL$">

SimpliFi then POSTs auth_user, auth_pass, zone, redirurl, accept=Login back to $PORTAL_ACTION$ (the pfSense LAN address).

Generic RADIUS (Huawei, Cisco, Aruba, Netgear, Teltonika, …)

  1. External portal / login page = the device's portal URL; RADIUS server, ports, secret as above.
  2. If the device sends a login address in the redirect (link-login, login_url, …), SimpliFi posts username/password (dst = original URL) to it automatically. Otherwise set Hotspot login URL (and the field names if they differ) on the device, or customers type their credentials.

Adding another vendor

Create app/Services/Routers/Drivers/<Vendor>Driver.php extending App\Services\Routers\Vendors\VendorDriver (controller API) or RadiusVendorDriver (RADIUS only), register it in config/simplifi.php (router_drivers, vendor_labels) and in VendorCatalog, and add a section + matrix column here. Never throw from driver methods — return ActionResult::fail() (RouterManager also catches and records devices.last_error).

Report only capabilities the hardware really has. Capability::BURST and Capability::FUP_THROTTLE are read by the package editor to warn the ISP, and App\Services\Hotspot\FupEnforcer falls back to stopping a customer when FUP_THROTTLE is missing. Claiming one you cannot honour sells a feature that silently does nothing; leaving one out only costs a warning in the UI. Implement applyFup() when the vendor can lower the rate of a connected client (RadiusVendorDriver already does it through radreply), and leave the AbstractRouterDriver default in place when it cannot.

For PPPoE there are two more: pppoeUsage(Device, array $usernames) returns per-subscriber counters (Data\PppoeUsage, raw values — Usage\PppoeUsageRecorder turns them into period totals) and is gated by Capability::PPPOE_USAGE, while applyFupToPppoe() lowers a connected subscriber's rate. RadiusVendorDriver implements both from accounting / radreply; a vendor that does not terminate PPPoE leaves the AbstractRouterDriver defaults ([] and unsupported()), and pppoe:usage then leaves those subscribers at full speed with the reason recorded instead of disconnecting a monthly subscription.

Ready to try it on your network?

Start your 14-day free trial today. Set up in minutes, no credit card, cancel any time.

Install SimpliFi App

One tap, no app store. Faster, full screen, works on weak signal.