PMClient

Documentation

Everything you need to install PMClient, connect to a cluster, and get the most out of consoles, clipboard, terminals and migration. Downloads are on the product page.

Getting started

Windows

Grab the win-x64 executable — or win-arm64 on a Snapdragon-class device — and run it. The application is that one file: no installer.

macOS

Two builds, and they are not interchangeable: osx-arm64 for Apple silicon (M-series) and osx-x64 for Intel. Check under Apple menu → About This Mac if unsure — "Chip: Apple M…" means Apple silicon. Unzip, open the app bundle — WickaSoft-PMClient-osx-x64.app in the Intel download, WickaSoft-PMClient-osx-arm64.app in the Apple silicon one — and drag it to Applications if you want it to stay. macOS 11 or newer.

Taking the wrong build is not subtle: the Apple silicon build will not start on an Intel Mac at all, and the Intel build on Apple silicon runs through Rosetta — slower than the native one for no benefit.

Linux — Debian and Ubuntu

sudo apt install ./wickasoft-pmclient_<version>_amd64.deb

Use the arm64 package on ARM hardware. The package adds PMClient to the applications menu, puts wickasoft-pmclient on your PATH, and pulls in what it needs — including WebKitGTK for browser sign-in. Remove it with sudo apt remove wickasoft-pmclient.

Keep the ./ in that command — it is what makes apt treat the file as a local package and resolve its dependencies. dpkg -i does not, and will simply complain.

Linux — other distributions

tar xzf WickaSoft-PMClient-<version>-linux-x64.tar.gz
./WickaSoft-PMClient-<version>-linux-x64

The tarball preserves the executable bit; a bare binary copied from elsewhere does not, so chmod +x it first in that case. Browser sign-in needs the WebKitGTK runtime (libwebkit2gtk-4.1-0 on Debian-family systems) — password and API-token logins work without it.

Connecting

Everything lives on the bar at the top, left to right:

  • Host — the cluster or node address. The port in use is shown faintly inside the box; a non-standard one goes on the end: pve.example.com:8007. After the first successful login the box remembers and offers previous hosts.
  • Realm — populated from the server once it answers, with the cluster's default preselected.
  • User / Password — for password realms. user@realm works too. For an API token, the user is user@realm!tokenid and the password is the token secret.
  • TOTP — leave it empty unless the account has a second factor. The cluster asks for the code after your password is accepted, so the box is available before PMClient can know whether you need it.

Single sign-on (OpenID / OIDC)

If the cluster has an OpenID realm — Microsoft Entra, Okta, Keycloak, Authentik or any other OIDC provider — pick it and the user and password boxes gray out: sign-in happens in a browser instead. On Windows and macOS that browser is embedded in the window; on Linux it opens as its own window. The embedded browser keeps its session, so later sign-ins are usually silent. To sign in as a different account, tick Choose account before logging in — the provider shows its account chooser instead of reusing the cached session.

PMClient fronts the cluster's own OpenID flow, using the PVE origin as the redirect — the same one the Proxmox web UI already uses — so nothing needs to change in your provider's app registration. The flow never names a provider — any realm whose type is openid qualifies — though Entra is the provider it has been exercised against most.

The certificate question

Most Proxmox installations run on a self-signed certificate, so your first connection asks you to confirm a fingerprint. That confirmation is only worth anything if you check it out of band — over a path that does not depend on the certificate you are checking. Opening the Proxmox web interface to compare would not do it: the browser reaches the same host over the same connection and is shown the same certificate, so you would be comparing a value against itself. Anyone able to substitute that certificate can substitute it for both.

The check that means something is made on the node, over a different path — a console session at the machine, or SSH, which carries its own host key rather than this certificate:

openssl x509 -in /etc/pve/local/pve-ssl.pem -noout -fingerprint -sha256

It prints colon-separated uppercase hex — the same form PMClient shows you — so the two compare directly, with nothing to convert. If they differ, do not accept the connection.

You are asked once per cluster, not once per node — after you accept, PMClient learns the cluster's own certificate authority over that trusted connection, so other nodes (including ones added later) are recognized automatically. A certificate that stops matching what you approved is refused outright, and there is deliberately no button to override it.

Save stores the host, user, realm and the accepted certificate under a profile name. The password itself is never written as cleartext: the operating system's own secret store holds the key — DPAPI on Windows, the login Keychain on macOS, Secret Service on Linux — and only an encrypted token sits beside the profile. Where no store is available, nothing is kept at all.

The tree at a glance

Hover a guest and a popup gives its vitals: status and node always, then whatever the cluster can answer for — uptime, CPU and memory for a running guest, its disk, its HA state where the guest is HA-managed, and network addresses on request. Guests carrying pending configuration changes are marked in the tree; the popup lists each change as key: current → pending, and each can be reverted on its own — not only all at once.

The datacenter summary counts a QDevice witness as the vote it is — a two-node cluster with a witness on a third machine shows the quorum it really has, instead of implying it can't survive a node loss.

VM consoles

Open a QEMU guest from the tree and you get a real VNC console — PMClient speaks RFB directly to the cluster. Containers and node shells get a text console instead, and selecting the Datacenter row opens the Proxmox web UI itself, already signed in where you connected with a password or through your identity provider — an API-token session has no web ticket to carry, so the portal asks you to sign in — embedded in the pane on Windows, macOS and Linux. Where a desktop will not allow the embed, it opens in its own window and says so. PMClient can also jump straight to a guest's own page in the portal, signed-in session carried along. A VM configured with a serial port gets a Serial console button on the console's action bar as well — a text console over the serial device, useful when the graphical one is unhelpful.

  • Encoding — the login-bar box. The default favors fast local networks (ZRLE); switch to Tight when working over a slow link. The box is a request and the server chooses — so the status line reports the encoding actually being sent.
  • Fullscreen — the button, F11, or Ctrl+Alt+Enter. The tree becomes a fly-out tab on the left edge, and the datacenter portal and a guest's hardware page open without making you leave fullscreen first.
  • Send Key — the console bar offers key combinations your own machine would otherwise swallow, and sends them to the guest instead. It appears once the guest's OS type is known, so it is absent where it could not work rather than present and failing.
  • Ctrl+Alt+Del — the console-bar button, or Ctrl+Alt+End; the real chord is caught by your own machine.
  • View only — a switch on the bar that withholds keyboard, mouse and paste, for watching a guest without touching it.
  • Powered-off guests — the console pane offers a Start button instead of failing, when your account may start the guest.
  • Navigation — Alt+← and Alt+→, or the mouse's back and forward buttons, move through where you have been. The keyboard shortcuts stay out of the way while a console or terminal has focus — those keys belong to the guest — while the mouse buttons keep working, because a guest has no use for them.
  • Theme — follows the system by default; pin Light or Dark in About. Consoles and terminals stay dark regardless; that is deliberate.

Resizing the guest desktop

A Resolution button appears on the console bar whenever the connection advertises desktop resizing, with sizes from 1024×768 up to 4K. On std the list is trimmed to what memory= allows (16 MiB when unset — 4K needs 32); on virtio-gpu that setting is not the framebuffer and does not limit it. The button appearing does not by itself mean the guest will accept the change — see below. The resize is sent over the console connection itself; nothing runs inside the guest. In practice this is a Linux capability, and it needs a display the guest can be resized through — virtio-gpu or qxl. The default std display refuses, and PMClient reports the refusal rather than appearing to succeed.

Windows guests don't follow host-initiated resizes on any display type — the virtio-win display driver is display-only and ignores the request. What the console offers instead is a one-click switch of the VM's display to virtio-gpu (needs VM.Config.HWType; the rest of the display config, clipboard=vnc included, is preserved; takes effect after a full stop and start — an in-guest reboot is not enough). That unlocks a much longer resolution list inside Windows, under Settings → Display — and the console follows whatever the guest picks.

PMClient reports honestly either way: QEMU can only confirm a resize request was forwarded to the guest, so when a guest ignores it, PMClient says so instead of pretending it worked.

Copy & paste

Copy inside the guest and the text is on your machine's clipboard; copy on your machine and paste inside the guest. Both directions, over the console connection itself. Two things make it work:

  • clipboard=vnc on the VM's display (PVE 8.1 or later). When it is off the console says so, and offers a one-click Enable clipboard if your account may change VM hardware. If it may not, the console says that instead and names the privilege it would need — VM.Config.HWType — rather than showing a button that would fail. Either way the change takes effect at the guest's next stop/start.
  • The clipboard agent inside the guest. On Windows guests it arrives with the virtio-win guest tools, alongside the QEMU guest agent; on Linux guests it is the spice-vdagent package, a small companion to the usual qemu-guest-agent.

When paste doesn't work, PMClient says why rather than failing silently — it checks whether the guest's agent is actually running and reports what it found. One limit worth knowing: clipboard payloads are capped at 1 MiB.

In a text console — a container console or a node shell — right-click pastes. View-only mode refuses and says so, and a multi-line paste warns first where the program you are pasting into cannot bracket it. In a graphical console right-click still reaches the guest, so right-clicking inside a desktop keeps doing what the desktop expects.

Clipboard and live migration

A running VM with clipboard=vnc will not live-migrate while its QEMU machine version is older than 10.1, and a machine version pinned below 10.1 keeps the block on any cluster. PMClient checks that before you start and shows the target as blocked, rather than letting the transfer fail part-way. Migrating the guest while it's stopped is never affected.

You won't discover this mid-transfer: PMClient's migrate menu shows the condition as Blocked before anything starts.

Text consoles

Containers, node shells and serial-only VMs get a genuine terminal, not a log view — vim, htop, less and full-screen curses programs render properly, in color.

  • Copy is Ctrl+Shift+C (Cmd+C on a Mac). Plain Ctrl+C is left alone — it has to keep working as interrupt.
  • Selection — select with the mouse; a double-click grabs a whole path rather than just a word, and a triple-click takes the line.
  • Scrolling — the wheel moves through history, or pages through less and man when one is running.

Sessions survive. A host shell or container console keeps running when you open something else — come back and the scrollback, and whatever was running in it, are still there. It ends when you press Disconnect, or when you log out. Disconnecting from the cluster ends it too, as does closing the window.

Terminal type

The terminal is an xterm-class emulator with the full 256-color palette. A node shell arrives with xterm-256color already set. A container console starts with TERM=linux, which is why a full-screen program can render poorly there — the console's notice strip says so. Serial consoles vary, and the value doesn't follow you through an onward ssh, so set it yourself:

export TERM=xterm-256color

On a rare guest whose terminfo database lacks that entry, plain xterm is the fallback. Avoid vt100: it works, but it costs you color and the function keys full-screen programs expect.

Migration

Right-click a guest and open Migrate to. Every viable target is listed with its route and cost up front — bare name for shared storage, (replicated) when replication already mirrors the guest there, or (copies 12 GiB) when local disks would have to move. Nodes that cannot take the guest stay visible, disabled, with the reason — an older PVE version, a QEMU too old for the guest's machine type, a running cpu=host guest that cannot cross CPU vendors. A guest that cannot move at all says Blocked and why, before anything starts.

Live migration doesn't require shared storage. A running VM with disks on ZFS, LVM or a plain directory can still move: Proxmox mirrors the disks to the target node while the guest keeps running, and switches over once they're in sync. It takes as long as the data takes — that's the (copies …) price on the menu — and a ZFS replication job shrinks the transfer to the changes since the last sync. Replication is also what makes moving with snapshots possible: a plain mirror can't carry snapshot history, so snapshots on non-replicated local disks have to be deleted first.

When can a guest move? The quick matrix

SituationLive move?What to know
All disks on shared storageYes The fast path — only RAM and device state move.
Local disks (ZFS, LVM, directory)Yes Disks are mirrored while the guest runs; the menu prices it — (copies 128 GiB).
Local disks + ZFS replication jobYes Only the changes since the last sync move; the replication direction reverses after the migration.
Local disks with snapshots, not replicatedNo A mirror can't carry snapshot history — delete the snapshots, or set up replication, which can.
Local disks with snapshots, replicatedYes Replication carries the snapshots (PVE 7.3 and later).
Leftover unused disks on local storageNo Unattached volumes can't be mirrored — remove the entries first.
Local ISO in the CD driveNo Set the drive's media to none first.
Passthrough hardware (PCI, USB, serial)No Blocks any live migration; move the guest stopped instead.
VNC clipboard enabled on the displayVersion-gated Needs PVE 9.2+ and machine version 10.1+ — details under Copy & paste.
Running cpu=host guest, other CPU vendor on targetNo A live guest can't cross vendors on the host CPU's feature set; offline is fine — it re-detects on boot.
Container (LXC), any storageNever live Containers are restarted to move — Proxmox has no live container migration.
Stopped guest, any of the above— Offline moves are the escape hatch: configuration and disks copy, and ZFS/qcow2 snapshots survive.

PMClient tells you which row you're in before anything starts — a disabled target with the reason on it, or Blocked on the menu — never mid-transfer. And when the refusal is the cluster's own policy, it's translated, not relayed: where a single HA resource rule is doing the blocking it is named by its name, with a link that opens the portal's HA rules page.

Before committing you're told what to expect: a running VM keeps running through a live migration with a brief pause, while a container is restarted — Proxmox cannot live-migrate containers, on any storage. During the move, a chip on the guest's row tracks the migration, naming the phase that dominates — disk copy or RAM transfer, with a percentage — when the cluster's task log reports one. A container has no RAM phase, and a short or offline move may show only that it is migrating. An open console rides along: it waits for the guest to be running, re-resolves the new node and reconnects by itself.

Replication & backup

Both live on a guest's right-click menu, beside Migrate, and both follow the same rule as everything else in the tree: PMClient tells you what it can do before you commit, and names the reason when it cannot.

Replication

The Replication submenu lists every job on the guest with its live status. Run a job on demand, or create, reschedule and delete jobs from here — the submenu refreshes in place as you change things. Add target gives an already-replicating guest another destination, listing only the nodes not yet covered; when every node is already a target, the item says so rather than disappearing.

Replication only applies where Proxmox allows it — ZFS-backed guests between nodes of the same cluster. Where it cannot apply, the menu says why instead of offering something that would fail.

Back up now

Back up now opens a submenu of the datastores that can actually receive a backup of this guest. Pick one, confirm, and the running backup's progress shows on the guest's row. If the submenu is empty it says which reason applies rather than showing nothing: no suitable datastore exists, none is visible to this account, none is on this guest's node, or your permissions could not be read — because those need different fixes. On the tree, a guest's backup chip turns red when a scheduled backup was missed or failed, and the hover says which. Where the account cannot read the backup index at all, the chip stays neutral and says so rather than reporting a miss it cannot know about.

Cloning a guest

Right-click a guest and choose Clone…. The cluster's next free VMID is filled in for you; pick a name, Full or Linked, and where it should land — target node, storage and pool. PMClient posts the job, follows the task and tells you how it ended, including the case Proxmox reports as finishing with warnings, which is neither a success nor a failure and is shown as itself.

A linked clone says which template it came from in its hover tip, and wears a clone chip in the tree, on block and file-based storage alike.

The menu entry follows the same rule as everything else here: it is absent where cloning can never apply, and present but disabled, with the reason, where it merely cannot happen yet — the guest is running, the source is not a template for a linked clone, the guest is locked, or your account lacks the privilege.

Balance

The Balance page, under the datacenter, shows how guests are spread across nodes and suggests moves that would even the load, with the reasoning for each. It is a view and a set of suggestions; nothing migrates unless you act on one. A guest you never want moved can be tagged nobalance in Proxmox — Balance leaves it out of every suggestion. The tag is matched whole and case-insensitively, and it has to be applied on the cluster: nothing is excluded until it is. It also respects the cluster's HA node preferences: where a strong suggestion would conflict with one, it says so rather than pretending the preference is not there. Where a row does recommend a move, the suggested target is a button — click it and the migration confirmation opens, rather than leaving you to find the guest and start again. Where the cluster's own scheduler or an HA rule would fight that move, the button is shown but disabled, with the reason on it: the analysis still stands, and PMClient will not quietly post a move the cluster is going to undo.

Where your account cannot check a guest — no permission to migrate it — the page says so on that guest's row and names the privilege once, rather than dropping the guest silently or failing the whole page. The other guests are still ranked and the rest of the analysis still shows.

The page also carries the cluster's own CRS settings — the scheduler mode, whether it rebalances on its own, the imbalance threshold, how many rounds it must persist, the improvement a move has to deliver, and the method used to choose — each with a line saying what it does and what changing it costs. Where your account holds Sys.Modify on the cluster you can change them here and apply; where it does not, the editors are disabled with the reason rather than absent, and the page still reads and explains the settings.

Keeping nodes updated

Right-click a node and open Update. Both actions run in a node console you can watch — real apt output, not a spinner — so they need Sys.Console on the node.

  • Update package database — runs apt-get update; it installs nothing. Afterwards the status bar sums up what's pending by origin — r730: 21 packages pending (17 Debian, 4 Proxmox) — a distinction worth having, since Debian security updates are routine while a Proxmox kernel means a reboot.
  • Upgrade packages… — opens the real upgrade shell on the node, the same one the Proxmox web UI uses, where apt lists exactly what would change and asks before installing. Proxmox only permits this shell for root@pam — its own restriction, not a grantable privilege — so for other accounts the item is grayed with that reason rather than hidden.
  • HA maintenance mode — in the same menu, on a cluster that uses HA. Entering it first shows a plan: every guest on the node, where each would go, and anything that would stop it moving. Run is offered once nothing blocks the plan; it moves the guests, puts the node into maintenance and reports each outcome. Leaving maintenance runs the HA manager as root on the node, so PMClient offers it only to root@pam; Reboot and leave HA maintenance mode… does both in one step. The item shows the state it actually found, even to an account that can't change it.

After a node session ends, PMClient compares the kernel the node booted with the newest one installed and says plainly when a reboot is due to start using the new kernel. When it can't determine the running kernel, it says nothing rather than guessing.

Permissions

PMClient reads your account's effective privileges — including grants inherited through pools, and privilege-separated API tokens — and shapes the UI to match. Power and migration actions you lack stay visible but disabled, with the missing privilege named on them; anything the cluster still refuses is explained in plain language, naming the privilege to request where the client can tell which one is missing rather than guessing at a refusal the server did not itemise. What each privilege unlocks:

PMClient can also change who has access. Manage access… on a guest or a pool opens a pane in two halves. Stored bindings lists the role bindings recorded on that path — identity, type, role and whether it propagates — with Add a role… and Remove, and a tick to include ancestor rows that propagate here, so what the object inherits sits beside what is set on it. Proxmox applies each change immediately; there is no save step and no undo, and PMClient says so rather than implying a draft.

Effective privileges answers the question the binding table cannot: what a chosen account can actually do on this object. Pick a user, a group or a token and every privilege is listed with the role that grants it, the source path it comes from and whether that binding propagates, and a status — applied, or superseded where a binding elsewhere overrides it. Inheritance and token separation stop being something you reconstruct in your head.

And when the account you are signed in as cannot see the whole picture, the pane says so instead of showing a short list as though it were the complete one. It names each thing it could not read and the privilege that would fix it — users and tokens filtered to the ones you may see, groups it could not read at all — so a partial list is never mistaken for a complete one.

PrivilegeUnlocks
VM.ConsoleOpening a VM or container console
VM.PowerMgmtPower actions, including the Start button on a powered-off guest
VM.Config.DiskHibernate, on top of VM.PowerMgmt — it allocates a state volume, which also needs Datastore.AllocateSpace on the storage that volume lands on
VM.MigrateThe Migrate to menu
VM.Config.HWTypeThe one-click clipboard Enable
Sys.ConsoleNode shells, including the update and upgrade consoles
Datastore.AuditAsking a storage for its contents. It gates the request, not the result — individual disk volumes can still be filtered out by per-guest rights the stock auditor role does not include, so a pool can come back empty to an account that holds this
Sys.AuditThe datacenter summary's health, quorum and node membership. Guests and storage still list without it

API tokens are privilege-separated by default in Proxmox: grant the ACL to user@realm!tokenid itself, or disable privilege separation on the token.

Where it writes

WindowsmacOSLinux
Profiles, layout %APPDATA%\PMClient\ ~/Library/Application Support/PMClient/ ~/.config/PMClient/
Saved secrets Windows DPAPI login Keychain Secret Service (GNOME Keyring / KWallet)
Sign-in browser data %LOCALAPPDATA%\PMClient\WebView2 inside the app's container ~/.local/share/PMClient/webkit/

Passwords and token secrets are never stored as cleartext. The operating system's store holds the key and an encrypted token is written beside the profile, so a copied profiles.json is useless on another machine or to another account. On a Linux machine without a running Secret Service — a minimal or server install — PMClient still works; it simply saves no secrets and asks again next launch, rather than writing them anywhere unprotected.

Troubleshooting

  • It won't start, or something looks broken — run it from a terminal with --self-test. It opens the real windows, checks assets, theming and the password store, prints a line per check and exits with a pass/fail code.
  • It crashed — every crash is appended to crash.log in the settings folder (see Where it writes), with the version, OS and architecture. That file, plus what you were doing at the time, is the fastest route to a fix.
  • Single sign-on on an older Windows 10 — browser sign-in uses the WebView2 runtime, preinstalled on Windows 11 and most patched Windows 10. If it's missing, install Microsoft's free Evergreen Bootstrapper once. Password, TFA and API-token logins never need it.
  • Blank or crashing portal or sign-in window on Linux — PMClient says what happened rather than leaving the pane empty: it embeds the portal, opens it in its own window if the desktop will not allow the embed, or says the portal could not start. If the portal's page process crashes in the graphics driver, PMClient reopens it once without the GPU by itself. If that keeps happening on a machine, update libwebkit2gtk-4.1-0 and the Mesa packages, or start PMClient with PMCLIENT_WEBKIT_SOFTWARE_GL=1 to keep the page off the GPU from the start (it costs some CPU on animated pages).
  • First launch on a new machine — there's no installer, so the first run performs the one piece of setup an installer would have done: unpacking bundled libraries into a one-time cache. Two instances launched together on a machine that has never run PMClient — the same file twice, or two copies — will both attempt that unpack, and can trip over each other. Let the first launch finish before opening a second; every launch after that finds the cache in place, and multiple instances are no trouble.
  • Paste stopped working — check the console's hint bar: PMClient reports whether clipboard=vnc is off or the guest's agent is missing or stopped, and names what it found. See Copy & paste.