I discovered today that you can expose qemu virtual machines serial console via websockets. Which is nice for remote exposure of VMs!

What are websockets

Websockets are an Upgrade of http (1.1) connections to a full duplex binary communication protocol called WebSockets. This, as the name says can be used from a browser. It can be used over TLS as well.

How to expose serial through websockets

qemu-system-x86_64 -m 2048 \
  -drive if=virtio,file=disk.qcow2,format=qcow2 \
  -enable-kvm \
  -netdev user,id=mynet0,hostfwd=tcp:127.0.0.1:7922-:22 \
  -device e1000,netdev=mynet0 \
  -nographic \
  -chardev socket,id=char1,websocket=on,host=localhost,port=4555,server,nowait \
  -serial chardev:char1

The part that we're interested in is the last part :

  -chardev socket,id=char1,websocket=on,host=localhost,port=4555,server,nowait \
  -serial chardev:char1

This basically creates a char device that is exposed as a websocket server on localhost on port 4555 and it connects it as to the serial interface.

How to connect to it

Well, I tried using websocat with it, but websocat adds a \n on each data received for some reason. So I found another tool that basically does it "the easy way". Enter https://github.com/anisse/websocktty/

It basically sets terminal in raw mode and prints everything received from the websocket to stdout. And it reads messages from stdin and sends them through the websocket.

It uses golang.org/x/crypto/ssh/terminal to interact with the terminal and put it in raw mode as well as github.com/gorilla/websocket to create websockets. So, very easy!

A few disappointments

Unfortunately, the VM need to be configured to use the serial console. Which is not really the default for most OS nowadays.

This, however can be automated through usage of pre-configured OSes ISOs or using ISO that support cloud-init to configure it. This is usually present in cloud images available online.

Conclusion

We discovered a nice Qemu feature to expose serial console through websocket and how to use it remotely.

I might use this to do easy VMs provisionning through an API and make access to them easy.

Future work

What about other hypervisors ?

What about using other programming language for the client ?