ProxmoxVE
ProxmoxVE copied to clipboard
VNC Trough the API
Hi there,
Thanks for developing this nice API wrapper! I'm very pleased with this!
I want to show the VNC client out of the Proxmox environment but get a 401 No Ticket and I don't really see what i'm doing wrong around here.
Would you mind to take a look at my code?
if($proxmox->login()) {
$config = $proxmox->create('/nodes/vm-1/lxc/100/vncproxy');
$websock = $proxmox->get('/nodes/vm-1/lxc/100/vncwebsocket',
[
'vncticket' => $config['data']['ticket'],
'port' => $config['data']['port'],
]);
return '<iframe src="https://my-server:8006/?console=lxc&novnc=1&node=vm-1&resize=scale&vmid=100&path=' . urlencode("api2/json/nodes/vm-1/lxc/100/vncwebsocket?port=" . $config['data']['port'] . "&vncticket=" . $config['data']['ticket']) . ' frameborder="0" scrolling="no" width="1024px" height="100%"></iframe>';
}
Thanks in advance! Cheers, Ramon
I'm sorry, I'm just seeing this! 😩 . A guy have contacted me with the same exact problem, did you manage to solve it? it was a problem with the library or with the API consumption? I honestly should say I did never test the vnc via api, so I couldn't help.
If you could share your findings would be helpful for others having the same issue.
Hi there,
Could not solve the problem :(.
You haven't closed your src="" the last "
Hi @RamonSmit @ZzAntares
This code would work, be aware that you have to change the default variables.
<?php
use ProxmoxVE\Proxmox;
$credentials = [
'hostname' => 'server-node',
'username' => 'root',
'password' => 'supersecurestrongpassword',
'realm' => 'pam'
];
$proxmox = new Proxmox($credentials);
if($proxmox->login()) {
$config = $proxmox->create('/nodes/server-node/qemu/100/vncproxy');
$websock = $proxmox->get('/nodes/server-node/qemu/100/vncwebsocket',
[
'vncticket' => $config['data']['ticket'],
'port' => $config['data']['port']
]);
echo 'https://server-node:8006/?console=kvm&novnc=1&node=server-node&resize=scale&vmid=100&path=api2/json/nodes/server-node/qemu/100/vncwebsocket?port=' . $config['data']['port'] . '&vncticket=' . $config["data"]["ticket"];
echo PHP_EOL;
}
Thanks! So the generated URL just needs to be in an iframe and that's it, right?
I'll add this to the Readme before closing the issue. 👍
That's true, I'd have to test it further and then I'll give you a final response.
Kudos hehe!
Hi @YWatchman I tried it just like you mentioned it above, but unfortunately it didn't work. I get a 401 No ticket error. How did you get it working? Isn't it mandatory to use cookies for this?
Haven't had any time looking at it further, I'll note it in my calendar for this sunday.
Hi @YWatchman, i have the same 401 no ticket error. Did you make any progress on this issue?
Didn't make any progress. It seems like you will need to create your own VNC client or use the vnc sdk.
Didn't make any progress. It seems like you will need to create your own VNC client or use the vnc sdk.
Problem can be solved by adding modifications to HTTPServer.pm file under /usr/share/perl5/PVE/
Hi @justamoose, exactly which modifications need to be added?
@ZzAntares One of solutions is authorization through external user with vnc permissions At first - create user for vnc with limited rights,then patch HTTPServer.pm file with following code (edit username to your)
if ($require_auth) { - die "No ticket\n" if !$ticket; - - ($username, $age) = PVE::AccessControl::verify_ticket($ticket); - - $rpcenv->set_user($username); + if ($rel_uri =~ /vncwebsocket/ && $method eq 'GET' && !$ticket) + { + $rpcenv->set_user("vnc\@pve"); + $username = "vnc\@pve"; + $age = 60; + } else { + die "No ticket\n" if !$ticket; + ($username, $age) = PVE::AccessControl::verify_ticket($ticket); + $rpcenv->set_user($username); + } if ($method eq 'POST' && $rel_uri =~ m|^/nodes/([^/]+)/storage/([^/]+)/upload$|) { my ($node, $storeid) = ($1, $2);
@ZzAntares One of solutions is authorization through external user with vnc permissions At first - create user for vnc with limited rights,then patch HTTPServer.pm file with following code (edit username to your)
if ($require_auth) {
die "No ticket\n" if !$ticket;
($username, $age) = PVE::AccessControl::verify_ticket($ticket);
$rpcenv->set_user($username);
if ($rel_uri =~ /vncwebsocket/ && $method eq 'GET' && !$ticket)
{
$rpcenv->set_user("vnc\@pve");
$username = "vnc\@pve";
$age = 60;
} else {
die "No ticket\n" if !$ticket;
($username, $age) = PVE::AccessControl::verify_ticket($ticket);
$rpcenv->set_user($username);
} if ($method eq 'POST' && $rel_uri =~ m|^/nodes/([^/]+)/storage/([^/]+)/upload$|) { my ($node, $storeid) = ($1, $2);
How do I need to add the user
Did anyone figure out a way to make this work without having to patch PVE?
Did anyone figure out a way to make this work without having to patch PVE?
Yes. I found a way to cheat it with cookies. Works only if everything(proxmox + client panel) at one domain (including subdomains) Example: node1.pve.example.com - proxmox cp.example.com - client panel, where you need to make redirect user to VNC with restricted access.
Thank you very much for your quick reply! You steered me in the right direction (everything under the same domain) and the rest was easy :)
Works great. Thank you!
Hi there,
Thanks for developing this nice API wrapper! I'm very pleased with this!
I want to show the VNC client out of the Proxmox environment but get a 401 No Ticket and I don't really see what i'm doing wrong around here.
Would you mind to take a look at my code?
if($proxmox->login()) { $config = $proxmox->create('/nodes/vm-1/lxc/100/vncproxy'); $websock = $proxmox->get('/nodes/vm-1/lxc/100/vncwebsocket', [ 'vncticket' => $config['data']['ticket'], 'port' => $config['data']['port'], ]); return '<iframe src="https://my-server:8006/?console=lxc&novnc=1&node=vm-1&resize=scale&vmid=100&path=' . urlencode("api2/json/nodes/vm-1/lxc/100/vncwebsocket?port=" . $config['data']['port'] . "&vncticket=" . $config['data']['ticket']) . ' frameborder="0" scrolling="no" width="1024px" height="100%"></iframe>'; }
Thanks in advance! Cheers, Ramon
- Your site and the panel itself must be in 1 domain (Example: example.com & cp.example.com)
- Before showing the iframe, you must set the cookie "PVEAuthCookie"
<?php
if($login = $proxmox->login()) {
/* SET COOKIE FOR DOMAIN & SUBDOMAINS example.com, .example.com*/
setcookie('PVEAuthCookie', $login->getTicket(), 0, '/', 'example.com', false);
$config = $proxmox->create('/nodes/vm-1/lxc/100/vncproxy');
$websock = $proxmox->get('/nodes/vm-1/lxc/100/vncwebsocket', [
'vncticket' => $config['data']['ticket'],
'port' => $config['data']['port'],
]);
return '<iframe src="https://cp.example.com:8006/?console=lxc&novnc=1&node=vm-1&resize=scale&vmid=100&path=' . urlencode("api2/json/nodes/vm-1/lxc/100/vncwebsocket?port=" . $config['data']['port'] . "&vncticket=" . $config['data']['ticket']) . ' frameborder="0" scrolling="no" width="1024px" height="100%"></iframe>';
}
?>
Hi @justamoose, exactly which modifications need to be added?
The post above fully describes how to access the console.
Hi there, Thanks for developing this nice API wrapper! I'm very pleased with this! I want to show the VNC client out of the Proxmox environment but get a 401 No Ticket and I don't really see what i'm doing wrong around here. Would you mind to take a look at my code?
if($proxmox->login()) { $config = $proxmox->create('/nodes/vm-1/lxc/100/vncproxy'); $websock = $proxmox->get('/nodes/vm-1/lxc/100/vncwebsocket', [ 'vncticket' => $config['data']['ticket'], 'port' => $config['data']['port'], ]); return '<iframe src="https://my-server:8006/?console=lxc&novnc=1&node=vm-1&resize=scale&vmid=100&path=' . urlencode("api2/json/nodes/vm-1/lxc/100/vncwebsocket?port=" . $config['data']['port'] . "&vncticket=" . $config['data']['ticket']) . ' frameborder="0" scrolling="no" width="1024px" height="100%"></iframe>'; }
Thanks in advance! Cheers, Ramon
- Your site and the panel itself must be in 1 domain (Example: example.com & cp.example.com)
- Before showing the iframe, you must set the cookie "PVEAuthCookie"
<?php if($login = $proxmox->login()) { /* SET COOKIE FOR DOMAIN & SUBDOMAINS example.com, .example.com*/ setcookie('PVEAuthCookie', $login->getTicket(), 0, '/', 'example.com', false); $config = $proxmox->create('/nodes/vm-1/lxc/100/vncproxy'); $websock = $proxmox->get('/nodes/vm-1/lxc/100/vncwebsocket', [ 'vncticket' => $config['data']['ticket'], 'port' => $config['data']['port'], ]); return '<iframe src="https://cp.example.com:8006/?console=lxc&novnc=1&node=vm-1&resize=scale&vmid=100&path=' . urlencode("api2/json/nodes/vm-1/lxc/100/vncwebsocket?port=" . $config['data']['port'] . "&vncticket=" . $config['data']['ticket']) . ' frameborder="0" scrolling="no" width="1024px" height="100%"></iframe>'; } ?>
There is a mistake in your solution. You do not need to call vncproxy or vncticket. If you set cookie for user, it will be able to open your proxmox from frame url and get access not only for a console. So, you need to restrict all except vnc access at the point of user creation: Client X
- Create user if not. Restrict access only for vnc from pool
- Create ordered vm
- Add vm to user pool Then you can load console just by it links
I finally won and connected to noVNC from remote host! Previous solutions have any problems and don't work properly…
100% worked solution:
<?php
/*
For the first you need:
1. Create User group "VNC" –> Datacenter / Permissions / Group
2. Create new user -> Datacenter / Permissions / Users - select Group: "VNC", Realm: pve
3. Create new Role -> Datacenter / Permissions / Roles - select Name: "VNC", Privilegies: VM.Console (only)
3. Add permision to access VM -> Datacenter / Node / VM / Permissions / Add Group Permissions - select Group: "VNC", Role: "VNC"
*/
require_once 'vendor/autoload.php';
use ProxmoxVE\Proxmox;
$host = 'pve1.your.com';
$node = 'pve-01';
$vmid = '100';
$credentials = [
'hostname' => $host,
'username' => 'username',
'password' => 'password',
'realm' => 'pve' // pve or pam
];
$proxmox = new Proxmox($credentials);
if($login = $proxmox->login()) {
// Get and save ticket
$ticket = $login->getTicket();
$config = $proxmox->create('/nodes/'.$node.'/qemu/'.$vmid.'/vncproxy', [
'websocket' => 1 // Start websocket
]);
$websock = $proxmox->get('/nodes/'.$node.'/qemu/'.$vmid.'/vncwebsocket', [
'vncticket' => $ticket,
'port' => $config['data']['port'],
]);
// Set Cookies (domain must be in same space that pve. Example: pve – pve1.your.com, host – auth.your.com, Set cookies to your.com)
setcookie('PVEAuthCookie', $ticket , 0, '/', 'your.com', false);
$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="800px" height="600px"></iframe>';
}
?>
401 No ticket i need help :(
@carloscmx
401 No ticket i need help :(
You can see my solution – https://github.com/dagababaev/ProxmoxVE_API_php
@carloscmx
401 No ticket i need help :(
You can see my solution – https://github.com/dagababaev/ProxmoxVE_API_php
not working :/
@carloscmx
401 No ticket i need help :(
You can see my solution – https://github.com/dagababaev/ProxmoxVE_API_php
not working :/
not working and all… :) need more information if you have 401 – check if your hostname of node and hostname where are you open VNC is same. It's may be different subdomain, but domain must be same (h1.yourhost.com and h2.yourhost.com). And check in Chrome local storage where ticket is wrote.
Eventually you can delete all code and add this for check what PVE is return:
if($login = $proxmox->login()) {
var_dump($login."\n\n");
$ticket = $login->getTicket();
var_dump($ticket);
}
If in response you can't see ticket – check if all parameters you pass are correct. I was check now – code 100% worked with PVE 6.3-2 and Chrome 88.0.4324.150
My last message correct if you use this API. If you have problem with my code need write issues there
Maybe this article will help you. You can enable "ip:port" access, install noVNC on a separate host, and pass "ip: port" & pass to novnc. Use official docs: https://pve.proxmox.com/wiki/VNC_Client_Access
Hey there! Can someone elaborate on how you'd circumvent the cookie requirement? I'm under the impression that you can call vncproxy and make it return a password to be used in place of the cookie?
https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}/qemu/{vmid}/vncproxy

The issue with using a cookie, that I can see, is that even if you create a user with only the VNC role, you're still giving whoever's on the other end of the console a cookie which they can use to view other users' VNC terminals, correct?
Hey there! Can someone elaborate on how you'd circumvent the cookie requirement? I'm under the impression that you can call vncproxy and make it return a password to be used in place of the cookie?
https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}/qemu/{vmid}/vncproxy
![]()
The issue with using a cookie, that I can see, is that even if you create a user with only the VNC role, you're still giving whoever's on the other end of the console a cookie which they can use to view other users' VNC terminals, correct?
Have you found a solution for this?