Skip to content

Instantly share code, notes, and snippets.

@tomdaley92
Last active November 10, 2025 09:01
Show Gist options
  • Select an option

  • Save tomdaley92/789688fc68e77477d468f7b9e59af51c to your computer and use it in GitHub Desktop.

Select an option

Save tomdaley92/789688fc68e77477d468f7b9e59af51c to your computer and use it in GitHub Desktop.
Proxmox - SPICE Client setup for MacOS

Proxmox - SPICE client setup for MacOS

  1. Install a working (and compiled) version of virt-viewer. You may view the homebrew package's upstream source on GitHub.

    brew tap jeffreywildman/homebrew-virt-manager
    brew install virt-viewer
  2. Once that's installed should be able make a call remote-viewer with a pve-spice.vv file downloaded from proxmox web interface

    remote-viewer pve-spice.vv

    Check out this useful script for debugging. There are also several other cli tools like this one on GitHub that can be used to test the same sort of thing.

Improving Quality of Life

We want remote-viewer to automatically start and open the session when we double click the VM entry in proxmox. To do that we need to first create a small helper application.

  1. Launch Automator and select Application from the dropdown list, when prompted.

    Screen Shot 2021-07-15 at 1 39 31 PM

  2. Search for shell and drag to the right. The contents:

    /usr/local/bin/remote-viewer "$@"

    Make sure to select as arguments for passing the input. Save as ~/Applications/pve-spice-launcher.app.

    Screen Shot 2021-07-15 at 2 13 01 PM

  3. Locate a pve-spice.vv file and right click, and go to Get Info -> Open With -> Change All, look for the .app file you just made.

    Screen Shot 2022-02-16 at 11 26 22 AM

  4. In Chrome, click on the small arrow on the list of downloads at the bottom, and select "Always open files of this type"

    Screen Shot 2021-07-15 at 2 02 46 PM

  5. If everything is set up correctly you should be able to double-click on the VM in the left pane of Proxmox and remote-viewer should start up and take care of the rest.

    Note: the pve-spice.vv files will be automatically deleted by remote-viewer

    Screen Shot 2021-07-15 at 2 05 57 PM

    Screen Shot 2021-07-15 at 4 42 21 PM

Enjoy!

#!/usr/bin/env bash
set -e
# needs pve-manager >= 3.1-44
usage() {
echo "Usage: $0 [-u <string>] [-p <string>] vmid [node [proxy]]"
echo
echo "-u username. Default root@pam"
echo "-p password. Default ''"
echo
echo "vmid: id for VM"
echo "node: Proxmox cluster node name"
echo "proxy: DNS or IP (use <node> as default)"
exit 1
}
PASSWORD=""
USERNAME=""
while getopts ":u:p:" o; do
case "${o}" in
u)
USERNAME="${OPTARG}"
;;
p)
PASSWORD="${OPTARG}"
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
if [[ -z "$PASSWORD" ]]; then
PASSWORD=""
fi
if [[ -z "$USERNAME" ]]; then
USERNAME='root@pam'
fi
DEFAULTHOST="$(hostname -f)"
# select VM
[[ -z "$1" ]] && usage
VMID="$1"
#[[ -z "$2" ]] && usage
NODE="${2:-$DEFAULTHOST}"
if [[ -z "$3" ]]; then
PROXY="$NODE"
else
PROXY="$3"
fi
NODE="${NODE%%\.*}"
DATA="$(curl -f -s -S -k --data-urlencode "username=$USERNAME" --data-urlencode "password=$PASSWORD" "https://$PROXY:8006/api2/json/access/ticket")"
echo "AUTH OK"
TICKET="${DATA//\"/}"
TICKET="${TICKET##*ticket:}"
TICKET="${TICKET%%,*}"
TICKET="${TICKET%%\}*}"
CSRF="${DATA//\"/}"
CSRF="${CSRF##*CSRFPreventionToken:}"
CSRF="${CSRF%%,*}"
CSRF="${CSRF%%\}*}"
curl -f -s -S -k -b "PVEAuthCookie=$TICKET" -H "CSRFPreventionToken: $CSRF" "https://$PROXY:8006/api2/spiceconfig/nodes/$NODE/qemu/$VMID/spiceproxy" -d "proxy=$PROXY" > $NODE-$VMID.vv
exec remote-viewer $NODE-$VMID.vv
@Albertfib6
Copy link

happens the same to me

@hanmilLee
Copy link

hanmilLee commented Mar 30, 2025

MacBook-Pro:Downloads username$ remote-viewer pve-spice.vv

(remote-viewer:9598): virt-viewer-WARNING **: 12:55:11.190: (../src/virt-viewer-window.c:831):accel_key_to_keys: runtime check failed: ((accel_mods & ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) == 0)

...

(remote-viewer:9598): virt-viewer-WARNING **: 12:55:11.354: (../src/virt-viewer-window.c:831):accel_key_to_keys: runtime check failed: ((accel_mods & ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) == 0)

2025-02-06 12:55:11.410 remote-viewer[9598:302570] +[IMKClient subclass]: chose IMKClient_Modern 2025-02-06 12:55:11.410 remote-viewer[9598:302570] +[IMKInputSession subclass]: chose IMKInputSession_Modern

and a pop up saying "Unable to connect to the graphic server pve-spice.vv(1)

@danzokuduro I’m encountering this as well. Has anyone found a solution yet?

@sylfr3na
Copy link

I have been smashing my head into this issue for about two or three days and have yet to find a way to get Spice to connect via MacOS - I have installed the remoteviewer via the homebrew commands listed above but I cannot call remote-viewer with a pve.vv file. I am on an M2 Mac, I've got Pop OS installed on another laptop and that is able to spice into the VMs successfully.
Any ideas before I give up forever?

@Nyrem
Copy link

Nyrem commented May 12, 2025

MacBook-Pro:Downloads username$ remote-viewer pve-spice.vv
(remote-viewer:9598): virt-viewer-WARNING **: 12:55:11.190: (../src/virt-viewer-window.c:831):accel_key_to_keys: runtime check failed: ((accel_mods & ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) == 0)

...

(remote-viewer:9598): virt-viewer-WARNING **: 12:55:11.354: (../src/virt-viewer-window.c:831):accel_key_to_keys: runtime check failed: ((accel_mods & ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) == 0)
2025-02-06 12:55:11.410 remote-viewer[9598:302570] +[IMKClient subclass]: chose IMKClient_Modern 2025-02-06 12:55:11.410 remote-viewer[9598:302570] +[IMKInputSession subclass]: chose IMKInputSession_Modern
and a pop up saying "Unable to connect to the graphic server pve-spice.vv(1)

@danzokuduro I’m encountering this as well. Has anyone found a solution yet?

I had issues connecting to the graphic server aswell, one of the things I did on my MacBook was brew reinstall --build-from-source spice-gtk - now it works.

@Nyrem
Copy link

Nyrem commented May 12, 2025

For the Automator quality of life: path on silicon Macs use /opt/homebrew/bin/remote-viewer (I spent quite a bit of time looking for it until I remembered chatgpt exists.)

@simonryf
Copy link

Maybe only for me when I revisit and maybe for others too:
The copy paste issue has still not be solved after > 6 years. I tried my self with gtk+3 3.24.49 and I still get the

gdkeventloop-quartz.c:585:select_thread_collect_poll: assertion failed: (ufds[i].fd == current_pollfds[i].fd)

Some refs:

Also mentioned in the homebrew tab repo

If anyone knows how copy&paste works on MacOS with spice - let me know please :-)
For the next 6 years I'm probably using noVNC or xrdp.

Happy Proxmoxing

@ealecho
Copy link

ealecho commented Sep 15, 2025

MacBook-Pro:Downloads username$ remote-viewer pve-spice.vv
(remote-viewer:9598): virt-viewer-WARNING **: 12:55:11.190: (../src/virt-viewer-window.c:831):accel_key_to_keys: runtime check failed: ((accel_mods & ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) == 0)

...

(remote-viewer:9598): virt-viewer-WARNING **: 12:55:11.354: (../src/virt-viewer-window.c:831):accel_key_to_keys: runtime check failed: ((accel_mods & ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) == 0)
2025-02-06 12:55:11.410 remote-viewer[9598:302570] +[IMKClient subclass]: chose IMKClient_Modern 2025-02-06 12:55:11.410 remote-viewer[9598:302570] +[IMKInputSession subclass]: chose IMKInputSession_Modern
and a pop up saying "Unable to connect to the graphic server pve-spice.vv(1)

@danzokuduro I’m encountering this as well. Has anyone found a solution yet?

I had issues connecting to the graphic server aswell, one of the things I did on my MacBook was brew reinstall --build-from-source spice-gtk - now it works.

build from source worked for me. M1pro thanks

@gachoinhac
Copy link

I followed host guideline.
But sometime spice connect successful or not. It seems not stable for using remote-viewer.

@thehonker
Copy link

thehonker commented Nov 8, 2025

M4mba, works good with the below as the launcher script, and this virt-viewer
https://github.com/jeffreywildman/homebrew-virt-manager

Note that the gtk4 version may vary - I wonder if there's a stable symlink somewhere that I didn't find

export GTK_PATH=/opt/homebrew/Cellar/gtk4/4.20.2/lib
export GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas
/opt/homebrew/bin/remote-viewer "$@"

@Transamers
Copy link

M4mba, works good with the below as the launcher script, and this virt-viewer https://github.com/jeffreywildman/homebrew-virt-manager

Note that the gtk4 version may vary - I wonder if there's a stable symlink somewhere that I didn't find

export GTK_PATH=/opt/homebrew/Cellar/gtk4/4.20.2/lib
export GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas
/opt/homebrew/bin/remote-viewer "$@"

Was trying to troubleshoot the issue, and yes the quoted shell script works !!
Machine: M4 Max

@simonryf
Copy link

simonryf commented Nov 10, 2025

M4mba, works good with the below as the launcher script, and this virt-viewer https://github.com/jeffreywildman/homebrew-virt-manager

Note that the gtk4 version may vary - I wonder if there's a stable symlink somewhere that I didn't find

export GTK_PATH=/opt/homebrew/Cellar/gtk4/4.20.2/lib
export GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas
/opt/homebrew/bin/remote-viewer "$@"

works great for me too. Copy/paste issue not resolved though:

(remote-viewer:2404): GSpice-WARNING **: 09:54:12.624: Warning no automount-inhibiting implementation available
**
Gdk:ERROR:../gdk/quartz/gdkeventloop-quartz.c:585:select_thread_collect_poll: assertion failed: (ufds[i].fd == current_pollfds[i].fd)
Bail out! Gdk:ERROR:../gdk/quartz/gdkeventloop-quartz.c:585:select_thread_collect_poll: assertion failed: (ufds[i].fd == current_pollfds[i].fd)
[1]    2404 abort      /opt/homebrew/bin/remote-viewer ckagSQVt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment