What the agent can and cannot do

Full disclosure on the optional Panelbot agent: what it runs, what it cannot run even if Panelbot were compromised, how updates and removal work.

Full disclosure, because you are the one taking the risk

The agent is the only part of Panelbot that runs on your machine, so it is the part you should read about most carefully. This page is the complete account: what it is, exactly what it is allowed to run, what it cannot do even in the worst case, how it updates, and how to take it off again. Nothing here is a promise about intentions. Every line is a property of the code and of files you can read on your own server after installing it.

You do not need the agent to use Panelbot. By default Panelbot connects over your panel’s API with a limited credential and nothing lands on your server at all. Connect a cPanel or DirectAdmin server covers that path, and With and without the agent shows capability by capability what each one reaches.

What the agent is

A small Python service that runs under its own system account, panelbot-agent, created with no password and /usr/sbin/nologin as its shell. Nobody logs in as it, including us. It does not run as root.

It opens no network ports. There is no listener anywhere in it, so the agent adds nothing to your server that an outsider on the internet could connect to. All its connections are outbound, from your machine to Panelbot: an HTTPS channel to report status and fetch updates, and an encrypted, mutually authenticated connection to the message channel it receives work on. If your firewall blocks outbound access, the agent simply cannot work; there is no inbound path to fall back on.

Its own code lives in root-owned directories under /opt/panelbot-agent that the agent account cannot write to. It owns only its runtime state directory. That split is deliberate: a compromised agent process cannot rewrite the code it will run next time. The exact file-by-file layout is in What the installer puts on your server.

What it can run

The agent holds no library of its own tricks. It is an executor: each unit of work arrives as an explicit list of program arguments, and the agent runs exactly that list.

Before it runs anything, every instruction is checked:

  • It is cryptographically signed, with a key established when the server enrolled, and the agent refuses anything whose signature does not verify.
  • It names your account and this specific server. An instruction addressed to a different account or a different machine is dropped, not executed.
  • It has an expiry. An instruction that arrives too late is refused and reported back as expired, never run.
  • It is run directly, never through a shell. The arguments are handed to the operating system as a list, so there is no place for shell syntax, pipes, redirection, or command chaining to appear.

Some hosting work genuinely needs elevation, such as reading a mail log that belongs to another account or restarting a service. Rather than run the agent as root, the installer writes a sudoers file listing the exact commands, with their exact argument patterns, that the agent may run with elevation. That file is generated from the published command catalog, the same catalog that defines every operation Panelbot can perform anywhere, so the file on your server is a projection of what the product supports, not a hand-written list that could quietly drift. It is plain text, it is on your machine, and you are meant to read it:

cat /etc/sudoers.d/panelbot-agent

The file is owned by root and the agent account cannot modify it. If a command is not in it, the agent cannot run that command with elevation, whatever anyone tells it to do. When the catalog changes, the agent fetches the new file, checks its signature, and hands it to a root helper that validates it with visudo before it replaces the live one, so a malformed file can never be installed.

Every operation that runs is recorded against your account with its name, the server it ran on, whether it succeeded, and when. Refusals are recorded too. You can review and export that trail; see Audit trail and accountability.

What it cannot do, even if Panelbot itself were compromised

This is the part worth being precise about, so assume the worst case: someone is sending the agent whatever instructions they like, correctly signed.

  • It cannot run anything as root that is not on the sudoers list. Elevation is enforced by sudo in the kernel, against the exact argument pattern, not by our code deciding to be careful. Everything else runs as the unprivileged panelbot-agent account and gets no more than that account already has on your machine.
  • It cannot open a shell or run an arbitrary command as root. There is no general-purpose “run anything” entry in the sudoers file and no shell interpreter between the instruction and the operating system.
  • It cannot rewrite what it runs next time. The program files, the helper scripts, the sudoers file, and the release-signing key all live in root-owned locations the agent account cannot write to.
  • It cannot install its own update. Updates are signature-checked twice, once by the agent and once again by a root-run helper reading a key the agent cannot touch. An unsigned or altered release is refused at both points.
  • It cannot read your customers’ passwords. The allow-listed operations include setting a new panel or mailbox password; there is no operation that reads an existing one, and no password is ever returned to Panelbot.
  • It cannot reach across accounts by way of a symlink. Before running anything that touches a customer’s home directory, the agent resolves the real path and refuses if it lands outside the account it was told to work on.
  • It cannot see your other servers. An agent holds credentials for its own machine only, and only ever receives instructions addressed to that machine. It carries no map of your fleet and no keys to anything else. See Tenant isolation.

What does leave your machine is worth stating just as plainly: the output of the commands the agent was asked to run, and a periodic status report containing the agent’s version, the panel it detected, the checksum of its allow-list, which third-party services it found installed, and basic health figures such as load, memory, and disk. It does not upload your files, your databases, your logs at large, or your customers’ content. What comes back from a command is what that command printed.

Two honest limits on the above. First, an attacker who is already root on your server does not need the agent for anything, and nothing the agent does would stop them; the agent’s boundary protects you from Panelbot, not the other way around. Second, the unprivileged account is a real account on your box: work that does not need elevation runs with that account’s ordinary permissions. The sudoers file is the boundary on root, and it is the boundary that matters.

How updates work

When a new version is released for your server, the agent picks it up on its next status report and applies it itself, so you are not asked to run anything.

Before a new release is allowed anywhere near your server, it is verified: the agent checks the download’s SHA-256 against the expected value, then checks a detached signature against a public key that was pinned on your server at install time and lives in a root-owned directory the agent cannot write to. The root helper that performs the swap re-reads that key and re-verifies the signature itself, so the check does not rest on the unprivileged process being honest. A failed verification stops the update and leaves the running version untouched, with a cooldown before it will try again.

Releases are installed side by side and a symlink decides which one runs, so the previous version is still sitting there. If a new release fails to come up on two consecutive boots, a root gate that runs before the service starts flips the symlink back to the version that was working on the next boot, and marks the bad release so the agent stops pulling it. A bad update therefore costs you a restart, not a broken server. The version actually running is shown on the server’s detail view in your dashboard, so you never have to guess.

How to remove it

Choose Uninstall agent on your Servers page, and the agent removes itself on its next heartbeat (about a minute), or run the uninstaller on the server yourself. It stops and disables the service and removes the unit file and its /etc/tmpfiles.d/panelbot-agent.conf entry, removes all four sudoers drop-ins, removes /opt/panelbot-agent and everything under it, removes the WordPress command-line helper’s refresh schedule and the per-account copies it made, deletes the panelbot-agent account and group, and tells Panelbot the server is no longer enrolled. The server entry stays in your dashboard, and its agent status changes to terminated once the removal is confirmed. Removing is shown only by the separate Remove server action, which also deletes the server entry.

What remains afterwards: the log lines the service already wrote to your system journal, which age out under your own journal retention like any other service; on a server running CSF, the outbound rule the installer added to /etc/csf/csf.allow for the message bus, which the uninstaller does not remove (see What the installer puts on your server for how to remove it by hand); and the server itself, which stays connected over its panel credential and keeps working within what that credential allows. Your panel, your accounts, and your customers’ data are untouched, because the agent never held them; it read through your panel and acted through it.

Removing the agent from the Servers page, or revoking an install approval, is recorded as your decision for that server, and your connect-page default (“Install the PanelBot agent on the servers I connect”) never overrides it. Nothing reinstalls the agent on that server until you ask again: choose Approve agent install (cPanel), or run the install command by hand.

Why we connect with a limited credential by default, and leave root as your decision

When your billing portal hands Panelbot a server, that portal usually holds the server’s root credential. Panelbot does not take it. The connector mints a new, restricted credential on your server, scoped to the specific things the assistant needs, and that is what Panelbot stores. The root credential your portal holds stays where it is.

That is a deliberate choice rather than a technical limit, and the reasoning is simple. Root on your servers is your decision to make, not ours to assume. A limited credential means the worst case of a Panelbot mistake, or a breach at Panelbot, is bounded by a list you can read on your own server and revoke in one click. It also means that when we ask for more, you can see exactly what more buys you rather than being asked for everything up front.

There is a real cost to that choice, and we would rather show it than hide it. A limited credential cannot read raw server logs, cannot manage the firewall as root, and cannot restart a hung service. Those jobs need root, and the way we do root is the agent, because the agent turns “root access” into “this fixed list of commands, on this one machine, each run logged”. That is a very different thing from handing over a root password, and it is why we recommend the agent rather than asking you to paste one.

You can hand over a root credential instead, and Panelbot will use it. We do not recommend it, for the reason above: a pasted root credential has no allow-list, so nothing on our side is bounded by anything except our own code. Permission tiers explained lays out the three ways to connect side by side.

How to approve the install, and what happens next

There are two ways in, and both end in the same place.

From Panelbot. On the connect page (Servers, then Connect server), open the server’s Show details and choose Approve agent install. Your click is the control. Because your billing portal already holds an administrative credential for that server, Panelbot asks the connector for it once, marked for this install only. It is used to run the installer, and then it is discarded: it is never written to Panelbot’s database and never reused for anything else. You do not have to open an SSH session or paste anything. This path is for cPanel/WHM servers only: a DirectAdmin server has no Approve agent install button and always uses the install command below. If you ticked Install the PanelBot agent on the servers I connect under More options on the connect page, cPanel servers your connector delivers are approved as they arrive, so you do not need to click per server. A server connected with a reseller login (a cPanel reseller, or a DirectAdmin reseller or user login key) is never offered the agent, because it has no root; only the server’s own host can do root-level work there. Until the install runs, Revoke approval withdraws it and nothing is installed. If an install fails, the server’s details show the reason and you can approve again or install by hand.

By hand. If you would rather run it yourself, Show the install command in the server’s details gives you the exact install command with a one-time enrollment token in it. Sign in to the server over SSH as an administrator and run it. The token is single-use and short-lived, so an old one cannot be replayed, and the installer is not obfuscated, so you or your team can read it before running it. Install the optional server agent walks through that path step by step.

Either way, what happens next is the same. The installer verifies the release before it runs, creates the unprivileged account, writes the sudoers file, starts the service, and enrolls the server. Within a moment the agent shows as Online in your dashboard with its version, the detected panel, and its last check-in. Live health figures start flowing, and the capability list on that server widens to include the jobs that needed root. Nothing about the assistant’s behaviour toward your customers changes: the same approval rules, the same ownership checks, the same record of everything.