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.
./ 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@realmworks too. For an API token, the user isuser@realm!tokenidand 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=vncon 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-vdagentpackage, a small companion to the usualqemu-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
lessandmanwhen 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
| Situation | Live move? | What to know |
|---|---|---|
| All disks on shared storage | Yes | 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 job | Yes | Only the changes since the last sync move; the replication direction reverses after the migration. |
| Local disks with snapshots, not replicated | No | A mirror can't carry snapshot history — delete the snapshots, or set up replication, which can. |
| Local disks with snapshots, replicated | Yes | Replication carries the snapshots (PVE 7.3 and later). |
| Leftover unused disks on local storage | No | Unattached volumes can't be mirrored — remove the entries first. |
| Local ISO in the CD drive | No | 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 display | Version-gated | Needs PVE 9.2+ and machine version 10.1+ — details under Copy & paste. |
Running cpu=host guest, other CPU vendor on target | No | 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 storage | Never 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.
| Privilege | Unlocks |
|---|---|
VM.Console | Opening a VM or container console |
VM.PowerMgmt | Power actions, including the Start button on a powered-off guest |
VM.Config.Disk | Hibernate, on top of VM.PowerMgmt — it
allocates a state volume, which also needs Datastore.AllocateSpace on the
storage that volume lands on |
VM.Migrate | The Migrate to menu |
VM.Config.HWType | The one-click clipboard Enable |
Sys.Console | Node shells, including the update and upgrade consoles |
Datastore.Audit | Asking 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.Audit | The 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
| Windows | macOS | Linux | |
|---|---|---|---|
| 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.login 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-0and the Mesa packages, or start PMClient withPMCLIENT_WEBKIT_SOFTWARE_GL=1to 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=vncis off or the guest's agent is missing or stopped, and names what it found. See Copy & paste.