[GH-ISSUE #221] LXC Container Terminal Websocket Fails #63

Open
opened 2026-03-03 15:29:57 +03:00 by kerem · 0 comments
Owner

Originally created by @z46-dev on GitHub (Dec 12, 2025).
Original GitHub issue: https://github.com/luthermonson/go-proxmox/issues/221

After following https://deepwiki.com/luthermonson/go-proxmox/6.1-container-lifecycle-operations#terminal-access, I wrote the RawExecute function at the bottom of this issue's description. Upon running the test that would test this function, I get the following: failed to create terminal websocket: unexpected EOF. Checking Proxmox, I can see:

failed waiting for client: timed out
TASK ERROR: command '/usr/bin/termproxy 5900 --path /vms/111 --perm VM.Console -- /usr/bin/dtach -A /var/run/dtach/vzctlconsole111 -r winch -z lxc-console -n 111 -e -1' failed: exit code 1

I should note that the test creates, starts, stops, and destroys an Ubuntu 25 container around this with no issues. The token I'm using has Administrator permissions, and is on the root user (yes, dangerous, I know, but it's what I'm doing for testing at this point in time).

The process of the test is:

  1. Create
  2. Start
  3. Defer { Stop, Destroy } (like calling defer in Go)
  4. Try to run command.

Step 4 always fails, and then the container is cleaned up and destroyed. I need terminal access to LXC containers for my project so that on containers without SSH pre-installed and running I can install/enable it to then run other commands. Or it would be splendid to just raw-execute as root over a terminal instead of using ssh, which could seriously improve my app.

It is possible I am doing this wrong, and if I am, please do tell.


func (api *ProxmoxAPI) RawExecute(ct *proxmox.Container, username, password, command string) (stdout string, stderr string, err error) {
	var term *proxmox.Term

	if term, err = ct.TermProxy(api.bg); err != nil {
		err = fmt.Errorf("failed to create terminal proxy: %w", err)
		return
	}

	var (
		send, recv chan []byte
		errs       chan error
		close      func() error
	)

	if send, recv, errs, close, err = ct.TermWebSocket(term); err != nil {
		err = fmt.Errorf("failed to create terminal websocket: %w", err)
		return
	}

	defer close()

	send <- []byte(command + "\n")

	var outputBuilder strings.Builder
	var errorBuilder strings.Builder

	done := make(chan struct{})

	go func() {
		for {
			select {
			case msg := <-recv:
				outputBuilder.Write(msg)
				fmt.Print(string(msg))
			case err := <-errs:
				if err != nil {
					errorBuilder.WriteString(err.Error())
				}
			case <-done:
				return
			}
		}
	}()

	// Wait (for testing, will add better handling later)
	time.Sleep(10 * time.Second)

	stdout = outputBuilder.String()
	stderr = errorBuilder.String()

	return
}

Note that api is initialized with

	api = &ProxmoxAPI{
		client: proxmox.NewClient(
			fmt.Sprintf("https://%s:%s/api2/json", config.Config.Proxmox.Hostname, config.Config.Proxmox.Port),
			proxmox.WithHTTPClient(&http.Client{
				Transport: &http.Transport{
					TLSClientConfig: &tls.Config{
						InsecureSkipVerify: true,
					},
				},
			}),
			proxmox.WithAPIToken(config.Config.Proxmox.TokenID, config.Config.Proxmox.Secret),
		),
		bg:    context.Background(),
		Nodes: make([]*proxmox.Node, 0),
	}
Originally created by @z46-dev on GitHub (Dec 12, 2025). Original GitHub issue: https://github.com/luthermonson/go-proxmox/issues/221 After following https://deepwiki.com/luthermonson/go-proxmox/6.1-container-lifecycle-operations#terminal-access, I wrote the `RawExecute` function at the bottom of this issue's description. Upon running the test that would test this function, I get the following: `failed to create terminal websocket: unexpected EOF`. Checking Proxmox, I can see: ``` failed waiting for client: timed out TASK ERROR: command '/usr/bin/termproxy 5900 --path /vms/111 --perm VM.Console -- /usr/bin/dtach -A /var/run/dtach/vzctlconsole111 -r winch -z lxc-console -n 111 -e -1' failed: exit code 1 ``` I should note that the test creates, starts, stops, and destroys an Ubuntu 25 container around this with no issues. The token I'm using has Administrator permissions, and is on the root user (yes, dangerous, I know, but it's what I'm doing for testing at this point in time). The process of the test is: 1. Create 2. Start 3. Defer { Stop, Destroy } (like calling `defer` in Go) 4. Try to run command. Step 4 always fails, and then the container is cleaned up and destroyed. I need terminal access to LXC containers for my project so that on containers without SSH pre-installed and running I can install/enable it to then run other commands. Or it would be splendid to just raw-execute as root over a terminal instead of using ssh, which could seriously improve my app. It is possible I am doing this wrong, and if I am, please do tell. --- ```go func (api *ProxmoxAPI) RawExecute(ct *proxmox.Container, username, password, command string) (stdout string, stderr string, err error) { var term *proxmox.Term if term, err = ct.TermProxy(api.bg); err != nil { err = fmt.Errorf("failed to create terminal proxy: %w", err) return } var ( send, recv chan []byte errs chan error close func() error ) if send, recv, errs, close, err = ct.TermWebSocket(term); err != nil { err = fmt.Errorf("failed to create terminal websocket: %w", err) return } defer close() send <- []byte(command + "\n") var outputBuilder strings.Builder var errorBuilder strings.Builder done := make(chan struct{}) go func() { for { select { case msg := <-recv: outputBuilder.Write(msg) fmt.Print(string(msg)) case err := <-errs: if err != nil { errorBuilder.WriteString(err.Error()) } case <-done: return } } }() // Wait (for testing, will add better handling later) time.Sleep(10 * time.Second) stdout = outputBuilder.String() stderr = errorBuilder.String() return } ``` Note that `api` is initialized with ```go api = &ProxmoxAPI{ client: proxmox.NewClient( fmt.Sprintf("https://%s:%s/api2/json", config.Config.Proxmox.Hostname, config.Config.Proxmox.Port), proxmox.WithHTTPClient(&http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, }, }), proxmox.WithAPIToken(config.Config.Proxmox.TokenID, config.Config.Proxmox.Secret), ), bg: context.Background(), Nodes: make([]*proxmox.Node, 0), } ```
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/go-proxmox#63
No description provided.