[TUTORIAL] How to set up noVNC on a web application.

Dec 25, 2021
7
3
3
21
parrot-ctfs.com
A little back story I have had many issues with setting up noVNC after countless hours of research I finally got everything working as designed. I would like to post a quick walkthrough of how I did this so people in the future will have less issues.

I am using the following API Wrapper for this: https://github.com/zzantares/ProxmoxVE


Here is a high-level overview of what we are going to do:

  • install the Api wrapper on our host system.
  • add an Api user and make sure this user has the proper permissions.
  • create functions to preview your VNC on pages of your choice.
  • Iframe the VNC instance on the web application

This set up may not work for you, if this is the case then reply in this thread and I will help you out. There may need to be a few changes that you need to make for your particular set up.

Here is how to create a new user with the perms needed for VNC: ( click on the datacenter and then click on users )

1677997390955.png

Add user by clicking here:

1677997459496.png


1677997495579.png


We then need to make sure there is a password for this new user that we created so here is what I personally like to do for that:


1677997557553.png

Then we can just add a new user here with a strong password ( be mindful of special chars as this proxmox wrapper does not like these chars: '&$'. )

Bash:
adduser api

Then we need to replicate this on the datacenter:

1677997390955-png.47577


Click on the new user that was created and then click on password:

1677997774823.png

Make sure you enter the same password that you entered in the host systems shell prompt.

Then we need to make sure that this new user has the perms needed for this:

( create a resource pool for our resources we want to give to the api user )

1677998442786.png

Then we just need to name it you can name it anything you want.

Once we have this then we can add resources to this pool:

1677998658937.png

Click virtual machines so we can add single machines in bulk:

1677998694119.png

Then just simply add the machines you want the Api user to be able to access

Lastly, we can add the proper perms to the user:

1677999139387.png

File system structure:

--- VNC_API:
- vm_functions.php
- preview_vnc.php


Wrapper Install:

Bash:
composer require zzantares/proxmoxve ~4.0

FILE: vm_functions.php
PHP:
require 'vendor/autoload.php';

use ProxmoxVE\Proxmox;
use GuzzleHttp\Client;

function PreviewVnc($vmID, $nodeid) {
    // pass in the vmid and nodeid from the functions above
    $node = $nodeid;
    $vmid = $vmID;

    // set up the proxmox creds and login
    $credentials = [
        'hostname' => 'proxmox-domain', // Also can be an IP
        'username' => 'api',
        'password' => 'password',
    ];

    $host = $credentials['hostname'];

    $proxmox = new Proxmox($credentials);

    if ($login = $proxmox->login()) {
      
        $ticket = $login->getTicket();
    
        $config = $proxmox->create("/nodes/$node/qemu/$vmid/vncproxy", [
            'websocket' => 1, // Start websocket proxy
        ]);


        $websock = $proxmox->get("/nodes/$node/qemu/$vmid/vncwebsocket", [
 
            'vncticket' => $config['data']['ticket'],
            'port' => $config['data']['port']
        ]);



        $src_href = 'https://'.$host.':8006/?console=kvm&novnc=1&node='.$node.'&resize=1&vmid='.$vmid.'&path=api2/json/nodes/'.$node.'/qemu/'.$vmid.'/vncwebsocket/port/'.$config['data']['port'].'"/vncticket/"'.$ticket;
        echo '<iframe src="'.$src_href.'" frameborder="0" scrolling="no" width="100%" height="100%"></iframe>';
    }
}

?>


FILE: preview_vnc.php

Code:
require 'vm_functions.php';

$vmid = 100;
$node = 'proxmox';

PreviewVnc($vmid, $node);


If all goes well you should now have a VNC instance running on preview_vnc.php
 

Attachments

  • 1677997843715.png
    1677997843715.png
    9.4 KB · Views: 175
Last edited:
Error 401 No ticket

https://myhostip:8006/?console=kvm&...n/nodes/s123/qemu/9505/vncwebsocket/port/5900"/vncticket/"PVE:root@pam:640D7AAD::S/gwT/TL7fGdfC+eVraLJZ3JmvUhKtxFxxWFAJG42Q2FPjMUXWZVBjN5Rn39olTwjIgiuiHCnfrSAd7Jgml/bUSZQ7v/M0lodhlfB96MnGE7ObLJixuldTxDVgf7giDxLiK+UL/ThVPs6darIeZniMN5kaGMXnspywv9u9o/qqW9/EJv0XQECM2u+8Rb4bTMlbVqfc0auX43dW/SqjoCdpINEfdMYAiMGpqInannQdvGG/gnPzrBxe3J3TWbtgAloJB0nZZM27LI53TdIFUdj313sUVBjPxEXOHIL7AB0SOvM7TXC9ejqzABH/PBh3YY2lP0WwIvldQQlRXTmg1omQ=="
 
Last edited:
  • Like
Reactions: stone shai
Error 401 No ticket

https://myhostip:8006/?console=kvm&...n/nodes/s123/qemu/9505/vncwebsocket/port/5900"/vncticket/"PVE:root@pam:640D7AAD::S/gwT/TL7fGdfC+eVraLJZ3JmvUhKtxFxxWFAJG42Q2FPjMUXWZVBjN5Rn39olTwjIgiuiHCnfrSAd7Jgml/bUSZQ7v/M0lodhlfB96MnGE7ObLJixuldTxDVgf7giDxLiK+UL/ThVPs6darIeZniMN5kaGMXnspywv9u9o/qqW9/EJv0XQECM2u+8Rb4bTMlbVqfc0auX43dW/SqjoCdpINEfdMYAiMGpqInannQdvGG/gnPzrBxe3J3TWbtgAloJB0nZZM27LI53TdIFUdj313sUVBjPxEXOHIL7AB0SOvM7TXC9ejqzABH/PBh3YY2lP0WwIvldQQlRXTmg1omQ=="

Hey, so there are two different kinds of tickets there is a VNC ticket and a PVE ticket make sure you are passing the right ticket to the right place. It looks like you are using a PVE ticket to login to the VNC when you need to be using a VNCPVE ticket.


'vncticket' => $config['data']['ticket'], <---- this portion of the code grabs the vnc ticket


the main difference between the two is the PVE ticket authenticates the entire server and the vnc ticket just authenticates the vnc proxy. I hope this helps if you still have trouble let me know.
 
And I just took your code

well, everyone's set up is going to be a little bit different this just goes over the basics of how to set it up. My code should work in theory as it does work on my end. In some cases you may need to have a get access token function that will get a certain ticket to auth with like this:


PHP:
function getAT() {
    $credentials = [
        'hostname' => 'domain.com',  // Also can be an IP
        'username' => 'apiuser',
        'password' => 'pass123',
    ];
    $proxmox = new Proxmox($credentials);
    if ($login = $proxmox->login()) {
        $ticket = $login->getTicket();
        return $ticket;
    }
    return null;

    $getTicket = $proxmox->get("/ticket");

}
 
PHP:
<?php
require 'vendor/autoload.php';
use ProxmoxVE\Proxmox;
use GuzzleHttp\Client;
function PreviewVnc($vmID, $nodeid) {
    // pass in the vmid and nodeid from the functions above
    $node = $nodeid;
    $vmid = $vmID;
    // set up the proxmox creds and login
    $credentials = [
        'hostname' => '123.123.12.12', // Also can be an IP
        'username' => 'root',
        'password' => 'mypassword',
    ];
    $host = $credentials['hostname'];
    $proxmox = new Proxmox($credentials);
    if ($login = $proxmox->login()) {
      
        $ticket = $login->getTicket();
    
        $config = $proxmox->create("/nodes/$node/qemu/$vmid/vncproxy", [
            'websocket' => 1, // Start websocket proxy
        ]);


        $websock = $proxmox->get("/nodes/$node/qemu/$vmid/vncwebsocket", [
 
            'vncticket' => $config['data']['ticket'],
            'port' => $config['data']['port']
        ]);




        $src_href = 'https://'.$host.':8006/?console=kvm&novnc=1&node='.$node.'&resize=1&vmid='.$vmid.'&path=api2/json/nodes/'.$node.'/qemu/'.$vmid.'/vncwebsocket/port/'.$config['data']['port'].'"/vncticket/"'.$config['data']['ticket'];
        echo '<iframe src="'.$src_href.'" frameborder="0" scrolling="no" width="100%" height="100%"></iframe>';
    }
}
?>


Now I changed it to $config['data']['ticket'], it didn 't help
 
well, everyone's set up is going to be a little bit different this just goes over the basics of how to set it up. My code should work in theory as it does work on my end. In some cases you may need to have a get access token function that will get a certain ticket to auth with like this:


PHP:
function getAT() {
    $credentials = [
        'hostname' => 'domain.com',  // Also can be an IP
        'username' => 'apiuser',
        'password' => 'pass123',
    ];
    $proxmox = new Proxmox($credentials);
    if ($login = $proxmox->login()) {
        $ticket = $login->getTicket();
        return $ticket;
    }
    return null;

    $getTicket = $proxmox->get("/ticket");

}
Server error: `GET https://123.123.12.12:8006/api2/json/ticket` resulted in a `501 Method 'GET /ticket' not implemented` response: {"data":null}
 
PHP:
<?php
require 'vendor/autoload.php';
use ProxmoxVE\Proxmox;
use GuzzleHttp\Client;
function PreviewVnc($vmID, $nodeid) {
    // pass in the vmid and nodeid from the functions above
    $node = $nodeid;
    $vmid = $vmID;
    // set up the proxmox creds and login
    $credentials = [
        'hostname' => '123.123.12.12', // Also can be an IP
        'username' => 'root',
        'password' => 'mypassword',
    ];
    $host = $credentials['hostname'];
    $proxmox = new Proxmox($credentials);
    if ($login = $proxmox->login()) {
     
        $ticket = $login->getTicket();
   
        $config = $proxmox->create("/nodes/$node/qemu/$vmid/vncproxy", [
            'websocket' => 1, // Start websocket proxy
        ]);


        $websock = $proxmox->get("/nodes/$node/qemu/$vmid/vncwebsocket", [
 
            'vncticket' => $config['data']['ticket'],
            'port' => $config['data']['port']
        ]);




        $src_href = 'https://'.$host.':8006/?console=kvm&novnc=1&node='.$node.'&resize=1&vmid='.$vmid.'&path=api2/json/nodes/'.$node.'/qemu/'.$vmid.'/vncwebsocket/port/'.$config['data']['port'].'"/vncticket/"'.$config['data']['ticket'];
        echo '<iframe src="'.$src_href.'" frameborder="0" scrolling="no" width="100%" height="100%"></iframe>';
    }
}
?>


Now I changed it to $config['data']['ticket'], it didn 't help
https://123.123.12.12:8006/?console.../nodes/s3356/qemu/9803/vncwebsocket/port/5900"/vncticket/"PVEVNC:640E5602::ZcxySe36YkbisxgRfXs3zqEMGO54zUXP1HdPMJKDjkZ7u7FaUdVYFMS9txDE1h2LVCnSsnZiV0tQzBd4zF4mue8A7evGajTMRoPGJSAsb73QSD8jW3je2bbxLokCqj/o8PzCyRh7yL/4gc3boELBkfsD3awcJKpfuT1zxMFckBMxESRRgog2bn4g9TmtMc8yqnZnViKm0rpaQZ7XVyOmV4LHP9336Ps/Dnh0naMByjTzoLaNw4++1IukrXIRAoDnJ1AvOdS5DPJZuwrCUawvjkSUTgyF7Nj9D/94uC5Z7LipKV9TNOXAq4K+5v8fK0B+UBj+DaibjDfjEbaRGeEF4A==
 
Could you get it to work in the end? I'm also getting a 401 No Ticket error even though i'm using the VNC ticket.
My url looks like this:
Code:
https://172.17.50.250:8006/?console=kvm&novnc=1&node=mynodename&resize=1&vmid=103&path=api2/json/nodes/mynodename/qemu/103/vncwebsocket/port/5900/"vncticket"/PVEVNC%3A64130932%3A%3Adn%2BOzhoQtfRvVKfxd%2F%2BxE9IbBIwegHihcg8IZ2YRce%2BQrRGHcXtFQRr1QSmOMCyJrgzPiHGdu%2Bv0WZmhqK6ablXIsj%2FEY1f%2BVma2Fkp%2FH9A0pvkoQxcMYayLDwZPIFQYAcf%2BLzmQNybVKdGQgCY%2FB%2Bib1abUaohbRWbBUZq6y8CS1S6y8u6DBSf5jp7zc6wugpr3AOWtj%2BpTCtZZWwCChE1t2CyFVF78hAQB%2F1BCPYFx9%2B%2FuEgdKv0s4Vzr%2BHXOQnXy%2F64G55lOcnz6ewIp6v0twwxr1i%2FjD6jmqZ9BBgWgMfzQaiUCLilSA3dE0G8Le30a%2ByReJIJyIi7QqgVvGvQ%3D%3D

Another thing to note is that while i after i get the 401 error, the proxmox webUI shows the connections a bit more before timing out
1678969644491.png
 
Last edited:
  • Like
Reactions: parrotassassin15
Have you guys tried to set the VNC ticket cookie? My webapp works without it but in some cases, you may need it.

Could you get it to work in the end? I'm also getting a 401 No Ticket error even though i'm using the VNC ticket.
My url looks like this:
Code:
https://172.17.50.250:8006/?console=kvm&novnc=1&node=mynodename&resize=1&vmid=103&path=api2/json/nodes/mynodename/qemu/103/vncwebsocket/port/5900/"vncticket"/PVEVNC%3A64130932%3A%3Adn%2BOzhoQtfRvVKfxd%2F%2BxE9IbBIwegHihcg8IZ2YRce%2BQrRGHcXtFQRr1QSmOMCyJrgzPiHGdu%2Bv0WZmhqK6ablXIsj%2FEY1f%2BVma2Fkp%2FH9A0pvkoQxcMYayLDwZPIFQYAcf%2BLzmQNybVKdGQgCY%2FB%2Bib1abUaohbRWbBUZq6y8CS1S6y8u6DBSf5jp7zc6wugpr3AOWtj%2BpTCtZZWwCChE1t2CyFVF78hAQB%2F1BCPYFx9%2B%2FuEgdKv0s4Vzr%2BHXOQnXy%2F64G55lOcnz6ewIp6v0twwxr1i%2FjD6jmqZ9BBgWgMfzQaiUCLilSA3dE0G8Le30a%2ByReJIJyIi7QqgVvGvQ%3D%3D

Another thing to note is that while i after i get the 401 error, the proxmox webUI shows the connections a bit more before timing out
View attachment 48053

I can make a video and link that later today if that would help?
 
Have you guys tried to set the VNC ticket cookie? My webapp works without it but in some cases, you may need it.



I can make a video and link that later today if that would help?
Hello, sorry to bringin this thread up again, can i use API Token instead of PVEAuthCookie? Thanks ! Also do you happen to already made the video?
 
Hello, i use this code and working, you can try :)
you need add auth cookie.

My PVE Node: n1.domain
My APP: vnc.domain

PHP:
<?php

// Require the autoloader
require_once 'vendor/autoload.php';

// Use the library namespace
use ProxmoxVE\Proxmox;

// Create your credentials array
$credentials = [
    'hostname' => 'n1.domain',  // Also can be an IP
    'username' => 'root',
    'password' => 'pass',
    'realm' => 'pam',
    'port' => '8006',
];

// Then simply pass your credentials when creating the API client object.
$proxmox = new Proxmox($credentials);

if ($login = $proxmox->login()) {
    $host = $credentials['hostname'];
    $node = 'n1';
    $vmid = 119;

    $ticket = $login->getTicket();
    setcookie("PVEAuthCookie",$ticket, 0, "/", '.domain' );
    $config = $proxmox->create("/nodes/$node/qemu/$vmid/vncproxy", [
        'websocket' => 1, // Start websocket proxy
    ]);

    $websock = $proxmox->get("/nodes/$node/qemu/$vmid/vncwebsocket", [
        'vncticket' => $config['data']['ticket'],
        'port' => $config['data']['port']
    ]);
    // print_r($login);
    $src_href = 'https://'.$host.'/?console=kvm&novnc=1&node='.$node.'&resize=1&vmid='.$vmid.'&path=api2/json/nodes/'.$node.'/qemu/'.$vmid.'/vncwebsocket/port/'.$config['data']['port'].'/vncticket/'.$config['data']['ticket'];
    echo '<iframe src="'.$src_href.'" frameborder="0" scrolling="no" width="100%" height="100%"></iframe>';
}
 
Last edited:
Can VNC be used without a PVEAuthCookie like Spice? If you have to set a cookie anyway then it's probably easier to just use basic links when the browser cookie is set.

https://{host}/?console=kvm&novnc=1&vmid={vmid}&node={node}&autoresize=true


This doesn't work as it tests for a CSRF token.

It would be nice if the VNC ticket was enough without setting a cookie.
 
Last edited:
This doesn't work as it tests for a CSRF token.

It would be nice if the VNC ticket was enough without setting a cookie.
Is there any way to get around the need for a CSRF token, can we use a reverse proxy that applies the correct token perhaps?
 

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!