Run Debian 12 (Bookworm) on KVM using Qcow2 Cloud Image

After close to two years of hard work, Debian 12 was released on June 10th, 2023 with plenty of new features and improvements from its predecessor, Debian 11(Bullseye).

If you’re running a private Cloud or Virtualization Platform powered by KVM, such as OpenStack and oVirt. The most ideal way to spin a Debian 12 virtual machine is from a Cloud image. In this blog we show you how you can download official Debian 12 cloud image and create a Virtual Machine instance from it on KVM hypervisor. In our future posts we will cover running Debian 12 Virtual Machine on OpenStack.

1. Download Debian 12 Cloud image

All Debian 12 Cloud images are available on official OS images downloads page. In this guide we will download the nocloud qcow2 image:

mkdir ~/cloud_images && cd ~/cloud_images
sudo wget https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.qcow2

You can check more details on the file using the file command:

$ file debian-12-nocloud-amd64.qcow2
debian-12-nocloud-amd64.qcow2: QEMU QCOW Image (v3), 3221225472 bytes (v3), 3221225472 bytes

For the raw image:

wget https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.raw

2. Move Cloud Image to /var/lib/libvirt folder

We are going to create a template from the image we just created. Let’s create a folder in the /var/lib/libvirt/images folder:

sudo mkdir /var/lib/libvirt/images/templates

Move Debian 12 cloud image you just downloaded in Step 1:

sudo mv debian-12-nocloud-amd64.qcow2  /var/lib/libvirt/images/templates/

Confirm the current contents listed on the directory:

$ ls /var/lib/libvirt/images/templates/
debian-12-generic-amd64.qcow2  debian-12-nocloud-amd64.qcow2

3. Create Debian 12 (Bookworm) on KVM using Cloud Image

Next we create a Debian 12 (Bullseye) virtual machine from our cloud image.

Let’s save some important variables:

  • Admin Username
  • Admin user password
  • Virtual Machine name

Save the variables as shown, but make sure you set the values to your liking:

export VM_NAME="Debian-12-Bookworm"

Once the variables are exported we create OS root disk image from the cloud image downloaded earlier:

sudo qemu-img convert \
  -f qcow2 \
  -O qcow2 \
  /var/lib/libvirt/images/templates/debian-12-nocloud-amd64.qcow2 \
  /var/lib/libvirt/images/$VM_NAME-root-disk.qcow2

Check file creation if successful:

$ file  /var/lib/libvirt/images/$VM_NAME-root-disk.qcow2
/var/lib/libvirt/images/Debian-12-Bookworm-root-disk.qcow2: QEMU QCOW Image (v3), 3221225472 bytes (v3), 3221225472 bytes

$ sudo du -sh /var/lib/libvirt/images/$VM_NAME-root-disk.qcow2
1.3G    /var/lib/libvirt/images/Debian-12-Bookworm-root-disk.qcow2

Resize the disk to desired size

Note that the root disk we created has a small disk capacity as defined in default cloud image.

$ qemu-img  info /var/lib/libvirt/images/$VM_NAME-root-disk.qcow2
image: /var/lib/libvirt/images/Debian-12-Bookworm-root-disk.qcow2
file format: qcow2
virtual size: 3 GiB (3221225472 bytes)
disk size: 1.27 GiB
cluster_size: 65536
Format specific information:
    compat: 1.1
    compression type: zlib
    lazy refcounts: false
    refcount bits: 16
    corrupt: false
    extended l2: false
Child node '/file':
    filename: /var/lib/libvirt/images/Debian-12-Bookworm-root-disk.qcow2
    protocol type: file
    file length: 1.27 GiB (1367605248 bytes)
    disk size: 1.27 GiB

Let’s resize to our desired root disk size.

# I'm setting mine to 30GB - set yours accordingly
export VM_ROOT_DISK_SIZE=30G

# Resize Debian 12 VM disk
sudo qemu-img resize \
  /var/lib/libvirt/images/$VM_NAME-root-disk.qcow2 \
  $VM_ROOT_DISK_SIZE

Expected command output:

Image resized.

Confirm the current size with the qemu-img info command:

$ qemu-img  info /var/lib/libvirt/images/$VM_NAME-root-disk.qcow2
imimage: /var/lib/libvirt/images/Debian-12-Bookworm-root-disk.qcow2
file format: qcow2
virtual size: 30 GiB (32212254720 bytes)
disk size: 1.27 GiB
cluster_size: 65536
Format specific information:
    compat: 1.1
    compression type: zlib
    lazy refcounts: false
    refcount bits: 16
    corrupt: false
    extended l2: false
Child node '/file':
    filename: /var/lib/libvirt/images/Debian-12-Bookworm-root-disk.qcow2
    protocol type: file
    file length: 1.27 GiB (1367605760 bytes)
    disk size: 1.27 GiB

Create a Debian 12 Virtual Machine using the virt-install command and the created disk.

virt-install \
    --memory 2048 \
    --vcpus 2 \
    --name $VM_NAME \
    --disk /var/lib/libvirt/images/$VM_NAME-root-disk.qcow2,device=disk,bus=virtio,format=qcow2 \
    --os-variant debian12 \
    --network network=default,model=virtio \
    --virt-type kvm \
    --graphics none \
    --import

Use the following command to list all available OS variants.

sudo osinfo-query os

As of this article writing the latest variant of Debian is debian12.

4. Add standard user admin account

Login as root user – no password is required to get shell access.

localhost login: root
Linux localhost 6.1.0-32-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.129-1 (2025-03-06) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@localhost:~#

After login as root user, proceed to create the first admin user using adduser command:

root@debian:~# adduser sysadmin
root@localhost:~# adduser sysadmin
Adding user `sysadmin' ...
Adding new group `sysadmin' (1000) ...
Adding new user `sysadmin' (1000) with group `sysadmin (1000)' ...
Creating home directory `/home/sysadmin' ...
Copying files from `/etc/skel' ...
New password: 
Retype new password: 
passwd: password updated successfully
Changing the user information for sysadmin
Enter the new value, or press ENTER for the default
        Full Name []: Sys Admin
        Room Number []: 
        Work Phone []: 
        Home Phone []: 
        Other []: 
Is the information correct? [Y/n] Y
Adding new user `sysadmin' to supplemental / extra groups `users' ...
Adding user `sysadmin' to group `users' ...

Check user id and group. It is evident the user is not in sudo privileged group.

root@localhost:~# id sysadmin
uid=1000(sysadmin) gid=1000(sysadmin) groups=1000(sysadmin),100(users)

Add the user created to sudo group for privilege escalation.

root@localhost:~# usermod -aG sudo sysadmin
root@localhost:~# id sysadmin
uid=1000(sysadmin) gid=1000(sysadmin) groups=1000(sysadmin),27(sudo),100(users)

Check if the user can login and use sudo command.

root@localhost:~# su - sysadmin
sysadmin@localhost:~$ sudo su -
[sudo] password for sysadmin: 
root@localhost:~#

5. Set hostname and update system

Set hostname for your Virtual Machine:

root@localhost:~# hostnamectl set-hostname debian11-bookworm-01.localdomain

Confirm hostname is set correctly.

root@localhost:~# hostnamectl
 Static hostname: debian12-bookworm-01.localdomain
       Icon name: computer-vm
         Chassis: vm 🖴
      Machine ID: c5759520f40f481fb464bad22b1673b9
         Boot ID: 487917da658d4db58bd9f3d12f287e43
  Virtualization: kvm
Operating System: Debian GNU/Linux 12 (bookworm)  
          Kernel: Linux 6.1.0-32-amd64
    Architecture: x86-64
 Hardware Vendor: QEMU
  Hardware Model: Standard PC _Q35 + ICH9, 2009_
Firmware Version: 1.16.3-debian-1.16.3-2

Logout the login again.

root@localhost:~# exit
logout

Debian GNU/Linux 12 debian12-bookworm-01.localdomain ttyS0

debian12-bookworm-01 login: sysadmin
Password: 
Linux debian12-bookworm-01.localdomain 6.1.0-32-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.129-1 (2025-03-06) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
sysadmin@debian12-bookworm-01:~$

If the network attached to Virtual Machine uses DHCP to assign IP addresses, the instance should get a NATed IP address:

sysadmin@debian12-bookworm-01:~$ ip ad
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host noprefixroute 
       valid_lft forever preferred_lft forever
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:e6:d5:04 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.209/24 metric 100 brd 192.168.122.255 scope global dynamic enp1s0
       valid_lft 2795sec preferred_lft 2795sec
    inet6 fe80::5054:ff:fee6:d504/64 scope link 
       valid_lft forever preferred_lft forever

Add the IP address and matching host name to /etc/hosts file.

$ sudo vim /etc/hosts
192.168.122.209 debian12-bookworm-01.localdomain

Update and upgrade system:

sudo apt updates
sudo apt upgrade -y

Reboot after the upgrade:

# reboot

Login with admin user created on the consoles that shows up after reboot.

Debian GNU/Linux 12 debian12-bookworm-01.localdomain ttyS0

debian12-bookworm-01 login: sysadmin
Password: 
Linux debian12-bookworm-01.localdomain 6.1.0-32-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.129-1 (2025-03-06) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Thu Mar 27 20:39:53 UTC 2025 on ttyS0
sysadmin@debian12-bookworm-01:~$ 

Install OpenSSH Server:

sudo apt install -y openssh-server

Wait for keys to be generated before checking service status.

Creating config file /etc/ssh/sshd_config with new version
Creating SSH2 RSA key; this may take some time ...
3072 SHA256:ahGSy76B9WsY4beRBZ/naaoI1RkT9dxZXuBHRWsY8so [email protected] (RSA)
Creating SSH2 ECDSA key; this may take some time ...
256 SHA256:zuW/gkjwXMTtiWZtrfrrq6fH6ka1Gq7ui7wyOg5O4Uk [email protected] (ECDSA)
Creating SSH2 ED25519 key; this may take some time ...
256 SHA256:z1CDz+kNhUCXHfiOZp+JBrrr9LoMnOOkGbWEpOYbYjM [email protected] (ED25519)
Created symlink /etc/systemd/system/sshd.service/lib/systemd/system/ssh.service.
Created symlink /etc/systemd/system/multi-user.target.wants/ssh.service → /lib/systemd/system/ssh.service.
rescue-ssh.target is a disabled or a static unit, not starting it.
ssh.socket is a disabled or a static unit, not starting it.
Processing triggers for man-db (2.11.2-2) ...
Processing triggers for libc-bin (2.36-9+deb12u10) ...

Restart ssh service to ensure it can come up without any issues in future.

sudo systemctl restart ssh

The service should now be running

$ sudo systemctl status ssh
● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/lib/systemd/system/ssh.service; enabled; preset: enabled)
     Active: active (running) since Thu 2025-03-27 20:55:53 UTC; 4min 21s ago
       Docs: man:sshd(8)
             man:sshd_config(5)
   Main PID: 889 (sshd)
      Tasks: 1 (limit: 2316)
     Memory: 2.9M
        CPU: 17ms
     CGroup: /system.slice/ssh.service
         889 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"

Mar 27 20:55:53 debian12-bookworm-01.localdomain systemd[1]: Starting ssh.servi>
Mar 27 20:55:53 debian12-bookworm-01.localdomain sshd[889]: Server listening on>
Mar 27 20:55:53 debian12-bookworm-01.localdomain sshd[889]: Server listening on>
Mar 27 20:55:53 debian12-bookworm-01.localdomain systemd[1]: Started ssh.servic>

6. Add your ssh pubkey to sysadmin user account

To login via ssh from your workstation or KVM node, generate user ssh keys:

cloudspinx@kvm-host:~$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/cloudspinx/.ssh/id_rsa):
Created directory '/home/cloudspinx/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/cloudspinx/.ssh/id_rsa
Your public key has been saved in /home/cloudspinx/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:Kzwt86BJaJkW4xO8MSWnFI0c83o2rrQ01w+iC/v9xd0 cloudspinx@kvm-host
The key's randomart image is:
+---[RSA 3072]----+
| .++             |
|  o+.            |
|  o +            |
| o *             |
|  X +   S        |
| . # + o o .     |
|. & = X = . E    |
| B X + @         |
|..*.+.. o        |
+----[SHA256]-----+

Create a file on VM:

sysadmin@debian12-bookworm-01:~$ touch ~/.ssh/authorized_keys

Copy your host ssh public key and add to file ~/.ssh/authorized_keys on created VM:

$ vim  ~/.ssh/authorized_keys

Or use ssh-copy:

cloudspinx@ubuntu-24:~$ ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/cloudspinx/.ssh/id_rsa.pub"
The authenticity of host '192.168.122.209 (192.168.122.209)' can't be established.
ED25519 key fingerprint is SHA256:z1CDz+kNhUCXHfiOZp+JBrrr9LoMnOOkGbWEpOYbYjM.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[email protected]'s password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh '[email protected]'"
and check to make sure that only the key(s) you wanted were added.

Test remote connection:

cloudspinx@ubuntu-24:~$ ssh sysadmin@192.168.122.135
Linux debian12-bookworm-01.localdomain 6.1.0-32-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.129-1 (2025-03-06) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Thu Mar 27 20:52:35 2025
sysadmin@debian12-bookworm-01:~$ hostnamectl
 Static hostname: debian12-bookworm-01.localdomain
       Icon name: computer-vm
         Chassis: vm 🖴
      Machine ID: c5759520f40f481fb464bad22b1673b9
         Boot ID: f98dd60c19d148689873bcd8ef97dd33
  Virtualization: kvm
Operating System: Debian GNU/Linux 12 (bookworm)  
          Kernel: Linux 6.1.0-32-amd64
    Architecture: x86-64
 Hardware Vendor: QEMU
  Hardware Model: Standard PC _Q35 + ICH9, 2009_
Firmware Version: 1.16.3-debian-1.16.3-2 

We have been able to create a Debian 12(Bookworm) Virtual Machine on KVM using Cloud image base image. Additionally, we created an admin user account, updated the system, and uploaded a public ssh key for passwordless authentication. In our future guide we will look at creation of Virtual Machine from Cloud image with Cloud-init user-data instance configurations.

More guides on Virtualization:

Your IT Journey Starts Here!

Ready to level up your IT skills? Our new eLearning platform is coming soon to help you master the latest technologies.

Be the first to know when we launch! Join our waitlist now.

Join our Linux and open source community. Subscribe to our newsletter for tips, tricks, and collaboration opportunities!

Recent Post

Leave a Comment

Your email address will not be published. Required fields are marked *

Related Post

In this tutorial, we are going to look at how to install Jenkins on Ubuntu 24.04|22.04. First, let us learn […]

Can I install and Use PowerShell on my macOS?. PowerShell is a cross-platform task automation and configuration management framework, consisting of […]

Fish, short for Friendly Interactive Shell, is an easy to install and use shell for Unix systems. The shell comes […]

Let's Connect

Unleash the full potential of your business with CloudSpinx. Our expert solutions specialists are standing by to answer your questions and tailor a plan that perfectly aligns with your unique needs.
You will get a response from our solutions specialist within 12 hours
We understand emergencies can be stressful. For immediate assistance, chat with us now

Contact CloudSpinx today!

Download CloudSpinx Profile

Discover the full spectrum of our expertise and services by downloading our detailed Company Profile. Simply enter your first name, last name, and email address.