Remote Spice access *without* using web manager

I have created a small windows command line app (.net) that achieves the same result if anyone wants it. I can put the code on github or provide a built exe.

Thank you for posting the link to the code.
I have disabled UserName/Password login for security reasons and only use key-pair authentication.
I do not know enough about programming and compiling to create my own app so cannot edit the code to let me use it.
Is there an easy code change that would let me use the code with key-pair authentication to the host?
 
Great job on the scripts guys!
Has anyone gotten either the golang or the bash script method to work with ssh port forwarding?
I'm trying to connect from an external network and I'm simply forwarding port 8006 from my proxmox machine.
The remote-viewer authenticates and opens properly, but then it gets stuck on a screen that says graphics are loading forever.
 
Sorry guys, rookie mistake. I have solved the problem.
I was forwarding port 8006 from my proxmox host, but I also had to forward port 3128.
Worked like a charm!
 
Here is a Perls script I created that will run on a Windows PC and automate the process to fetch a SPICE ticket from a Proxmox host, then launch RemoteViewer, using the SPICE ticket for configuration, to setup a Remote Desktop using SPICE protocols.

The script is heavily commented so remove comments if you want to compact it.

To use this script:
Install Strwberry Perl on Windows
Install the NET::SSH::perl module in Perl
Install RemoteViewer on the PC
Copy/Paste this script into a .pl file
Edit the parameters at the top of the script to suit your situation
Run the script

A Remote Desktop will launch, connecting you to your VM using SPICE protocols

I have violated securtiy norms by passing a password, but it is AFTER I connect using SSH with key-pair and I lock my PC down, so I am OK with it. If you want ot change using Expect (will not loadd on Windows) or React, it is yours to modify.


Code:
#!C:\StrawberryPerl\perl\bin\perl5.30.2.exe
###!/usr/bin/perl
###!perl

# See perldoc.perl.org for information on Perl
# # comments out a line ; / ... / comments out everything between the slashes

# Include this whenever creating code; If you want to comment it out for production, your call
use warnings;
# You may want to comment this out for production (resource usage) but use for development
use diagnostics;
# Use this to ensure you properly declare variables prior to their use and reserve space for them
use strict;

# Enable the module that will setup SSH connections
# Make sure the module is installed and if not, install it with "cpan install Net::SSH::Perl"
use Net::SSH::Perl;

# Establish Parameters for the connection and command to use for fetching the SPICE ticket
my $host = 'host_ip_address';
my $debug_flag = 1;
my $port_number = 22;
my $protocol_selection = '2,1';
my $user = 'linux_user_name_on_remote_host';
my $user_password = "linux_user_password_on_remote_host";
my $node_name = "Proxmox_node_name";
my $vm_number = number_of_virtual_machine;
my @identity_file_location = ( "C:\\path\ to\ file\\using\ windows\slashes.pem" );

# Establish Parameters for the conversion of the raw ticket to a format remoteviewer can use
# Tell the system what encoding you will be using: more necessary for read but a good habit to get into
my $encoding = ":encoding(UTF-8)";
# Set the filename and path for edited file
my $output_filename_with_path = "C:\\path\ to\ ticket\ file\\using\ windows\slashes.vv";

# identify the location of the Remote viewer application that will use the ticket / configuration file generated
# Put this inside single brackets and do NOT use \ to designate literal character
my $path_to_remoteviewer_program = 'C:\Program Files\VirtViewer v8.0-256\bin\remote-viewer.exe';

# =======================================================

# Instantiate the SSH connection object using the method enabled above NET:SSH:Perl
my $ssh_connection = Net::SSH::Perl->new( $host , debug => $debug_flag , port => $port_number , protocol => $protocol_selection , identity_files => \@identity_file_location );
# Or, to have it work with user/password (when user/password is enabled)
# my $ssh_connection = Net::SSH::Perl->new( $host , debug => 1 , port => 22 , protocol => 2 );

# Login to the remote host
$ssh_connection->login($user);
# Or, to have it work with user/password (when user/password is enabled)
# $ssh_connection->login($user,$user_password);

# Issue the command at the remote host to generate the SPICE ticket and put it into a variable called $output
# I know storing a password in a script and sending it is a security issue
# If someone else wants to use Expect or React for making an interactive script, be my guest
# This script uses key-pair to make the encrypted connection, then sends the password so I am ok with the transmission
# Yes, storage of password in a readable text file is risky; I password protect my PC and do not allow others access
my $command = ( "echo $user_password | sudo -S pvesh create /nodes/$node_name/qemu/$vm_number/spiceproxy" );
my ($output, $error_message, $exit_code) = $ssh_connection->cmd( "$command" );

# Read the raw ticket content, edit the content to match what remoteviewer is looking for
# and write the edited content to a file on the system that is hosting the script
# We will use this edited content file as the configuration settings when we launch remoteviewer
# Create the file handler, with read and/or write permission (include the $encoding as shown)
#    The '>' designator tells the system this file handler is for writing
#    To Read, use "< $encoding"
#    To Read and Write use "+< $encoding"
#    To Read and Write by deleting existing content in a file (truncating) use "+> $encoding"
#    To Read and Write by appending to existing contents of a file use "+>> $encoding"
# If the file deos not already exist, it will be created
# Note: the $! system variable contains the error code for the failure.  If $! is empty, there was no error
open ( my $raw_content_handler , "< $encoding" , \$output ) or die "Could not open the raw content due to $! \r\n";
open ( my $output_file_handler , "> $encoding" , $output_filename_with_path ) or die "Could not open file $output_filename_with_path due to $! \r\n";

# Bring the file contents in one line at a time
# When you use <filehandler> syntax, the <> brackets bring in the next line of a file
# When you us <STDIN>, the system assumes there will user input from STDIN and waits
# If you do not define a variable for bringing the contents in, Perl uses the system variable $_ to hold each line
# So if you use while ( <file_handler> ) without assigning it to a variable, the line will be in $_
# I prefer the explicit assignment to a variable so I use while ( my $variable = <file_handler> ) and use $variable
# This script is parsing a specific format to convert it to another specific format,
# so the sequence is unlikely to be exactly what you will want to use in your situation
# but the functions shown give you a sample of what text manipulation looks like in Perl
# Re-set the file pointer for the input file to the start of the file
# Usually not needed but a good habit to get into
seek $raw_content_handler , 0 , 0;
# Since we are creating a linux file from a Windows script,
# the newline character will be Windows and will be problematic on linux
# We need to change the $INPUT_RECORD_SEPARATOR = $/ but do not want to do that globally, just in this script
# so we put the editing functions into a subroutine and change a local version of $/
# Initialize the first line of the file (specific to this situation; normally initialize to blank)
our $edited_contents = "[virt-viewer]\n";
while ( my $file_line = <$raw_content_handler> ) {
    # Delete / skip lines that have + as the first character; they are delimeter lines
    if ( substr( $file_line , 0 , 1 ) eq '+' ) {
        next;
    # Delete / skip the second line - it is a header line
    } elsif ( substr( $file_line , 0 , 5 ) eq '| key' ) {
        next;
    } else {
        # The remaining lines have the content we want, so we will manipulate them to our format
        # Delete the first two characters of each line (they are "| ")
        substr( $file_line , 0 , 2 ) = '';
        # Convert what was the middle | character (now the first | in the line) to an = sign
        # and insert a ~ character before and after the = sign so we can hold a spot for them later
        $file_line =~ s/ \| /~=~/;
        # Convert all the remaining | to spaces
        $file_line =~ s/\|/ /g;
        # Trim white space at start and end of each line
        # Remove white spaces from left side of string
        $file_line =~ s/^\s+//;
        # Remove white spaces from right side of string
        $file_line =~ s/\s+$//;
        # Remove white space between first "word" and = sign
        # Make sure there is at least one space before making the edit
        my $first_space_location = index( $file_line , " " , 0 );
        if ( $first_space_location != -1 ) {
            my $first_character_location_after_space = index($file_line , "~" , $first_space_location + 1 );
            substr( $file_line , $first_space_location , $first_character_location_after_space - $first_space_location ) = '';
        }
        # Delete the temporary placeholder ~ characters surrounding the = sign
        $file_line =~ s/\~//g;
        # Replace the Windows newline \r\n with the Linux newline \n
        # Remove the Windows newline
        chomp $file_line;
        # Save the remaining characters into the output line with the linux newline
        $edited_contents .= $file_line . "\n";
    }
}

# Save the edited contents into the output file
# Set the file pointer to the start of the file and erase the existing contents to create a blank file
# Not necessary for a new file but a good habit to get into IF you do not want to append to a file's contents
seek $output_file_handler , 0 , 0;
truncate $output_file_handler , 0;
# Write your edited contents to the output file
print $output_file_handler $edited_contents;
# Close the file - which will ensure that buffered content is completely written and any lock is released
close $raw_content_handler or die "Could not close the raw content holder due to $! so content may not be properly written \r\n";
close $output_file_handler or die "Could not close the file $output_filename_with_path due to $! so content may not be properly written \r\n";


# Launch the remoteviewer application using the formatted configuration file
# There will be a series of warnings generated but the viewer will launch and work
system ( "$path_to_remoteviewer_program" , "$output_filename_with_path" ) or die "Errors encountered while launching from $path_to_remoteviewer_program \r\n";


# (Use when debugging) Show that you made it to the end of the script without erroring out
# print "\r\n\r\nMade it to the end of the script!\r\n\r\n";
 
Hi,

Tested the tool, works like a charm in the local network, but as soon as i access this from a remote location/network it refuses to open the console. it just silently exits, i have the port 3128 open in the firewall. any help on this... - i have even tried - local ssh tunneling of port 8006 and 3128 using plink -L 8006:proxmox-local-ip:8006 -L 3128:proxmox-local-ip:3128 user@ssh-server

then ran the proxmox spice launcher with the ip as localhost, tried everything ... can you please help if possible
 
Hi,

Tested the tool, works like a charm in the local network, but as soon as i access this from a remote location/network it refuses to open the console. it just silently exits, i have the port 3128 open in the firewall. any help on this... - i have even tried - local ssh tunneling of port 8006 and 3128 using plink -L 8006:proxmox-local-ip:8006 -L 3128:proxmox-local-ip:3128 user@ssh-server

then ran the proxmox spice launcher with the ip as localhost, tried everything ... can you please help if possible
Which "tool" are you talking about?
There are numerous soltions posted in this thread.
 
Thank you very much for the ProxMox spice launcher! It works great! I can connect from my windows PC in local network to VM ubuntu desktop now!

Could you tell me please how I can connect to my linux VMs from android tablet in local network? What application I should use for it? And how to configure it?

Maybe I can run some script directly on ProxMox server for create instant proxy for making an access directly to VM by spice on some ports?
 
Last edited:
Works on some machines and not on some,, mostly works on Win7 and not on win10.
but on the win10 systems works with the web interface download.vv and remote-viewer.exe

any ideas ?
 
Works on some machines and not on some,, mostly works on Win7 and not on win10.
but on the win10 systems works with the web interface download.vv and remote-viewer.exe

any ideas ?

Edited: - works on Win too. it was a issue with my windows profile. its ok now after I deleted and re-created a new user profile in windows
 
Last edited:
Hi
I tried to follow your instructions. But I think I'm doing something wrong because it doesn't work for me. Can you help please?
1.png
 
Hi mr Lupo,
I'm trying to run cv4pve-pepper, but I don't understand how to run it.

from the github:
"E.g. install on linux 64

Download last package e.g. Debian cv4pve-pepper-linux-x64.zip, on your os and install:

root@debian:~# unzip cv4pve-pepper-linux-x64.zip"

But I don't find this zip file. I guess I have to compile it.
Can you explain me how to, I'm running linux.
Do I need powershell?

or is there a place where I can download the binary?
 
it's a paramater of remote-viewer, to run it in fullscreenmode.
I need to make so that the end user have his VM run in fullscreen mode when his PC starts.
(kiosk mode is more than fullscreen, it removes the widget on top where you can disable fullscreen, change tty etc, so that the end user cannot escape his VM)
 
Last edited:
@frank lupo
When I execute the script in U20.04, it seems to execute but nothing happens. I tested it by putting in wrong passwords and wrong hosts and get errors, but when I put in all the right info, I get nothing:
./cv4pve-pepper --host=192.168.1.111 --username=root --password=secret --vmid 100 --viewer /usr/bin/virt-viewer
I'm using the following:
--host=IP of the Proxmox server
--username=same username as when logging in to Proxmox from the web interface
--password=same password as when logging in to Proxmox from the web interface
--vmid=virtual machine number in Proxmox

Is there a debug mode so I can find out what's going on?

Thanks,
Grant
 

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!