Skip to content

Subscribers

The Subscribers page is the central list of every PPPoE / hotspot / static user in your system. From here you create, edit, renew, disconnect, ping, change-service, reset-FUP, rename, refill, top-up, and delete — individually or in batches of up to a few thousand at a time.

The page is paginated server-side (default 25 rows) and counts are pre-aggregated server-side, so it stays fast at 60,000+ subscribers. Stats refresh on every page load; the row data refreshes when you change a filter or click pagination.

Sidebar → Subscribers (people icon). Direct URL: /subscribers.

Visible to every authenticated user. Resellers see only their own subscribers and sub-resellers’ subscribers unless they have the subscribers.view_all permission, in which case they see everyone.

SectionWhat it shows
Stat bar (top)Total, Online, Offline, Active, Inactive, Expired, FUP 0–6, Monthly FUP counters — each clickable as a filter
Filter rowSearch box, Status dropdown, Service dropdown, NAS dropdown, Reseller dropdown
Action toolbar (sticky)Select All, Renew, Reset FUP, Activate, Deactivate, Disconnect, Rename, Add Days, Change Service, Refill, Ping, Delete
TableConfigurable columns (see below); selected rows highlight red
PaginationPage size 25 / 50 / 100 (max 100 per request)

Each tile in the stat bar is a filter shortcut. Click once to filter the list to that subset; click again to clear.

CounterFilter applied
TotalNo filter
Onlineis_online = true
Offlineis_online = false
Activestatus = active
Inactivestatus = inactive
Expiredexpiry_date < now (tenant-local time)
Expiringexpiry_date BETWEEN now AND now + 7 days
FUP 0–6fup_level = N (daily FUP tier)
Monthly FUPmonthly_fup_level >= 1 (any monthly tier active)

The active filter shows a coloured ring around the counter so you always know what you’re looking at.

The search box does a case-insensitive ILIKE %query% across these fields, ordered by hit rate to keep the OR chain short-circuiting cheap:

username, full_name, phone, email, address, mac_address, ip_address, building, region, country, note, static_ip.

Searching by partial username or phone number is the most common pattern.

Click the Columns button (gear icon) to toggle column visibility. Your selection is saved to localStorage per browser.

ColumnWhat it showsDefault visible
UsernamePPPoE username (with optional realm @domain). Cyan in dark mode for readability.Yes
Full NameCustomer’s legal/business nameYes
PhonePrimary phoneYes
MAC AddressBound MAC, if MAC binding enforcedYes
IP AddressCurrent PPPoE-assigned IP (or static, or last-known)Yes
ServiceService plan name + speedYes
ResellerOwner reseller. Sub-resellers show ”↳ Sub of: parent”Yes
StatusBadge: Active / Inactive / Expired (with colours)Yes
Expiry DateNext renewal dateYes
Last Seen”Online Now” if currently up; otherwise relative (“5m ago”, “3h ago”, “2d ago”); “Never” if no recordYes
Daily QuotaDaily used / daily cap as X / Y GBYes
Monthly QuotaMonthly used / monthly capYes
BalanceSubscriber prepaid balance (separate from reseller balance)No
Address / Region / CountryGeographic detailNo
NotesOperator notesNo
Created AtWhen the subscriber row was createdNo

The Online indicator is the green dot next to the username. It is subscribers.is_online, updated by QuotaSync every 30 seconds. A subscriber may briefly show online for up to 30 minutes after losing their PPPoE session if MikroTik missed the Accounting-Stop packet; the Stale Session Cleanup service closes that within five minutes.

Each row has an action column with quick buttons (icons only on mobile, full text on desktop):

  • Edit — Opens the Subscriber Detail page.
  • Renew — Adds one service period to expiry_date, charges the reseller’s balance, resets FUP counters, sends new Mikrotik-Rate-Limit, removes any Auth-Type := Reject.
  • Disconnect — RADIUS CoA Disconnect first; falls back to MikroTik API /ppp active remove if CoA times out.
  • Ping — Executes ping through the MikroTik router (not from the API container, which can’t reach the PPPoE subnet). Result shown in a dismissible toast.
  • Torch — Signal icon on online rows. Shows live per-connection traffic from MikroTik /tool/torch — see the detail page for the modal.
  • Delete — Soft delete (deleted_at = now). The username remains unique-blocked by a partial unique index that excludes deleted rows.

Select rows with the checkboxes and the action toolbar at the top of the table activates. The toolbar is sticky — it stays visible as you scroll. Selected rows turn red with a strong left border so you always know what’s selected.

ActionWhat it doesPermission
RenewPer-row renewal logic, in a loop. Skips subscribers whose reseller can’t cover the cost.subscribers.renew
Reset FUPResets fup_level to 0, zeros daily_*_used, sets last_daily_reset = now. Restores Mikrotik-Rate-Limit. Monthly counters unchanged (only Renew resets monthly).subscribers.reset_fup
Activatestatus = active, removes Auth-Type := Reject from radcheck.subscribers.inactivate
Deactivatestatus = inactive, adds Auth-Type := Reject, disconnects active session.subscribers.inactivate
DisconnectCoA disconnect → MikroTik API fallback. Does not change status.subscribers.disconnect
DeleteSoft-delete. Custom confirmation modal lists subscriber names in bold red text (up to 20 names shown).subscribers.delete
Change BulkOpens Bulk Operations with the selected IDs pre-populated for set-expiry, set-service, set-price, set-reseller, set-static-ip, set-monthly-quota, set-daily-quota.subscribers.change_bulk

Click any header to sort. Allowed sort fields: username, full_name, created_at, expiry_date, is_online. Two derived sorts use SQL expressions:

  • Daily usage(daily_download_used + daily_upload_used) DESC
  • Monthly usage(monthly_download_used + monthly_upload_used) DESC

Default sort is created_at DESC (newest first). Sort persists in the URL so refreshing keeps your view.

Server-side. Page size is capped at 100 to keep PostgreSQL LIMIT queries cheap on large tables. Use the search box and filters to narrow down before paging — scrolling through 60,000 subscribers 100 at a time is not a workflow we optimised for.

  1. Click the Expiring stat counter (filters to users expiring in the next 7 days).
  2. Optionally narrow further by reseller or service.
  3. Click the Select All checkbox in the table header.
  4. Click Renew in the action toolbar.
  5. Confirm. Review the success/failed count in the toast.
  1. Filter by NAS dropdown → select the offending router.
  2. Filter by Status → Online.
  3. Select All → Disconnect.
  4. The system sends CoA Disconnect per subscriber; falls back to MikroTik API where CoA fails. Users reconnect within a few seconds with fresh IPs.
  1. Type the phone number (or partial) into the search box.
  2. The list filters live. Click the row to open the Subscriber Detail page.
  1. Filter by current service plan.
  2. Select the 50 rows you want to move.
  3. Click Change Service in the toolbar — opens the Bulk Operations page with selection pre-loaded.
  4. Pick the target service, optionally tick “disconnect after change” so users reconnect to the new pool immediately.
PermissionEffect
subscribers.viewRequired just to load this page. Resellers without it see “Access Denied”.
subscribers.view_allReseller sees the global list instead of just their own + sub-resellers’ subscribers. Also widens stat counts.
subscribers.createShows the Add Subscriber button.
subscribers.editAllows opening the detail page in edit mode.
subscribers.deleteEnables per-row and bulk Delete.
subscribers.renewEnables per-row and bulk Renew.
subscribers.disconnectEnables per-row and bulk Disconnect.
subscribers.reset_fupEnables Reset FUP.
subscribers.inactivateEnables Activate / Deactivate.
subscribers.pingShows the Ping button.
subscribers.view_graphShows the live torch icon on online rows.
subscribers.change_bulkEnables the Change Bulk button.

Admins bypass all checks and see every action. Resellers with no permission group assigned also see every action (back-compat).