lxdware / lxd-dashboard

This LXD dashboard is a web-based user interface (GUI) for managing containers and virtual machines through LXD
https://lxdware.com
GNU Affero General Public License v3.0
317 stars 37 forks source link

Interactive terminal access #5

Closed ghost closed 3 years ago

ghost commented 3 years ago

Hi,

I have tried most of the web-based interfaces to LXD and of all of those I think yours provides the best balance of features vs resource requirements for me. I am running LXD on an RPi 4 8GB and lxd-dashboard is running as a container which I can access thanks to a reverse proxy on the host. So thanks, it is an excellent project.

To setup and get new containers running and doing something useful my one request would be for interactive terminal access. I realise moving from a non-interactive to interactive terminal probably is not trivial. LxdMosaic does include this so perhaps some inspiration could be taken from there?

I am happy to assist where I can but I do not know PHP and my JS is rather limited. If this is beyond the scope of the project or would add signifcant resource requirements please feel free to close.

Thanks

Daniel

matthewalanpenning commented 3 years ago

@danieldean Thanks for the suggestion and I am glad you are enjoying the dashboard. I had worked to try to get websockets working originally but after countless hours gave up and tabled that idea for a later time. After your suggestion I went back to my notes and tried it again. I made some progress where I left off and now think after a few more tweaks I will have a solution that will work. I am planning to add it to the 2.0.0 release that will coming out early this summer.

ghost commented 3 years ago

@matthewalanpenning thanks that is great to hear.

I started trying to hack something together myself thinking I might be able to offer you some assistance. It sounds like you have it covered by my hacked together example can be found here if it is of any help:

https://github.com/danieldean/lxd-term

As I see it the main issue with what I have done is that it assumes the lxd remote will be accesible externally which most likely will not be the case but for my local testing it works fine. If it could be made to work with some form of proxying I think it provides a much lighter weight way of doing things.

matthewalanpenning commented 3 years ago

Version 2.0.0 is now released and I have replaced the exec option with a terminal console connection. I used the base code from xterm.js and configuring the web socket connection with PHP and client-side JavaScript it seems to work very well. You can now even use applications like top, vi, nano, etc in the terminal emulator. You can find this in the console tab on the instance page. Thanks for the suggestion.

ghost commented 3 years ago

Thanks that works well. It took me a little while to work out what I needed to do to install/upgrade, i.e. that users were now stored in the DB and I needed php7.4-curl installed, but I got there in the end. The other changes are excellent too.

I adjusted the following in 'instances-single.php' so I do not have to login to my containers:

case "establishInstanceWebSocketConsoleConnection":
  //$url = $base_url . "/1.0/instances/".$instance."/console?project=" . $project;
  $url = $base_url . "/1.0/containers/".$instance."/exec?project=" . $project;
  $data = '{ "command": ["/bin/bash"], "wait-for-websocket": true, "environment":{"HOME": "/root", "TERM": "xterm", "USER": "root"}, "interactive": true}';
  //$data = '{ "type": "console", "width": 80, "height": 25 }';

And commented out the following line in 'instances-single.html' to prevent the immediate disconnect:

 //Send Ctrl+d and return to show login screen on console connections
 setTimeout(() => { socket.send(convertString2ArrayBuffer('\04 \r')); }, 1000);

I am unsure if the intention was to have to login to the containers using a username and password for security reasons? None of mine have users with passwords which is why I did this.

I guess it is worth pointing out, and I am sure you realise, that this approach only works if the remote is accessible from your current machine and not just from the lxd-dashboard server.

I also made some other changes to 'instances-single.html' to handle disconnects (such as ctrl+d or the exit command) too:

//Listen for websocket messages
socket.onmessage = function (e) {
  // If length is zero this usually signals a disconnect.
  if (e.data.length == 0) {
    socket.close();
  } else if (e.data instanceof ArrayBuffer) {
    if (convertArrayBuffer2String(e.data) != null) {
      term.write(convertArrayBuffer2String(e.data));
    }
  }
};

//Listen for websocket closing
socket.onclose = function (e) {
  term.dispose();
  term = new Terminal({
    cursorBlink: "block"
  });
  term.open(document.getElementById("terminal-console"));
  // Reset stop/start console buttons.
  $("#stopConsoleButton").hide();
  $("#startConsoleButton").show();
  console.log(e);
};
matthewalanpenning commented 3 years ago

Thanks for that additional information. I debated whether to go with the console or exec approach. Some environments require login access to machine and other do not, so I went to with the console approach. After your feedback I may add an option in the settings to toggle either approach, giving the admin the choice as to which they prefer.

Yes, unfortunately using the client-side approach does mean that the user has to have network access to the LXD server from their desktop/laptop. If I get some time I may look at creating a tutorial or two on using a VPN connection to access remote LXD servers behind a firewall.

If you have any additional ideas for the project, drop a message. I would like to continue developing this into a robust solution and suggestions help.