You open the VNC console of a Debian VM on OpenStack. Login prompt shows up. You start typing. Nothing. Cursor doesn't move. Mouse works, screen renders, but the keyboard is dead.
It's not a noVNC bug, not a browser issue, not a QEMU misconfiguration. It's the kernel.
The problem
Official Debian GenericCloud images (Debian 12, 13, and likely future releases) ship with a cloud kernel variant. This kernel strips out drivers to keep the image small and boot fast.
One of the things it strips: all USB support.
$ grep USB_SUPPORT /boot/config-$(uname -r)
# CONFIG_USB_SUPPORT is not set
Why does that matter? Because QEMU (the hypervisor behind OpenStack) exposes a virtual USB keyboard to the guest. When you type in the VNC console, QEMU receives the events and forwards them through this USB device.
No USB driver in the kernel means the device simply doesn't exist inside the guest:
$ cat /proc/bus/input/devices | grep Name
N: Name="AT Translated Set 2 keyboard" # PS/2 only, no USB
N: Name="Power Button"
Compare with a working AlmaLinux or CentOS VM:
$ cat /proc/bus/input/devices | grep Name
N: Name="AT Translated Set 2 keyboard"
N: Name="VirtualPS/2 VMware VMMouse"
N: Name="QEMU QEMU USB Tablet"
N: Name="QEMU QEMU USB Keyboard" # this receives VNC input
N: Name="Power Button"
QEMU QEMU USB Keyboard — that's the device missing on Debian.
The fix
Install the standard Debian kernel (non-cloud), which includes USB support:
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y linux-image-amd64
Set the standard kernel as the default in GRUB:
# Switch to saved default
sed -i 's/GRUB_DEFAULT=.*/GRUB_DEFAULT=saved/' /etc/default/grub
# Find the standard kernel entry
GRUB_ENTRY=$(grep -oP "gnulinux-advanced-[a-f0-9-]+" /boot/grub/grub.cfg | head -1)
STD_ENTRY=$(grep -oP "gnulinux-[0-9][^']*-advanced-[a-f0-9-]+" /boot/grub/grub.cfg | grep -v cloud | head -1)
grub-set-default "${GRUB_ENTRY}>${STD_ENTRY}"
update-grub
Optionally, remove the cloud kernel to save space:
apt-get remove -y linux-image-*-cloud-*
apt-get autoremove -y
Reboot. After restart, verify:
$ uname -r
6.12.73+deb13-amd64 # standard, not cloud
$ cat /proc/bus/input/devices | grep Name
N: Name="AT Translated Set 2 keyboard"
N: Name="QEMU QEMU USB Tablet"
N: Name="QEMU QEMU USB Keyboard" # now it exists
VNC keyboard works.
For image builders
If you build cloud images with Packer or similar tooling, add the kernel swap step to your Debian provisioning. This script auto-detects whether it's running a cloud kernel:
#!/bin/bash
export DEBIAN_FRONTEND=noninteractive
if [[ "$(uname -r)" != *"cloud"* ]]; then
echo "Not a cloud kernel, skipping"
exit 0
fi
apt-get update -qq
apt-get install -y linux-image-amd64
sed -i 's/GRUB_DEFAULT=.*/GRUB_DEFAULT=saved/' /etc/default/grub
GRUB_ENTRY=$(grep -oP "gnulinux-advanced-[a-f0-9-]+" /boot/grub/grub.cfg | head -1)
STD_ENTRY=$(grep -oP "gnulinux-[0-9][^']*-advanced-[a-f0-9-]+" /boot/grub/grub.cfg | grep -v cloud | head -1)
grub-set-default "${GRUB_ENTRY}>${STD_ENTRY}"
update-grub
apt-get remove -y linux-image-*-cloud-*
apt-get autoremove -y
apt-get clean
rm -rf /var/lib/apt/lists/*
The resulting image will boot with the standard kernel and VNC will work out of the box.
Why CentOS/AlmaLinux/Rocky/Fedora aren't affected
Cloud kernels on RHEL-based distros don't disable USB. They ship with CONFIG_USB_SUPPORT=y and all the necessary HID modules. VNC works out of the box on these distros.
Ubuntu cloud images — worth testing. They may or may not have the same issue.
TL;DR
Debian cloud kernel = no USB = no VNC keyboard. Install linux-image-amd64, set it as default, reboot. Done.