PVE VDI Client, a Proxmox desktop client built for mass deployment
Proxmox based VDI client
At a glance
- What is it?
- PVE VDI Client is a Python and Tk application that sits between end users and a Proxmox VE cluster, letting a user log in, see the virtual machines they are allowed to open, and connect to them over Spice through virt-viewer. It is one script, a configuration file, and a set of install recipes for Windows, Debian and Fedora, and the interesting engineering is in how a single file is frozen and distributed to a large user base.
- Who is it for?
- The client fits an organisation that has standardised on Proxmox VE and wants to give staff a desktop that shows only the virtual machines they are entitled to, without exposing the hypervisor management interface, and it installs with a single file and a configuration file.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One script in front of a hypervisor
PVE VDI Client is a Proxmox based VDI client, and the project states its purpose plainly: to create a simple VDI client intended for mass deployment. The client connects directly to Proxmox VE and allows users to connect, via Spice, to any virtual machines they have permission to access.
That last clause is the design decision. The application is not a management console for the hypervisor. It is a front end for people who need to use a virtual desktop, and it is deliberately narrow about what a user can see, because what a user can see is decided by their Proxmox permissions rather than by the client.
The repository matches that scope. There is a single application file, vdiclient.py, an example configuration file, requirements scripts for the two platforms, build scripts for Windows and for a Linux binary, a directory of screenshots, the application icon, and a dist/ directory for packaged output. A project of this kind can be read in one sitting, and the whole of its behaviour is in one Python file.
The client is written with Tk, since the Linux install instructions ask for python3-tk and the Fedora instructions for python3-tkinter, and it is packaged for Windows as an MSI. There is also a way to define multiple Proxmox clusters so that end users can select which server group they want to connect to, which is the feature that makes it a desktop pool client rather than a single-site tool.
The connection itself is delegated. The client is not a Spice implementation; it launches the local virt-viewer, which the documentation insists you install first on Windows and lists as a prerequisite on both Linux distributions.
The configuration file is not optional
The readme is emphatic on this point: the client requires a configuration file to function. It searches for the file in a list of locations, and the command line can override that search.
On Windows the locations are %APPDATA%\VDIClient\vdiclient.ini and %PROGRAMFILES%\VDIClient\vdiclient.ini. On Linux they are ~/.config/VDIClient/vdiclient.ini, /etc/vdiclient/vdiclient.ini and /usr/local/etc/vdiclient.ini. That list follows the usual platform conventions, with a per-user location first, then a per-installation location, then a system-wide one for a machine-wide deployment.
The command line options cover the same ground. The help text lists --list_themes for listing all available themes, --config_type with the choices file and http and a default of file, --config_location to specify the config location with a default of searching for the config file, --config_username and --config_password for HTTP basic authentication, and --ignore_ssl to have HTTPS ignore SSL certificate errors, defaulting to false.
The http option is the one that matters for the mass deployment case. If --config_type http is selected, the URL is passed in the --config_location parameter, and the two credential options supply basic authentication. That is a way to serve the configuration from a central server, so that the same client install on a thousand desktops picks up whatever that site group needs, without anyone editing an ini file on the machine.
The readme points at vdiclient.ini.example for the full set of available options, and that file is the real reference for what can be configured.
Three Proxmox permissions carry the whole access model
The permission section is short and it is the security model of the deployment.
Users accessing VDI instances need to have three permissions assigned for each virtual machine they access: VM.PowerMgmt, VM.Console and VM.Audit. The first is the ability to control the machine, the second is the console, which is the Spice connection the client relies on, and the third is the audit permission, which is the read access that lets the client list and describe the machine.
The important property is that these permissions are assigned per virtual machine, not per cluster. A user who is entitled to two desktops gets the three permissions on those two virtual machines and nothing else, and the client shows only what the Proxmox API returns for that identity. In other words, the client does not implement an access control layer of its own, it inherits one, which means there is exactly one place to get the policy right and no possibility of the two disagreeing.
That is the argument for building this on Proxmox rather than building a separate portal in front of it. It is also the argument for being careful with the roles, because a permission granted in Proxmox is effective immediately in the client with no second approval step.
The screenshots in the repository show a login screen, a login screen with a one-time password, and the VDI view, which is the window that lists the machines the user may open.
Three installation recipes and one MSI
The installation section covers three platforms, and each is a short list of commands.
On Debian and Ubuntu the prerequisites are installed with apt, and the client is cloned, prepared and copied into place:
apt install python3-pip python3-tk virt-viewer git
git clone https://github.com/joshpatten/PVE-VDIClient.git
cd ./PVE-VDIClient/
chmod +x requirements.sh
./requirements.sh
cp vdiclient.py /usr/local/bin
chmod +x /usr/local/bin/vdiclient.pyThe Fedora, CentOS and RHEL instructions are the same shape with dnf instead of apt, and python3-tkinter instead of python3-tk. The readme has a copy-paste slip here, since the text above the Fedora commands still says Debian and Ubuntu, but the commands themselves are the right ones for that family.
On Windows the story is different. The readme insists that you must install virt-viewer before using the client, with a link to the Virtual Machine Manager download page, and then points at the releases section for a prebuilt MSI package. That is the deployment path for a large user base: one package, installed by the desktop management system, with virt-viewer handled separately.
Building your own MSI is documented for the case where you need to sign the executable and the installer. You download the legacy WIX 3.14 toolset, install the latest Python 3.14, run requirements.bat to install the necessary packages, make any changes you need, and then run the build_vdiclient.bat script. The emphasis on the legacy toolset and on signing is the tell: this is a project built for organisations that ship signed Windows software.
Freezing one script into a binary with PyInstaller
The Linux binary instructions are the most technical part of the readme, and they are interesting because of what they reveal about the dependency graph.
After the usual prerequisites and the requirements script, the instructions add pip3 install pyinstaller and then run a very long pyinstaller command. The command uses --onefile, --noconsole and --noconfirm, and then lists a series of hidden imports:
pyinstaller --onefile --noconsole --noconfirm --hidden-import proxmoxer.backends --hidden-import proxmoxer.backends.https --hidden-import proxmoxer.backends.https.AuthenticationError --hidden-import proxmoxer.core --hidden-import proxmoxer.core.ResourceException --hidden-import subprocess.TimeoutExpired --hidden-import subprocess.CalledProcessError --hidden-import requests.exceptions --hidden-import requests.exceptions.ReadTimeout --hidden-import requests.exceptions.ConnectTimeout --hidden-import requests.exceptions.RequestException vdiclient.pyThe pattern in that list is the point. PyInstaller analyses the imports it can see statically, and any module that is imported dynamically, or only on an error path, is missed. The Proxmox API client, proxmoxer, loads its backends at runtime, which is why the backend modules, the authentication error and the resource exception all have to be named by hand. The same applies to the requests exception classes, which are only reached when a connection times out, and to the subprocess exceptions, which are only raised when the call to virt-viewer fails. Without those hidden imports the binary would build and then fail at exactly the moment a user hits a network problem or a missing viewer.
The result is a single executable at dist/vdiclient, which is a much better artefact for a mass deployment than a script plus a Python environment. The prerequisite line in the readme has a typo, with virt-viewr instead of virt-viewer, which is the sort of thing to expect from a document that is edited in several places.
Where this client is the wrong tool
The first limit is that it is a desktop program. The client is a Tk application that runs on the user's machine and starts a local virt-viewer to display the console. That is a reasonable design for a virtual desktop, and it is the wrong one for a user who wants to reach a machine from a browser on a phone, or from a machine they do not have administrative access to install software on. The presence of the --ignore_ssl option, which tells HTTPS to ignore certificate errors, is also a flag for a security review, whatever the reason for it.
The second limit is the credential handling. The configuration can be a file or an HTTP resource, and in the HTTP case the username and password are supplied on the command line, where they are visible in the process list of the machine. A deployment that cares about that has to design around it, and the readme does not discuss the alternatives.
The third is the dependency on virt-viewer, which is a real prerequisite rather than an optional extra, and which on Windows has to be installed separately from the MSI. For a mass deployment that is a second package to manage, and the readme treats it as something the reader already knows about.
The fourth is the release history. Version 2.0.2 was published in November 2023 and version 3.0.0 in April 2026, with the last push on the same day as the 3.0.0 release. A two and a half year gap between minor versions suggests a project that is used, occasionally revisited, and released when something needs to change, which is a healthy pattern for an internal tool and a risky one to depend on.
The fifth is scope. There is no directory service integration described, no multi-factor flow beyond the one-time password screen, and no session management or audit trail of its own. The audit trail is Proxmox's, and the user management is the directory's, which is a sensible division and also means this client is not a replacement for either.
Editorial conclusion
The client fits an organisation that has standardised on Proxmox VE and wants to give staff a desktop that shows only the virtual machines they are entitled to, without exposing the hypervisor management interface, and it installs with a single file and a configuration file. It does not fit a team that wants a web client, since the application is a Tk desktop program that hands the connection to the local virt-viewer, and it does not fit a security review that objects to a command line option for ignoring TLS certificate errors. Before deploying it, write the Proxmox roles carefully, since the three permissions it documents are the access control for the whole thing, decide whether the configuration will be distributed per site group over HTTP or by file, and read vdiclient.ini.example, because the readme sends you there for every available option. The licence is Apache-2.0, version 3.0.0 was published on 2026-04-10, and the last push was on the same day.
Frequently asked questions
Which Proxmox permissions do users need for the PVE VDI Client?
Three permissions for each virtual machine they access: VM.PowerMgmt, VM.Console and VM.Audit. The client inherits the access model from Proxmox rather than implementing its own, and it shows only the machines the identity is entitled to.
Where does the PVE VDI Client look for its configuration file?
On Windows in %APPDATA%\VDIClient\vdiclient.ini and %PROGRAMFILES%\VDIClient\vdiclient.ini, and on Linux in ~/.config/VDIClient/vdiclient.ini, /etc/vdiclient/vdiclient.ini and /usr/local/etc/vdiclient.ini. The search is overridden with --config_type and --config_location, and vdiclient.ini.example lists every option.
What do I need before running the client on Windows?
You must install virt-viewer first, and the releases page carries a prebuilt MSI. To build your own, for example to sign the executable and the MSI, you need the legacy WIX 3.14 toolset, the latest Python 3.14, and then requirements.bat and build_vdiclient.bat.
Can the configuration be served over HTTP instead of from a file?
Yes. Use --config_type http and pass the URL in --config_location, with --config_username and --config_password for HTTP basic authentication. That is the arrangement to use when the same client install has to pick up a different configuration per site group.
How do I build a single-file Linux binary of the client?
Install pyinstaller and run it in onefile mode against vdiclient.py, naming the dynamically loaded modules as hidden imports, including the proxmoxer backends and the requests and subprocess exception classes. The resulting executable is placed in dist/vdiclient.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/joshpatten-pve-vdiclient)Was this useful?