How to Install a KVM Guest OS from the Command-Line

How to Install a KVM Guest OS from the Command-Line Feature Image

On most Linux servers, the only interface available to you will be a command-line interface. Without the GUI, it is not possible to use tools such as virt-manager or virt-viewer. So, the way to install a KVM guest OS from the command-line on such systems is through a serial console using the virt-install tool.

Interaction with a serial console is similar to using a text-based terminal without a graphical interface or mouse. It provides an alternative way of accessing your servers by replacing the default graphical consoles. Generally, the first serial port on the guest VM (/dev/ttyS0) is used for the serial console.

The serial console also comes in handy when you cannot ssh into your virtual machine due to some connectivity issues, or when you want to provide a LUKS password during startup.

In this blog, I’m going to show you how to install a KVM guest OS from the command-line using the virt-install tool. While virt-install also supports graphical installations using SPICE or VNC, I will only focus on text mode installs over the serial console. I will use Debian 11 as an example, but it may also be another OS.

If you want to install guest OS using Virtual Machine Manager, take a look at my other blog on How to Install Guest OS in Virt-Manager: A Quick Intro.

If you haven’t already installed KVM, please check out my other blog on how to install KVM on Linux and run guest OS faster.

So, let’s begin.

1. The virt-install command with arguments

The following command will create a Debian 11 guest named debian-server with 2048 MiB (2 GiB) of RAM, 2 virtual CPUs, 20 GiB qcow2 virtual disk, and 1 network interface card (NIC). The guest is created in text-only mode. It connects the guest console to the serial console.

The virt-install tool must be run as root, or the user must be in the libvirt group. As I am in the libvirt group, I will run it as a regular user.

$ virt-install \
    --name debian-server \
    --memory 2048 \
    --vcpus 2 \
    --cpu host \
    --disk size=20 \
    --location /Repo/Iso/debian-11.0.0-amd64-DVD-1.iso \
    --os-variant debian11 \
    --network network=default \
    --graphics none \
    --extra-args 'console=ttyS0,115200n8 --- console=ttyS0,115200n8'

A brief description of arguments:

--name debian-server: Name of the guest VM. It must be unique among all known guests of the hypervisor on the connection, including those not currently active.

--memory 2048: The amount of host RAM (in MiB) you would like to assign to the guest VM. For the host memory information, enter the command virsh nodememstats.

--vcpus 2: The number of virtual CPUs you would like to assign to the guest VM. To get the CPU information of the host, enter the command virsh nodeinfo.

--cpu host: Sets the host CPU configuration to the guest VM so that it can take advantage of several of its features. To define a different CPU, use the command virsh cpu-models x86_64 and select one of the models closest to your host processor. For example --cpu core2duo.

--disk size=20: Sets the disk size to 20 GiB, disk format to qcow2, and bus to virtio. In this disk image format, preallocation mode will be set to metadata and the lazy_refcounts option is set to on.

--location /Repo/Iso/debian-11.0.0-amd64-DVD-1.iso: ISO installer image location. Here I’ve specified a local ISO installer image, but one can also specify a URL containing an installation tree like --location 'http://ftp.nl.debian.org/debian/dists/Debian11.0/main/installer-amd64/'. To verify if the ISO file is an OS installer image, run the command osinfo-detect <iso image>.

--os-variant debian11: Specify the operating system for which the guest VM should be optimized. Use the command osinfo-query os to get the list of the accepted OS variant names.

--network network=default: Connects the guest VM to the host network. You can specify the network by name (network=NAME) or by bridge device (bridge=BRIDGE). To find network connection names, use the command virsh net-list, and to find bridge devices, use the command ip link show type bridge.

--graphics none: No graphics console will be assigned to the guest VM. The guest VM must therefore be configured with a text console on the first serial port of the guest VM. It is done with the option --extra-args (next line).

--extra-args 'console=ttyS0,115200n8 --- console=ttyS0,115200n8': The first console=ttyS0,115200n8 option in --extra-args line tells virt-install to use the serial console /dev/ttyS0 to install the guest VM, use 115200 bits per second speed, with no parity bit, and 8 data bits. The same second option after a triple dash (---) tells the installer to copy it into the bootloader of the installed guest VM permanently. Boot messages are then sent to the serial console on subsequent boots. The changes are made to the GRUB_CMDLINE_LINUX line in the /etc/default/grub file on the guest VM.

2. Install KVM guest OS from the command-line

Once you execute the above command, the text-based installation process for Debian 11 begins in the serial console.

Starting install...
Retrieving file vmlinuz...                                  | 6.5 MB  00:00     
Retrieving file initrd.gz...                                |  17 MB  00:00     
Allocating 'virtinst-hx97nv6u-vmlinuz'                      | 6.5 MB  00:00     
Transferring virtinst-hx97nv6u-vmlinuz                      | 6.5 MB  00:00     
Allocating 'virtinst-9kott6dy-initrd.gz'                    |  17 MB  00:00     
Transferring virtinst-9kott6dy-initrd.gz                    |  17 MB  00:00     
Allocating 'debian-server.qcow2'                            |  20 GB  00:02     
Connected to domain 'debian-server'
Escape character is ^] (Ctrl + ])
[    0.000000] Linux version 5.10.0-8-amd64 (debian-kernel@lists.debian.org)
 (gcc-10 (Debian 11.0.0-1) 11.0.0 20210110, GNU ld (GNU Binutils for Debian)
 2.35.2) #1 SMP Debian 5.10.46-3 (2021-07-28)
[    0.000000] Command line: console=ttyS0,115200n8 --- console=ttyS0,115200n8
...

Follow the standard installation procedure for the guest operating system. Just be sure to uncheck any GUI desktop environment. You won’t need it.

How to Install a KVM Guest OS from the Command-Line Software Selection

When the installation is finished, press the Continue button, and the system will reboot to a text-mode login page.

How to Install a KVM Guest OS from the Command-Line Installation Complete

Type in your username and password and you will be logged into a command-line interface within a virtual serial console.

  Booting `Debian GNU/Linux'

Loading Linux 5.10.0-8-amd64 ...
Loading initial ramdisk ...
/dev/mapper/debian--vg-root: clean, 32202/447040 files, 299586/1784832 blocks

Debian GNU/Linux 11 debian ttyS0

debian login: madhu
Password: 
Linux debian 5.10.0-8-amd64 #1 SMP Debian 5.10.46-5 (2021-09-23) x86_64

The programs included with the Debian GNU/Linux system are free software;
permitted by applicable law.
madhu@debian:~$

You can exit the console by pressing the Ctrl + ] keys.

And if you want to re-connect the guest console anytime, type the following command in the host.

$ virsh console debian-server 
Connected to domain 'debian-server'
Escape character is ^] (Ctrl + ])

madhu@debian:~$

3. Set the terminal type and console window size

When you connect a remote device via ssh, the terminal type and the host screen size are sent to the remote device automatically. But when you connect through a serial connection, this does not happen, and as a consequence, the screen size is reduced, visual abnormalities may appear, and scrolling may not function properly.

By default, the serial console will have a terminal type vt220 (or, vt100) and a size of 24x80.

madhu@debian:~$ echo $TERM
vt220

You may want to set the terminal type to xterm-256color.

madhu@debian:~$ export TERM=xterm-256color

Get the current size of the console window.

madhu@debian:~$ stty size
24 80

Set the new console window size manually.

madhu@debian:~$ stty rows 40 cols 150

madhu@debian:~$ stty size
40 150

There is another tool called resize that comes with the xterm package in Debian/Ubuntu. In Rocky/Fedora it is called xterm-resize. It uses the settings from the host terminal window to set the size of the serial console.

madhu@debian:~$ resize
COLUMNS=192;
LINES=48;
export COLUMNS LINES;

madhu@debian:~$ stty size
48 192

If, after setting the new screen size, the console is still cropping the text, then exit the serial console by pressing Ctrl + ] keys and type the command reset on the host’s terminal. Reconnect to serial console with the command virsh console debian-server.

4. Check and set the baud speed of the serial port

In a real-world situation, the baud speed setting of the RS-232 connection is affected by the length of the cable. The higher the baud rate, the shorter the cable should be. Otherwise, the communication will be unreliable. So most of the Linux distributions set the baud speed to 9600, which is considered a reliable and safe baud speed. The Linux kernel supports a serial console speed of 1200, 2400, 4800, 9600, 19200, 38400, 57600, and 115200 bits per second.

Since we are using a virtual serial console, a much higher baud rate of 115200 is recommended.

I had set the baud speed to 115200 bits per second. Check if the baud speed of the serial port is the same as you defined.

madhu@debian:~$ stty speed
115200

If you want to change the speed of the serial port for instance to 9600 bps, then.

madhu@debian:~$ stty -F /dev/ttyS0 speed 9600

madhu@debian:~$ stty speed
9600

To know which TTY you are attached to, run the tty command.

madhu@debian:~$ tty
/dev/ttyS0

5. Review the serial port options in grub2 conf

Verify that the necessary serial port options have been permanently defined in the GRUB2 configuration file for subsequent restarts.

madhu@debian:~$ grep -E 'tty|serial' /etc/default/grub
GRUB_CMDLINE_LINUX="console=ttyS0,115200n8"
GRUB_TERMINAL=serial
GRUB_SERIAL_COMMAND="serial --unit=0 --speed=115200 --word=8 --parity=no --stop=1"

Description:

In the first line of the output, the option console=ttyS0,115200n8 tells the kernel to print boot messages on serial port 0 (/dev/ttyS0), with 115200 baud rate, with no parity and a word length of 8 bits. This option is added because I have mentioned it in the virt-install command (after the triple dash in --extra-args argument).

In the second line of the output, the option serial specifies where the grub menu should be displayed, in this case – the serial console.

The last line of the output sets the serial port environment and hardware specs. --unit=0 tells to use the first serial port (taken from ttyS0). --speed=115200 – the speed of the serial link in bits per second (taken from 115200n8). --word=8 – the number of data bits per character (taken from 115200n8). --parity=no – use no parity bit (taken from 115200n8), and finally --stop=1 – the number of stop bit-times (default). For detailed info visit the webpage Select a serial speed and parameters.

6. Install QEMU guest agent in the virtual machine

The QEMU guest agent is a daemon that runs on a virtual machine. According to Red Hat,

The QEMU guest agent runs inside the guest and allows the host machine to issue commands to the guest operating system using libvirt, helping with functions such as freezing and thawing filesystems. The guest operating system then responds to those commands asynchronously.

Note that QEMU guest agent can be used to enable and disable virtual CPUs (vCPUs) while the guest is running, thus adjusting the number of vCPUs without using the hot plug and hot unplug features.

Enhancing Virtualization with the QEMU Guest Agent and SPICE Agent

Verify if the communication channel between the QEMU guest agent and the host has been configured in debian-server guest VM.

madhu@debian:~$ sudo systemctl status qemu-guest-agent.service
● qemu-guest-agent.service - QEMU Guest Agent
     Loaded: loaded (/lib/systemd/system/qemu-guest-agent.service; static)
     Active: active (running) since Wed 2021-10-06 10:53:31 IST; 2h 36min ago
   Main PID: 397 (qemu-ga)
      Tasks: 2 (limit: 2337)
     Memory: 2.0M
        CPU: 12ms
     CGroup: /system.slice/qemu-guest-agent.service
             └─397 /usr/sbin/qemu-ga

Oct 06 10:53:31 debian systemd[1]: Started QEMU Guest Agent.

You should get similar output as above. If not, first shut down the debian-server guest VM, then, on the host machine, add a new QEMU guest communication channel to debian-server guest VM.

$ virt-xml debian-server --add-device \
    --channel unix,target.type=virtio,target.name='org.qemu.guest_agent.0'

Now, start the debian-server guest VM and install the qemu-guest-agent package within the guest VM.

root@debian:~# apt install qemu-guest-agent

Finally, start the qemu-guest-agent service.

root@debian:~# systemctl start qemu-guest-agent.service

7. Conclusion

In this blog, you learned how to install a KVM guest OS from the command-line using the virt-install tool. Once the installation is complete, the next step is to learn how to administer KVM virtual machine using the virsh command-line tool.

Going forward, I will be writing articles on how to use the virsh command-line tool and also on how to take snapshots of virtual machines.

guest
0 Comments
Inline Feedbacks
View all comments