Menu

Using QEMU-KVM to run a Debian Virtual Machine as guest

Legal Notices

Copyright (c) 2026 Dr. Thomas Redelberger, redetho(a‍t)gmx.de. All rights reserved. You may quote and copy this publication provided you link back to this original web-site https://web222.webclient5.de/doc/computing/vm/qemu. Suggestions for amendments and improvements are welcome.

This information is provided as-is. I do not take any responsibility and do not grant any warranty nor do I imply any fitness for any purpose or kind, nor shall I be liable for any issues when using it.

The original version of this document was in English language. I might do a German version. People are invited to do translations to other languages. But they shall properly cite me and link back to this original web-site.

Introduction

I had created and used a Debian virtual machine to run under Windows 10/Hyper-V for browsing the Internet. This page describes how to set up a similar Debian virtual machine to run under QEMU, with Debian Linux as host operating system.

Choices on the Debian Linux Host and QEMU Choices

The only Debian package I use on the host is qemu-system-x86 (includes amd64 and qemu-utils). This "bare" QEMU shall be

I do not use virt-manager, which comes as a separate Debian package. virt-manager

Requirements

The first VM I developed to run under QEMU is a "Web Browser Virtual Machine" (WBVM). The purpose of WBVM is to safely browse the web. I have the following requirements for WBVM:

  1. Minimal functionality, just a standard web browser
  2. The browser window shall integrate as seamlessly as possible in the host's X11 window system, including clipboard and mouse support
  3. Capability to up and download files from/to the VM guest to/from the host
  4. The guest shall always work in "snapshot" mode, i.e. forget any changes of the file system when the guest terminates
  5. Ease of use. Using the WBVM shall be as easy as selecting a menu item in the users desktop environment

Summary of Solutions to Requirements

1. Minimal Web Browser Functionality

This requirement is fulfilled by a minimal Debian based VM, which just runs Firefox and a light weight window manager. See below . The set-up is similar to the Debian VM I had running under Hyper-V.

2. Browser Window Integration

After trying other options, I chose running xrdp on the VM guest and freerdp3 on the host.

3. File Exchange

After trying other options, I chose NFS (network file system) to exchange files between VM guest and host.

4. Snapshot Operations

QEMU has simple snapshot operations built-in. Advanced virtual disk functionality ‑ which QEMU also offers ‑ is not needed.

5. Ease of Use

I have developed a set of scripts to start/stop, use and manage the WBVM.

Software

I order to help others build a similar set up, I publish here the software I developed in a ZIP archive file ./wbvm.zip.

Manifest

The ZIP archive ./wbvm.zip contains the following files:

wbvm/README.txt Text version of this web page
wbvm/bin/wbvm-install1 Script for first VM installation step
wbvm/bin/wbvm-install2 Script to boot the VM the first time
wbvm/bin/wbvm-start Script to start the VM in the back-ground
wbvm/bin/wbvm-poweroff-wait Script to stop the VM
wbvm/bin/wbvm-conn-console Script to connect to the VM using a terminal
wbvm/bin/wbvm-conn-rdp Script to graphically connect to the VM
wbvm/in/fstab Example fstab file for the VM
wbvm/in/grub Example grub file for the VM
wbvm/in/.profile Example .profile for the VM

Note that all scripts shall be run by a normal unprivileged user. No step requires root privileges.

Installation process

The installation process should be done by manually starting the scripts wbvm-install1 and later wbvm-install2 from an xterm running on the host. QEMU will then open an X11 GUI window on the host. The window's tab menu allows to switch between two "screens":

  1. A screen, which shows the guest VM's virtual display (monitor). When this screen shows, you keyboard input goes to the guest VM
  2. A screen which is called "monitor" confusingly. This "monitor" allows you to query and manage QEMU by typing commands to QEMU via the keyboard

First step - boot a live ISO file

Like installing Linux on a physical machine, one option to install Linux in a VM is to boot a "live system" from an ISO image. The script wbvm-install1 does the following:

At the end of this installation step, the live system asks you to reboot, and "remove the CD-ROM". It is easier to just power down the VM.

Second step - boot from the virtual hard disk an finish installation

The script wbvm-install2 does the following:

At this point, you can install the wanted software in the VM guest.

Regular operations

Starting QEMU and and Guest VM

The file wbvm-start starts QEMU which in turn starts (boots) the guest VM. There are various options:

Note that wbvm-start does not bring up the QEMU graphical X11 window, as that window would be confusing normal users during regular operations. Rather:

Connecting to the Guest from the Host's Desktop

The file wbvm-conn-rdp connect to the VM via the Remote Desktop Protocol (RDP), such that a graphical X11 window appears on the host that gives access to the VM's X11 desktop. You might want to call wbvm-conn-rdp from a menu item on your host's desktop environment or window manager.

Shutting Down the Guest

The file wbvm-poweroff-wait powers down the guest VM OS, as if a virtual power button was pressed. The script issues the command system_powerdown to the QEMU monitor via the HMP channel that I implemented as a named pipe. All recent operating systems will do an orderly shutdown. The script monitors the state of the VM and waits for the VM to power down. This uses the fact that by default QEMU terminates when the guest VM is shut down. The script has a time-out functionality to cater for error conditions.

You might want to call wbvm-poweroff-wait once you log out from a terminal, a window manager or a desktop environment.

Normally, all changes to the VM are thrown away

As a special provision, I have QEMU operate the VM's virtual disk in "snapshot mode", i.e. all disk writes go to a provisional store (in RAM or to a /tmp directory). When the VM is powered down and QEMU terminates, all write operations are discarded and the virtual disk image file is unchanged. You could even chmod the virtual disk image file as read-only on the host operating system!

The rational is increased security from rogue web sites.

Note that QEMU "snapshot mode" for virtual disks is not to be confused with running virtual disks as "base" and "differencing" disks using the qcow2 virtual hard disk file format:

Maintenance

Updating the guest OS

To maintain the guest OS, e.g. to update the software because of security patches, I first open a terminal and stop the VM by issuing wbvm-poweroff-wait. Then I manually start the script wbvm-start with the command line switch -m (for maintenance). This option

Usually, I will then connect to the guest as usual and open an xterm in the guest and e.g. do sudo apt update; sudo apt upgrade and then sudo poweroff.

QEMU will still be running, because of the QEMU no-shutdown command line option. This allows to type commit all on the terminal on the host side, which directs QEMU to write all virtual disk changes to the virtual hard disk's image file on the host. Finally typing quit will terminate QEMU. Obviously, the disk image file needs to be write enabled for that to succeed.

Optional log-in to the Guest's Linux console

Normally, to maintain the guest, I open an xterm from the guest's X11 desktop, which I access using XRDP from the host.

Should X11 not be running on the guest or access from the host via RDP is not be possible for whatever reason, you need to have an alternate way to connect to the guest. For this I configured an additional channel to the guest's Linux console. The file wbvm-conn-console allows to log in to a non-graphical terminal session on the guest, where you can log-in. For this to work, a Linux kernel command line parameter (see the file in/grub) re-directs the Linux console to a virtual serial line. QEMU allows to connect to that virtual serial line via the telnet protocol, i.e. QEMU has a built-in telnet server.

On the host, you could use a standard telnet client or use a tool like ckermit. Using kermit would additionally allow to exchange files with the guest, provided kermit is also installed on the guest.

Additional Comments to Script wbvm/bin/wbvm-start

This section provides additional comments to script wbvm/bin/wbvm-start so that you could adapt it to your needs more easily.

The purpose of the first section of the script is to support multiple instances of the VM. The script supports one instance per user that is logged-in to the host.

The core of the script is one long command line calling QEMU. For better readability the command line is split into multiple lines and each line (except the last one) is terminated by a backslash line continuation character.

Start the QEMU executable, replacing the bash shell that called it:

exec qemu-system-x86_64 \

Naming the VM allows to identify different VMs from commands like ps. However, I do not use that feature yet:

-name wbvm \

Have QEMU create a pid-file, which allows to identify that instance later unambiguously, e.g. in script wbvm-poweroff-wait. QEMU deletes the pid-file when it terminates:

-pidfile ${MYPIDFILE} \

Normally, I want to access the QEMU monitor via a named pipe. But when the script is started with the option -m

${MYSHTDMD} ${MYMONDEV} \

We do want to use the KVM feature:

-accel kvm \

The following two lines define the VM's network interface, with the attributes:

-device virtio-net,netdev=mynic,romfile="" \
-netdev user,id=mynic,ipv6=off,hostfwd=tcp::${MYXRDBPRT}-:3389 \

The following two lines define a virtual sound card. Sound worked out of the box. Pulseaudio is used:

-device virtio-sound-pci,audiodev=mysnd \
-audiodev pa,id=mysnd \

The VM guest gets 2 GB of RAM:

-m 2G \

The guest's Linux console is made accessible via the telnet protocol:

-serial telnet::${MYTLNTPRT},server,nowait \

No need for the QEMU GUI, as I have set up three channels above

  1. QEMU monitor via pipe or stdin
  2. guest console via telnet
  3. guest X11 via RDP:
-nographic \

Who needs a virtual parallel port?

-parallel none \

The guest VM boots a tad faster, when I provide an empty virtual floppy:

-drive format=raw,file=/home/shared/wbvm/empty-floppy.img,if=floppy,readonly=on \

The virtual disk. snapshot=on forces all writes to a temporary store on the host (presumably under /tmp). You could set the file main.img read only using chmod and only temporarily enable write access when you start the script with -m to update the guest OS:

-drive format=raw,file=/home/shared/wbvm/main.img,snapshot=on \

Boot from the virtual disk:

-boot c

WBVM Guest Debian Settings and Packages

For the guest OS I used Debian 13 (Trixie), with the following choices:

I installed the following Debian packages in the guest:

Debian Package Comments, apt install Options
anacron  
pulseaudio --no-install-recommends
nfs-common suffices on guest, --no-install-recommends
xrdp  
jwm --no-install-recommends
firefox-esr  

Links


Last change: 2026-03-13
© 2002-2026 Dr. Thomas Redelberger redetho(a‍t)gmx.de

Close menu