Bash terminal for LXD container in webpage

Hello guys
I’m a new LXD user and i want to have a bash terminal for website using xterm.js
I can create container starr and sop it using php-curl mais i have no idea for Terminal or console

/1.0/instances/exec gets you some websockets which you can then connect to pretty easily from xterm.js.

I’m not familiar with PHP but @turtle0x1 likely has done exactly that before for Mosaic. You’d most likely have your PHP code doing the LXD interaction to start the exec session, then feed the resulting web socket address to xterm.js.

Thank @stgraber
my html and php code looks like this
@turtle0x1 what’s the wrong here

<?php $containerName = 'vmcas2'; $curl = curl_init(); curl_setopt_array($curl, [ CURLOPT_URL => "https://10.149.3.207:8443/1.0/containers/{$containerName}/exec", CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode([ 'command' => ['ls'], 'environment' => [ 'HOME' => '/root', 'TERM' => 'xterm', ], 'wait-for-websocket' => true, 'interactive' => true, 'width' => 80, 'height' => 24, 'timeout' => 60, ]), CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', ], ]); // Ajouter les certificats auto-signés curl_setopt($curl, CURLOPT_SSLCERT, '/var/www/html/plateforme/cert/client.crt'); curl_setopt($curl, CURLOPT_SSLKEY, '/var/www/html/plateforme/cert/client.key'); // Désactiver la vérification des certificats auto-signés curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); $response = curl_exec($curl); $result = json_decode($response, true); $operationId = $result['operation']; //echo $result['operation']; //echo "baba"; //echo $result['metadata']['fds']['0']; // WebSocket endpoint for the operation //$websocketUrl = "wss://10.149.3.207:8443/1.0/operations/{$operationId}/websocket?secret=".$result['metadata']['fds']['0']; // Print the WebSocket URL for testing purposes $websocketUrl = "wss://10.149.3.207:8443{$operationId}/websocket?secret=".$result['metadata']['id']; echo "WebSocket URL: {$websocketUrl}\n"; echo "\n"; //echo $result['metadata']['fds']['0']; echo "\n"; ?> Interactive Terminal body { background-color: #002b36; color: #839496; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; } #terminal-container { width: 80%; height: 500px; margin: auto; margin-top: 50px; }
// Create an xterm.js terminal instance var term = new window.Terminal();
    // Attach the terminal instance to a container element
    term.open(document.getElementById('terminal-container'));

    // Connect to the WebSocket endpoint
    var socket = new WebSocket('<?echo $websocketUrl; ?>');
    socket.binaryType = 'arraybuffer';

    // Handle incoming messages from the WebSocket
    socket.addEventListener('message', function (event) {
        term.write(new TextDecoder().decode(event.data));
    });

    // Handle user input and send it to the WebSocket
    term.onData(function (data) {
        socket.send(data);
    });
</script>

my new code

Terminal LXD


@turtle0x1 can you solve the issue please???

You were going wrong in a few places, it would be easier to explain on something like Github, most notably you weren’t using the right secret paths and text needs to be encoded before being sent to the websocket.

In the future when sharing code you should copy and paste it, not screenshot it as people are less likely to help if they to type it all out.

Here is a script that works, just change the variables at the top so it has your details in.

<?php
    /**
     * CHANGE ONLY THESE
     */
    $lxdDomainAndPort = "localhost:8443";
    $containerName = 'c1';
    $lxdCertLocation = 'PATH_TO_CERT.cert';
    $lxdKeyLocation = 'PATH_TO_KEY.key';
    $command = "bash"; // Will have to use "ash" or "zsh" or some instance types

    $curl = curl_init();
    curl_setopt_array($curl, [
        CURLOPT_URL => "https://$lxdDomainAndPort/1.0/containers/{$containerName}/exec",
        CURLOPT_RETURNTRANSFER=> true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode([
            'command' => [$command],
            'environment' => [
                'HOME' => '/root',
                'TERM' => 'xterm',
                'USER' => 'root',
            ],
            'wait-for-websocket' => true,
            'interactive' => true,
            'width' => 80,
            'height' => 24,
            'timeout' => 60
        ]),
        CURLOPT_HTTPHEADER => [ 'Content-Type: application/json'],
        CURLOPT_SSLCERT => $lxdCertLocation,
        CURLOPT_SSLKEY => $lxdKeyLocation,
        CURLOPT_SSL_VERIFYHOST => 0,
        CURLOPT_SSL_VERIFYPEER => 0
    ]);
    $response = curl_exec($curl);
    $result = json_decode($response, true);
    $operationId = $result['operation'];
    $websocketUrl = "wss://{$lxdDomainAndPort}{$operationId}/websocket?secret=".$result['metadata']['metadata']["fds"][0];
    $controlUrl = "wss://{$lxdDomainAndPort}{$operationId}/websocket?secret=".$result['metadata']['metadata']["fds"]["control"];

?>
<style>
body {
    background-color: #002b36;
    color: #839496;
    font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
}

#terminal-container {
    width: 80%;
    height: 500px;
    margin: auto;
    margin-top: 50px;
}
</style>
<div id="terminal-container"></div>
<script src=" https://cdn.jsdelivr.net/npm/xterm@5.1.0/lib/xterm.min.js "></script>
<link href=" https://cdn.jsdelivr.net/npm/xterm@5.1.0/css/xterm.min.css " rel="stylesheet">
<script>
    // Create an xterm.js terminal instance
    var term = new Terminal();
    // Attach the terminal instance to a container element
    term.open(document.getElementById('terminal-container'));
    // You must do this these days
    var controlSocket = new WebSocket('<?php echo $controlUrl; ?>');
    // Connect to the WebSocket endpoint
    var socket = new WebSocket('<?php echo $websocketUrl; ?>');
    // Set binary type
    socket.binaryType = "arraybuffer"
    // Handle incoming messages from the WebSocket
    socket.addEventListener('message', function (event) {
        term.write(new TextDecoder().decode(event.data));
    });
    // Handle user input and send it to the WebSocket
    term.onData(function (data) {
        socket.send(new TextEncoder(data).encode(data))
    });
</script>

Edit 1: Remove the leftover xterm-attach addon (it didn’t work as expected)