Serial console for Proxmox VMs
proxmox vm linux guideIn this blog post, I will describe how to use the serial console as the standard VM display in Proxmox VE. This will give you the ability to access a text-based shell from the web interface and the PVE host shell. This has some advantages compared to a regular text console displayed via VGA:
- The font rendering is better
- The output is scrollable
- Text can be copied and pasted
Configuring the Serial Hardware #
A serial port has to be added to the VM hardware. It is possible to do this via the web interface, just navigate to the "hardware" tab, then click "add" -> "serial port". Restart the VM to see the changes
Configure the VM to use the serial port #
To actually see some output on the newly created serial port, the system itself has to be configured:
Configure serial output for Linux (kernel and getty) #
The kernel has to be configured to use the serial console. On ubuntu 22.04, the kernel command line is passed via GRUB, so changes have to be made to the /etc/defaults/grub
file:
GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,115200"
After making the change, run update-grub
as root and restart the system.
By itself, this will only configure the kernel itself to dump log messages onto the serial console. To attach a linux terminal session onto the serial port, a getty
process has to be started. On Ubuntu 22.04 (and probably later versions as well), this requires no additional configuration: systemd-getty-generator
will automatically enable a corresponding systemd service for every console configured in the kernel command line. In our case, the service name is serial-getty@ttyS0.service
- we can check its status later to verify that the getty generation is working. On other distributions, you might have to enable the service manually or start the getty
yourself.
Optional: Configure serial console for GRUB #
The GRUB bootloader itself can be configured to use the serial console by specifying the following in /etc/default/grub
:
# change grub bootloader itself to use serial
GRUB_TERMINAL_INPUT="console serial"
GRUB_TERMINAL_OUTPUT="gfxterm serial"
GRUB_SERIAL_COMMAND="serial --unit=0 --speed=115200"
Afterwards, execute update-grub
as root to commit the changes.
- Note: I've had mixed success with the GRUB configuration. On some VMs, I would get the error message
secure boot forbids loading module serial.mod
. It appears that the module is not correctly signed or simply not present, but GRUB over serial was not that important to me, so I did not investigate further.*
Accessing the terminal #
The serial terminal can be accessed using qm terminal $VMID
. To exit the session, simply press CTRL+O
. In addition, the serial console can be accessed with the web UI, by selecting xterm.js
in the 'Console' menu of the VM. Some further notes:
- The serial terminal output is not buffered internally by proxmox (as of version 7.4) - therefore, you might not see anything besides the message
starting serial terminal on interface serial0
. Pressing ENTER should bring up the login prompt. - There can only be a single connection to the serial port at a time. If you open multiple xterm.js windows, the second one apparently tries to create a new connection, and the terminal will appear unresponsive.
- The terminal will also work as usual for a VM with a desktop environment, which can be great for debugging
- It is not necessary to switch the display from default to the serial console - this would remove the regular graphics output, and instead render the serial console in the default noVNC view. Regardless of the display option, the serial console is always accessible using the xterm.js option.. I would recommend leaving the main display at the default settings, so that the actual video output of the VM is rendered in the default noVNC session; this way, you can still access the OVMF menu or the default console (if there should be some issues with the serial connection)
Appendix: Playbook #
I made a small Ansible role for myself to configure new VMs automatically on the guest side. Currently, the playbook does not add the serial port, since this has to be configured on the host. Be aware that the playbook overwrites the Linux command line. I am only using this for 'blank' VMs, you might want to change it if you use a custom command line:
---
- name: Configure Linux command line
lineinfile:
path: /etc/default/grub
regexp: '^GRUB_CMDLINE_LINUX_DEFAULT='
line: 'GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,115200"'
register: setup_cmdline
- name: Configure Grub serial console
block:
- lineinfile:
path: /etc/default/grub
regexp: '^GRUB_TERMINAL='
state: absent
register: setup_grub_terminal
- lineinfile:
path: /etc/default/grub
regexp: '^GRUB_TERMINAL_INPUT='
line: 'GRUB_TERMINAL_INPUT="console serial"'
register: setup_grub_terminal_input
- lineinfile:
path: /etc/default/grub
regexp: '^GRUB_TERMINAL_OUTPUT='
line: 'GRUB_TERMINAL_OUTPUT="gfxterm serial"'
register: setup_grub_terminal_output
- lineinfile:
path: /etc/default/grub
regexp: '^GRUB_SERIAL_COMMAND='
line: 'GRUB_SERIAL_COMMAND="serial --unit=0 --speed=115200"'
register: setup_grub_serial_command
- name: Update GRUB
command:
cmd: update-grub
when: setup_cmdline.changed or setup_grub_terminal.changed or setup_grub_terminal_input.changed or setup_grub_terminal_output.changed or setup_grub_serial_command.changed
References #
https://wiki.archlinux.org/title/working_with_the_serial_console https://www.kernel.org/doc/html/v4.14/admin-guide/serial-console.html https://blog.wataash.com/ubuntu_console/
Comments
If you have any questions or comments, please feel free to reach out to me by sending an email to blog(at)krisnet.de.