Partner / Read-Only Role
A “partner” is a non-employee who needs full visibility of the ISP’s operations — every subscriber, every transaction, every report — but zero ability to change anything. Typical use cases:
- A business partner who paid for a stake and wants live dashboards.
- An external auditor doing year-end reconciliation.
- A managed-services consultant monitoring a customer’s deployment.
- A super-admin assistant who answers support tickets but isn’t trusted to delete subscribers.
ProxPanel supports this through a specific combination of user_type, permission group, and IP lockdown — internally referred to as the “Bilal pattern” after the original customer who requested it.
How to get here
Section titled “How to get here”Admin only. From Settings → Users and Settings → Permissions:
/users— create / edit the user account./permissions— create / edit the read-only permission group.
This is a two-step setup. Both must be configured for the role to work.
The three pieces
Section titled “The three pieces”A partner role is three things stacked on each other:
| Layer | What it does | Where it’s set |
|---|---|---|
| 1. user_type = 2 (reseller) | Lets the user log into the reseller panel, not the admin panel. | Users page → Type: Reseller. |
2. Permission group with *.view_all | Bypasses the reseller-scope filter — they see system-wide data. | Permissions page → new group with all *.view_all permissions. |
| 3. allowed_ips lockdown (optional) | Restricts logins to specific source IPs. | Reseller record → Allowed IPs field. |
Without all three, you get a role that’s either too narrow (only sees own subs), too broad (can also edit), or too exposed (anyone with the password can log in from anywhere).
Why a reseller, not an admin
Section titled “Why a reseller, not an admin”ProxPanel has six user types (admin, reseller, support, subscriber, collector, read-only). The “read-only” type sounds like the right answer but is a separate feature for portal-style accounts. For the partner pattern, reseller is the correct user_type because:
- Resellers go through
RequirePermissionmiddleware on every route — fine-grained control. - Admins bypass permission checks entirely — once you’re an admin, you’re root.
- Resellers can be IP-restricted via
allowed_ips. Admins cannot (by design — locking out the only admin is fatal).
The view_all permissions
Section titled “The view_all permissions”The *.view_all family of permissions exists specifically for this role. Each one lifts the scope filter on a specific page:
| Permission | Effect |
|---|---|
subscribers.view_all | See all subscribers system-wide, not just your own. |
transactions.view_all | See all transactions system-wide. |
sessions.view_all | See all active PPPoE sessions. |
resellers.view_all | See all resellers (not just sub-resellers). |
dashboard.view_admin | Unlock admin-style dashboard cards (Top Resellers, etc.). System Metrics is still admin-only. |
A reseller granted all five sees the panel approximately the way an admin sees it — but cannot click any Save / Create / Delete button because they lack the matching .edit / .create / .delete permissions.
allowed_ips — the third leg
Section titled “allowed_ips — the third leg”Even with view-only permissions, a partner still has access to a lot of data. If their credentials leak, an attacker can scrape your entire customer list. The fix: lock the account down to source IPs you control.
allowed_ips is a comma-separated allowlist of IPs or CIDR ranges. Every login and every API call from this account checks c.IP() against the list — see IP Restriction.
For a partner role, typical values:
203.0.113.42— the partner’s office static IP.203.0.113.0/24— the partner’s office subnet.203.0.113.42, 198.51.100.10— office + the partner’s home VPN.
If you don’t know the partner’s IP yet, start with a wide range (0.0.0.0/0 or empty), let them log in once, look at their last_login_ip in the user record, then tighten.
Common workflows
Section titled “Common workflows”Setting up a partner role (full walk-through)
Section titled “Setting up a partner role (full walk-through)”-
Permissions → Add Permission Group. Name:
PARTNER. Description: “Global read-only — view everything, edit nothing.” -
In the new group, tick every permission ending in
.viewor.view_all. Specifically:dashboard.view_admin,subscribers.view,subscribers.view_all,transactions.view,transactions.view_all,sessions.view,sessions.view_all,resellers.view,resellers.view_all,services.view,nas.view,prepaid.view,reports.view,tickets.view,audit.view. Save. -
Resellers → Add Reseller. Username:
partner_bilal. Password: a strong random one. Full name: the partner’s real name. Email: theirs. Set Permission Group toPARTNER. Leave parent empty. -
(Optional but recommended) Edit the new reseller → set Allowed IPs to the partner’s office IP, e.g.
203.0.113.42. -
Hand the partner their credentials and the panel URL. They sign in and immediately see system-wide data.
-
Verify they cannot create / edit / delete by clicking around — every action button should be hidden or 403. Open Subscribers → confirm the Add Subscriber button is missing. Open any subscriber → confirm no pencil-edit icon.
Promoting a partner to “view + ticket reply”
Section titled “Promoting a partner to “view + ticket reply””The partner can now monitor everything, but you want them to answer support tickets too.
- Permissions → open the
PARTNERgroup. - Add
tickets.reply(ortickets.edit, depending on your installed permission list). Save. - Tell the partner to log out and log back in. Their permissions refresh on login. The Tickets page now shows a reply box.
Spotting partner activity in the audit log
Section titled “Spotting partner activity in the audit log”The audit log records who did what. Every action by the partner shows their username:
- Audit → filter
username = partner_bilal. - Sort by date desc. You see every page they visited, every export they downloaded.
- Cross-reference against the partner’s expected hours — anything outside is a flag.
- If their account is compromised, set
is_active = falseon the reseller record to block all future logins (existing JWTs are also blocked because the User row is also marked inactive).
Common mistakes
Section titled “Common mistakes”| Mistake | Symptom | Fix |
|---|---|---|
| Used user_type=admin instead of reseller | Partner can edit anything, even with no permission group. | Delete the user and recreate as reseller. |
Forgot subscribers.view_all | Partner sees their own subscribers (zero) — page looks empty. | Add the permission, log out / log back in. |
Set credit = 1000 accidentally | Partner sees a “balance: -X” in the header. | Set credit back to 0. |
Set allowed_ips to the public NAT gateway | Partner can’t log in from home. | Add their home IP too, or remove the restriction temporarily. |
Granted .edit permissions “for convenience” | Partner accidentally deletes a subscriber. | Remove the .edit / .delete permissions. View-only means view-only. |
Permissions snapshot — what a partner needs
Section titled “Permissions snapshot — what a partner needs”| Group | Permissions |
|---|---|
| Dashboard | dashboard.view_admin |
| Subscribers | subscribers.view, subscribers.view_all |
| Sessions | sessions.view, sessions.view_all |
| Transactions | transactions.view, transactions.view_all |
| Resellers | resellers.view, resellers.view_all |
| Services | services.view |
| NAS | nas.view |
| Prepaid | prepaid.view |
| Reports | reports.view |
| Tickets | tickets.view |
| Audit | audit.view (system-wide audit log) |
Notably absent: any .create, .edit, .delete. Also notably absent: settings.view, permissions.view, users.view, backups.view — those expose admin-only material.
Related pages
Section titled “Related pages”- IP Restriction — the per-reseller IP allowlist used in step 4.
- Permissions — creating the PARTNER permission group.
- Reseller Onboarding — the underlying account-creation flow.
- Audit Log — tracking partner activity.
- Customer Portal Overview — different role entirely; end-customer login.