Skip to content

Cluster

A single OPanel server is a cluster of one. Join more servers and they share the same platform database, cluster certificate authority and panel — customers and staff never see individual servers, just capacity.

Every server takes on one or more roles:

Role What it runs
control The controller: API, web UI, job engine, billing, the cluster’s certificate authority
web Sites: nginx, per-site PHP-FPM
edge Public HTTP/HTTPS/HTTP/3, on-demand TLS, the WAF
ssh The customer SFTP/SSH gateway
db Customer MariaDB databases
cache A shared Valkey pool

opanel install gives the first server every role. Servers you add afterwards join with just the roles they need.

A joined server shares the first server’s platform database, cluster CA and panel; new sites go to whichever server has room in the plan’s pool.

  1. On an existing control server, create a one-time join token for the new server’s roles:

    Terminal window
    opanel cluster token create --roles web,edge --pool default --ttl 1h

    This prints the exact opanel join command to run, including the controller address and the cluster CA’s fingerprint.

  2. If the new server has the edge role, make every edge share the same TLS certificates:

    Terminal window
    opanel cluster share-certificates
  3. On the new, fresh Debian 13 server, with the opanel package installed, run the printed command as root:

    Terminal window
    opanel join --controller 10.0.0.1:7444 --token opj_... --ca-sha256 <fingerprint>

    The server verifies the controller against the pinned CA fingerprint before it ever sends the token, so the token is useless to anyone who intercepts it in transit to anywhere but your controller. It then installs the packages its roles need, generates its own keys, receives its certificates and starts its services.

    Flag Purpose
    --node-name Name of the server in the cluster (default: its hostname).
    --node-address Address other servers reach it at (default: the address it used to reach the controller).
    --public-ipv4, --public-ipv6 Public addresses of an edge server, for domain DNS checks.
  4. Check it: opanel doctor on the new server, and GET /api/v1/nodes from the console shows it online and in sync within about a minute.

Give servers a private network for cluster traffic — it isn’t encrypted between edges and web servers. Point customer domains at the public addresses of every edge server, or at a load balancer in front of them.

Plans point at a node pool (for example standard, premium-nvme, eu-west); customers never pick a specific server. When a new site is created, OPanel filters candidate web servers (role, status, pool membership, PHP version, disk and memory headroom) and scores the rest on recent CPU, memory and disk usage plus site count, picking the best fit. Databases are placed on a database pool the same way.

Operators move individual sites, drain a server before maintenance, and act on the rebalancer’s suggestions — customers see only a note in the site’s activity log.

  • Move a site: POST /api/v1/sites/{id}/move. Files copy in the background while the site keeps serving from its current server; the cutover to the new server takes seconds once its copy is caught up. The previous server keeps a stopped copy for a rollback window (24 hours by default) in case you need to move back quickly.
  • Cordon a server (POST /api/v1/nodes/{id}/cordon): stop sending it new sites; its existing sites stay put.
  • Drain a server (POST /api/v1/nodes/{id}/drain): cordon it and move all of its sites off, a few at a time, before you take it down for maintenance or retirement. GET /api/v1/nodes/{id}/drain shows progress and flags any site whose move failed repeatedly.
  • Uncordon (POST /api/v1/nodes/{id}/uncordon): let a server take new sites again.

Every 15 minutes OPanel scores each pool’s web servers on CPU, memory, disk and site count. When a pool stays unbalanced for three evaluations in a row, the rebalancer proposes moving a few busy, small sites from the hottest server to the coolest. By default it only suggests these moves (GET /api/v1/rebalancer/proposals) for an operator to accept or dismiss; turn on rebalancerAutoMoves in placement settings to let it start one move per pool automatically. Pinned sites are never proposed.

Placement setting Default Purpose
maxMovesPerNode 2 Concurrent moves touching one server
maxMovesPerPool 4 Concurrent moves in one pool
rollbackWindowHours 24 How long a moved site’s previous copy is kept
transferMBPerSecond 100 Throughput cap per transfer stream
rebalancerThreshold 0.25 Load spread that triggers rebalancing proposals
rebalancerAutoMoves off Let the rebalancer start moves itself