Supported RouterOS Versions
| Version | API Method | Notes |
|---|---|---|
| RouterOS 7.1+ | REST API (HTTP/HTTPS) | Recommended. Full feature support. |
| RouterOS 6.x | REST API via www service | Requires /ip service set www enabled. |
/rest/ endpoint prefix for all API calls, which requires the www or www-ssl service to be enabled on the router.Architecture Overview
Connection Setup
Register the NAS device
- Device name: a human-readable label (e.g. “Westlands-POP-1”)
- IP address: the router’s WAN IP (used for RADIUS NAS registration)
- RADIUS secret: shared secret for RADIUS authentication
- CoA port: default is
3799
Run the bootstrap script
BOOTSTRAP_VERSION=2, current) is tunnel-first: it brings the SSTP management tunnel up before touching anything else, so a partial bootstrap leaves the router reachable for retry. Steps:- SSTP tunnel creation with a dedicated PPP profile (
fyberpay-tunnel) - RADIUS client configuration (authentication port 1812, accounting port 1813)
- REST API user creation with scoped permissions
- Firewall rules to allow tunnel traffic, ordered so the tunnel rule lands first
comment=FyberPay-fw:*); the operator’s hand-rolled firewall is never modified.Configure the REST API user
fyberpay-api. This group has the following policies:ftp, reboot, policy, test, password, sniff, sensitive, romon.The REST API service is restricted to the tunnel subnet:API Port Configuration
| Port | Protocol | Use Case |
|---|---|---|
| 80 | HTTP | Default REST API port over SSTP tunnel |
| 443 | HTTPS | REST API with TLS (self-signed certs accepted) |
| 8728 | API | Legacy MikroTik API protocol (RouterOS 6.x) |
| 8729 | API-SSL | Legacy API with TLS |
What FyberPay Reads from the Router
FyberPay polls the following data from each connected router:System Resources
System Resources
GET /rest/system/resourceRetrieves CPU load, memory usage (total/free), uptime, RouterOS version, board name, and architecture. Displayed on the fleet dashboard.Active PPP Sessions
Active PPP Sessions
GET /rest/ppp/activeLists all active PPPoE/PPTP/L2TP sessions with username, service type, caller ID, assigned IP, uptime, and encoding. Used for subscriber session monitoring.Network Interfaces
Network Interfaces
GET /rest/interfaceReturns all interfaces with name, type, running/disabled status, TX/RX byte counters, packet counts, link-down count, and MTU.DHCP Leases
DHCP Leases
GET /rest/ip/dhcp-server/leaseLists active DHCP leases with IP address, MAC address, hostname, status, and expiry time.Simple Queues
Simple Queues
GET /rest/queue/simpleReads all simple queues with name, target address, max-limit, and burst-limit. Used for bandwidth plan enforcement visibility.PPPoE Servers
PPPoE Servers
GET /rest/interface/pppoe-server/serverLists configured PPPoE server instances with service name, bound interface, and disabled state.What FyberPay Writes to the Router
FyberPay’s writes to the router are driven by the NasService model: one row per customer-facing service (PPPoE, Hotspot, or CPE Management), reconciled against live router state by the NasService Reconciler. Operators create services in the FyberPay admin UI; the reconciler translates each service into the right combination of PPPoE servers, hotspot servers, IP addresses, pools, DHCP, VLAN sub-interfaces, walled-garden rules, and bridges on the live router.The NasService model
Each service is one row in thenas_services table with these fields:
| Field | Meaning |
|---|---|
type | pppoe, hotspot, or cpe-management |
parentInterface | The interface on the router the service binds to. Can be an ether port (ether2), an SFP port (sfp1), a VLAN sub-interface (vlan100-mgmt), or an operator-managed bridge (bridge-customer). |
vlanId | Optional VLAN tag. If set, the reconciler creates a VLAN sub-interface as the binding point. |
subnet, gateway, poolStart, poolEnd | Auto-allocated from 10.50.0.0/16 (customer) or 10.20.0.0/16 (management). Operator can override under “Advanced”. |
state | pending → active (or failed / degraded if the reconciler hits an error or detects drift). |
5d8f2a1e-... is named pppoe-svc-5d8f2a1e. Every resource the reconciler creates carries comment=FyberPay-svc:<service-id> so ownership is unambiguous on the router.
The reconciler primitives
Three idempotent primitives, all inapps/api/src/network/nas-services/reconciler.ts:
- applyService(serviceId): read live state for the service tag, compute a diff against the desired state, execute the diff. Used on create, update, manual reconcile, and drift recovery.
- removeService(serviceId): tear down every resource carrying the service tag. Used on delete.
- reconcileDevice(deviceId): scan the device for orphaned resources (carrying a service tag for a service that no longer exists in the database) and remove them.
Bridge as parent interface
If the operator already runs a downstream switch off their MikroTik and wants every customer plugged into any LAN port to use the same service, they create a bridge on the router and pick that bridge as the parent interface. See the bridge-as-parent guide for the full operator workflow. The parent-interface dropdown groups options by type (Bridges, Ethernet, SFP, VLAN). Bridges are filtered to excludebridge, bridge-lan, fyberpay-tunnel, and any FyberPay-managed br-svc-* bridge (those are reserved by the reconciler itself). VLAN-on-bridge is allowed for tagged trunks.
Reserved interfaces (safety guard)
Before any RouterOS write, the reconciler checks the parent interface against a reserved set computed live from the router. The reserved set is the union of seven sources:- Always-reserved names:
bridge,bridge-lan,fyberpay-tunnel - Members of
bridge-lan(the management LAN) - Interfaces with a bound DHCP client (the WAN uplink)
- Interfaces a default route exits through
- Members of the RouterOS
WANinterface-list, if the operator set one - PPPoE/L2TP/SSTP client interfaces (the router dialing out to its upstream)
- FyberPay-managed service-scoped bridges (
br-svc-*) — identified by their service-tag comment
Drift detection
A BullMQ background job runs every ~15 minutes per device. For each NasService, it computes the diff between the live router state and the desired state. If the diff is non-empty, the service is markeddegraded and an outbox event (nas.service.drift_detected) is emitted.
Drift detection is detect-only by default. The operator clicks Reconcile on the service card to apply the diff. Auto-healing is intentionally not on by default to avoid silently undoing deliberate operator changes made in Winbox.
Reconfigure semantics (hard cut)
When an operator changes a service’stype, parentInterface, or vlanId, the reconciler tears down the old resources and creates new ones. Active customer sessions on the affected service are kicked. The UI surfaces a confirmation dialog quoting the impact (“This will disconnect N active users. Re-issue with confirm=true to proceed.”) before allowing the change.
Non-disruptive changes (subnet/gateway/pool tweaks, walled-garden adjustments) apply without kicking sessions.
Other writes
Walled garden (hotspot)
Walled garden (hotspot)
PUT /rest/ip/hotspot/walled-garden
IPs: PUT /rest/ip/hotspot/walled-garden/ipEach hotspot service maintains its own walled-garden rules (Safaricom Daraja endpoints, FyberPay’s payment callback domain, M-Pesa portal). Operators can add custom entries per service.Firewall Address Lists
Firewall Address Lists
PUT /rest/ip/firewall/address-list
Remove entry: DELETE /rest/ip/firewall/address-list/{id}Used for walled-garden enforcement on the L3 path (post-dunning subscribers redirected to a “pay your bill” portal until they pay).Simple Queue Updates
Simple Queue Updates
PATCH /rest/queue/simple/{id}Optional. Used when an ISP manages bandwidth through router-side queues rather than RADIUS attributes (the recommended path is RADIUS-driven via FreeRADIUS, see the FreeRADIUS integration).Device Reboot
Device Reboot
POST /rest/system/rebootTriggers a remote reboot. Requires admin or super_admin role. All reboot actions are recorded in the audit log.What FyberPay does NOT manage on the router
- WAN configuration: never touched. WAN is detected (sources 3/4/5/6 of the reserved set) and protected.
- Operator-managed bridges: their existence and port membership are owned by the operator. FyberPay binds to bridges but never modifies their members or comments.
- Default firewall: never touched. The bootstrap script only adds tunnel-traffic allow rules.
- Existing PPP profiles: never touched. FyberPay creates per-service profiles named
ppp-prof-svc-<slug>.
Fleet Monitoring
FyberPay polls all configured NAS devices in parallel (batches of 10) to build the fleet status dashboard. Each device reports:- Reachability (online/offline)
- Board name and RouterOS version
- CPU load percentage
- Memory usage percentage
- System uptime
- Active PPP session count
RADIUS Configuration
The bootstrap script configures each router as a RADIUS client pointing to FyberPay’s FreeRADIUS server:Troubleshooting
Router shows as unreachable
Router shows as unreachable
- Verify the SSTP tunnel is established: check
/interface sstp-client printon the router - Confirm the tunnel has an IP in the 10.99.x.x range:
/ip address print where interface=fyberpay-tunnel - Ensure the
wwwservice is enabled and bound to the tunnel subnet:/ip service print - Check that the firewall allows tunnel traffic:
/ip firewall filter print where comment~"FyberPay"
API credentials not configured error
API credentials not configured error
SSTP tunnel keeps disconnecting
SSTP tunnel keeps disconnecting
- Confirm the tunnel uses
profile=fyberpay-tunnel(notprofile=default) - Check that
verify-server-certificate=nois set (FyberPay uses self-signed certs for the SSTP server) - Verify the router has stable internet connectivity:
/ping 8.8.8.8 count=5 - Review tunnel logs:
/log print where topics~"sstp"
REST API returns 401 Unauthorized
REST API returns 401 Unauthorized
Circuit breaker is open
Circuit breaker is open
A service stays in 'pending' state forever
A service stays in 'pending' state forever
- Parent interface no longer exists (renamed or deleted in Winbox)
- Parent interface has its own IP that conflicts with the service’s allocated subnet
- A bridge member port has its own
/ip/address(RouterOS won’t allow it as a bridge port) - The router is unreachable (circuit breaker open)
A service shows 'degraded' state
A service shows 'degraded' state
- An operator manually deleted the PPPoE/hotspot server in Winbox
- The router was reset to defaults but FyberPay’s NasService row still exists
- Someone modified a FyberPay-managed resource without going through the FyberPay UI
The bridge I created in Winbox does not appear in the parent-interface picker
The bridge I created in Winbox does not appear in the parent-interface picker
- The bridge is disabled. Run
/interface/bridge enable <name>on the router. - The bridge name is
bridge,bridge-lan, orfyberpay-tunnel(always-reserved). - The bridge’s comment carries a FyberPay service tag (
FyberPay-svc:...). Either you accidentally edited an existingbr-svc-*bridge’s comment, or this is a FyberPay-managed bridge. Pick a different bridge with a different name. - The router is unreachable, so FyberPay cannot list its interfaces.
Security Considerations
- All API traffic flows through the encrypted SSTP tunnel. No RouterOS API ports are exposed on public interfaces.
- API credentials are encrypted at rest using AES-256 (the platform
ENCRYPTION_KEY). - The
fyberpay-apiuser group has minimal permissions: no access topolicy,password,sensitive, orsniffoperations. - Every write operation (reboot, queue change, address list modification) is recorded in FyberPay’s audit log with the acting user, timestamp, and IP address.