Skip to content

Client Portal

Self-service portal for hosting customers

The Client Portal is a built-in plugin that gives hosting customers a simplified, branded web interface to manage their assigned VMs - without exposing the full PegaProx dashboard. Customers access it at /portal and can only see VMs assigned to them via VM ACLs.

VM Dashboard

Customers see their VMs with real-time CPU, RAM, disk usage bars, IP addresses, and uptime. Auto-refreshes every 30 seconds.

Power Actions

Start, stop, shutdown, and reboot VMs - the hoster decides which of them the portal offers (see Allowed actions). Each action is logged in the audit trail and appears in the admin task bar.

VNC Console

Embedded noVNC console directly in the portal. Customers can access their VM desktops without any additional software.

Snapshot Management

Create, revert, and delete snapshots with configurable limits (e.g., max 5 per VM). Hosters control whether snapshots are allowed.

2FA Self-Service

Customers can set up TOTP two-factor authentication themselves - scan QR code, verify, done. Uses the same 2FA infrastructure as the main app.

Password Change

Change password directly from the portal header. Validates against the server's password policy.

VM ACLs & Permissions

The Client Portal relies entirely on PegaProx's existing VM ACL system to determine which VMs a customer can see and control. No separate permission model is needed - the portal reads the same ACLs as the main dashboard.

Create a User

Go to Settings → Users → Add User. Set the role to Viewer (or a custom role). Enable the "Portal Only" checkbox so the user can only log in via /portal.

Assign VM ACLs

Go to Settings → Permissions → VM ACLs Add the user to the VMs they should manage. The portal will only show VMs where the user has an ACL entry.

Required Permissions

The user needs no cluster-level permissions - not even cluster.view. The one permission it does need is plugins.view: every portal call goes through the plugin API, which checks it. The built-in Viewer and User roles have it; a custom role needs it ticked, otherwise every portal call answers 403 and the portal stays empty. The portal bypasses the cluster permission check and queries VM ACLs directly. Each action then needs two things: the hoster offers it in the plugin's config.json (see Allowed actions), and the user holds the matching permission on that guest, through a VM permission, a pool grant or their role.

💡 How ACL matching works: For each connected cluster, the portal loads all VM ACLs and checks if the authenticated username appears in the users list of any VM. A wildcard * in the users list grants access to all users. The portal never exposes cluster configuration, node details, or VMs without an ACL entry.

Portal-Only Users

Users with the portal_only flag can only log in via /portal. If they try to access the main dashboard at /, they are immediately logged out. This is enforced both during login (the main dashboard rejects portal-only sessions) and during session restore (navigating to / with an existing portal session triggers an automatic logout). Set this flag when creating or editing users in Settings → Users (the "Portal Only" checkbox).

Hoster Configuration

The portal is configured via plugins/client_portal/config.json (editable in Settings → Plugins → Edit; the file is in the plugin folder of your install, and from 1.4.0 an update keeps it):

Setting Default Description
portal_title "Client Portal" Title shown in the portal header and login page
allowed_actions ["vm.view", "vm.start", "vm.stop", "vm.console"] Which actions customers can perform
allow_snapshots true Enable snapshot management for customers
max_snapshots_per_vm 5 Maximum snapshots a customer can create per VM
allow_password_change true Allow customers to change their own password
show_resource_usage true Show CPU/RAM/disk bars on VM cards
show_ip_addresses true Show VM IP addresses (requires guest agent)
theme_color "#e57000" Accent color for the portal UI
custom_logo_url "" URL to custom logo shown in the portal header

Allowed actions

allowed_actions lists what the portal offers at all, and the portal asks it first: an action the hoster does not list is refused with "Action not allowed by hoster", whatever the user may do elsewhere in PegaProx. An action the hoster lists still needs the user's own permission on that guest.

Portal button Entry in allowed_actions Permission the user needs on the guest
Start vm.start vm.start
Shutdown, Stop vm.stop vm.stop
Reboot vm.restart vm.restart
Console vm.console vm.console

The shipped list has no vm.restart, so reboot is off until the hoster adds it. To offer reboot as well:

"allowed_actions": ["vm.view", "vm.start", "vm.stop", "vm.restart", "vm.console"]

vm.view has no effect here: the portal always lists the guests the user's VM ACLs, pool grants or tenant give them. On 1.4.1 and earlier the Reboot button shows as soon as vm.start is listed, but a reboot still needs vm.restart in this list.

Snapshots, deleting a guest and creating containers are not in this list, they have switches of their own:

Setting Default What the user needs as well
allow_snapshots true vm.snapshot on the guest, at most max_snapshots_per_vm snapshots
allow_destroy false The guest is one of theirs, vm.stop on it, and its name typed to confirm
allow_ct_create with the ct_create block false Room in their tenant quota
allow_iso_mount with allowed_isos or iso_storage false vm.config on the guest, QEMU guests only
allow_password_change true -

ISO mounting offers the ISOs listed in allowed_isos (volume ids such as local:iso/debian.iso) and every ISO on the storage named in iso_storage, and puts the chosen one into a CD-ROM slot of the guest (ide2 unless the call names another of ide0-ide3 or sata0-sata5). From 1.5.0 the portal shows the ISO button when allow_iso_mount is on, and refuses every ISO call while it is off; on 1.4.1 and earlier the button does not show.

AGPL Branding

The portal includes a "Powered by PegaProx" footer with an AGPL-3.0 license notice. This footer is protected by an integrity check - removing or hiding it displays a license violation warning instead of the portal content. Hosters may add their own branding (logo, title, colors) but must not remove the PegaProx attribution.

Self-service container creation

Portal users can create LXC containers themselves (self-service) within their tenant quota. The feature is disabled by default - an administrator must enable it.

Enabling it (administrator)

Set allow_ct_create and add a ct_create block to the portal config. The block configures where and how containers are created:

Setting Description
cluster_id The cluster containers are created on
node The node containers are created on
storage The storage used for the container root disk
bridge The network bridge attached to new containers
allowed-templates list The whitelist of templates portal users may choose from
max cores / memory / disk caps The upper limits for CPU, memory, and disk on new containers

Creating a container (portal user)

Once enabled, portal users get a "+Container" button. They:

  • choose from the admin-whitelisted templates,
  • set a hostname, and
  • set resources (cores, memory, disk) within the configured caps.

Creation is quota-enforced - a request is blocked if it would exceed the tenant quota. On success, the new container is ACL-granted to its creator.

From 1.3 the configured cluster_id must be a cluster of the customer's tenant, the one its quota counts; a target outside that tenant is refused.

Security hardening

The container-creation endpoint is security-hardened: the template whitelist is enforced, resource values are clamped to the configured caps, and the hostname and password are validated.

API Endpoints

All endpoints are under /api/plugins/client_portal/api/ and require authentication via session cookie.

Method Endpoint Description
GET /api/plugins/client_portal/api/config Portal configuration (public, no secrets)
GET /api/plugins/client_portal/api/my-vms List VMs assigned to the authenticated user
POST /api/plugins/client_portal/api/vm/power Start/stop/shutdown/reboot a VM
GET /api/plugins/client_portal/api/vm/console Get VNC console ticket + WebSocket token
GET /api/plugins/client_portal/api/vm/snapshots List snapshots for a VM
POST /api/plugins/client_portal/api/vm/snapshots Create a snapshot
POST /api/plugins/client_portal/api/vm/snapshot-rollback Revert VM to a snapshot
POST /api/plugins/client_portal/api/vm/snapshot-delete Delete a snapshot
POST /api/plugins/client_portal/api/account/change-password Change the authenticated user's password