Creating a virtual machine using Fedora Server Edition disk image

Peter Boy Versi F39-F41 Last review: 2024-11-01
Installation of Fedora Server Edition in a virtual machine is a supported way for a long time by using the standard installation program in a Virtual Machine. Another option is to download a prebuild Fedora Server Edition virtual disk image and mount that in a virtual machine. The former can be quite flexibly adapted to a specific, individual requirement. The latter entails a default installation, but requires much less time and effort. It is the scope of this guidance.

There are 2 ways to create a Fedora Server in a virtual machine. System administrators can use the standard installation program as described in Installing a Fedora Server virtual machine using Cockpit. In this process, a number of properties and functionalities can be adapted to local requirements. Or they can download a Fedora Server virtual disk image containing an already preinstalled, pre-configured and ready-to-run operating system and mount it in a virtual machine.

There exist a multitude of virtual disk images that claim to provide a server based on the Fedora distribution. An example of this is the virt-builder system. However, it is not a Fedora Server, but its own, deviating concept for the configuration of a server. And accordingly, e.g., the Fedora Server administration tools and principles may not fit. System administrators can also create their own disk images using tools such as Image Factory or Image Builder.

What you get

To begin with, you gain time. Instantiating a virtual disk image takes only a few minutes, as opposed to running through the standard installation routines. The workload is significantly lower and correspondingly faster.

Fedora Server KVM image resembles all features and properties of a Fedora Server as close as possible, except for directly hardware-related measures, of course. In general, the system administrator of a virtual server (guest system) can perform configuration and administration largely independently and autonomously from the system administrator of the host system. Ideally, they should not notice any difference in everyday practice. As the system administrator of the host is limited by the available hardware resources, the administrator of the guest system is just limited only by the virtual hardware resources.

Unlike a cloud image, Fedora Server VM is designed to run like any self-sustaining server, albeit optimized for a generic hypervisor (here QEMU/KVM/libvirt) rather than bare-metal hardware.

Fedora Cloud Image and Fedora Server Image have in common that they adhere to the build process and control of the distribution.

How it works

The creation of a virtual machine image involves two steps.

  1. Provisioning the server VM image

    Basically you will download the distributed image file and keep it available for creating one or mostly several virtual servers. The appropriate location for this is /var/lib/libvirt/boot.

  2. Instantiation of a Server virtual machine

    To do this, first create a copy of the distribution image in the pool of disk images (/var/lib/libvirt/images) with the name of the VM to be instantiated. This image is then imported into Libvirt using one of the following methods.

    1. Import via CLI using minimal integrated initial configuration

    2. Import via Cockpit with comfortable minimal initial configuration

    Each of these alternatives then follows a more detailed, mission-specific follow-up customization.

Overall, the process is very straightforward and efficient.

Provisioning the Server VM image

We assume a complete installation of virtualization support according to the Adding Virtualization Support guide.

  1. If not already done, download the Fedora Server Edition virtual disk image into the Installation media storage pool and verify the image. This involves the following steps.

    […]$ sudo -i
    […]# cd /var/lib/libvirt/boot
    […]# wget https://download.fedoraproject.org/pub/fedora/linux/releases/41/Server/x86_64/images/Fedora-Server-KVM-41-1.4.x86_64.qcow2
    […]# wget https://download.fedoraproject.org/pub/fedora/linux/releases/41/Server/x86_64/images/Fedora-Server-41-1.4-x86_64-CHECKSUM
    […]# curl -O https://fedoraproject.org/fedora.gpg
    […]# pgv --keyring ./fedora.gpg Fedora-Server-41-1.4-x86_64-CHECKSUM
    […]# sh -c ' cd /var/lib/libvirt/boot/  &&  sha256sum --ignore-missing -c *-CHECKSUM '
    Fedora-Server-KVM-41-1.4.x86_64.qcow2: OK

    If you copy or move files directly from elsewhere, you should check the correct SELinux label and correct it if necessary.

    […]# ls -alZ /var/lib/libvirt/boot/*
    […]# restorecon -R -vF /var/lib/libvirt/boot/*
  2. Adjust the image file to your needs. The maximum disk size of the server VM image file is 7GB, of which about 6GB in the root file system is free. This is not intended for pro­ductive operation, but as a starting point for customization. The minimal recommended size is about 20G. To save these adjustment steps for further instantiations, create a customized base image. Copy the disk image to an intermediate file and adjust the maximum disk size.

    […]# cd /var/lib/libvirt/boot
    […]# cp Fedora-Server-KVM-41-1.4.x86_64.qcow2  Fedora-Server-KVM-41-custom.qcow2
    […]# qemu-img info   /var/lib/libvirt/boot/Fedora-Server-KVM-41-custom.qcow2
    […]# qemu-img resize /var/lib/libvirt/boot/Fedora-Server-KVM-41-custom.qcow2 40G
    […]# qemu-img info   /var/lib/libvirt/boot/Fedora-Server-KVM-41-custom.qcow2

    The example above expands the maximal capacity to 40 GiB. You can resize the virtual disk later, too. Therefore, there is no reason to plan too generously in terms of size now. Due to the qcow2 format resizing does not affect the current image file size. It is dynamically adjusted as needed up to the maximum specified.

    If you intend to create multiple VMs with similar structure, it may be useful to customize the customised file in detail. See section Import via CLI and elaborated initial configuration further down.

Instantiation of a Server virtual machine

Alternative 1: Import efficiently via CLI

Copy the customized distribution file into the disk image pool and use virt-install to instantiate the new virtual machine. In the example, we assume that the VM has 2 interfaces, one for connecting to the public network and another for connecting to the internal protected network.

[…]# cp /var/lib/libvirt/boot/Fedora-Server-KVM-41-custom.qcow2  /var/lib/libvirt/images/{VM_NAME}.qcow2
[…]# virt-install  --name <VM_NAME> \
     --memory 4096  --cpu host --vcpus 2 --graphics none \
     --os-variant fedora41 \
     --import  \
     --disk /var/lib/libvirt/images/<VM_NAME>.qcow2,format=qcow2,bus=virtio \
     --network type=direct,source=enp1s0,source_mode=bridge,model=virtio \
     --network bridge=virbr0,model=virtio

If a message "Unknown OS name 'fedora41'" appears, the list has not yet been updated in virt-install. You can then use "fedora-unknown" without any problems.

The parameters are quite descriptive and are to be adjusted accordingly. You will find a more detailed explanation in the appendix.

A lot of messages then scroll across the screen. If the network interface doesn’t provide DHCP, in includes a NetworkManager error message. You can safely ignore it for now. It finally ends with a simple, text-based input mask for the first boot configuration.

Starting install...
Running text console command: virsh --connect qemu:///system console vm1-test
Connected to domain 'vm1-test'
Escape character is ^] (Ctrl + ])
...
[  OK  ] Reached target User and Group Name Lookups.
         Starting User Login Management...
[  OK  ] Started NTP client/server.
[   21.523663] NET: Registered PF_QIPCRTR protocol family
================================================================================
================================================================================

1) [x] Language settings                 2) [x] Time settings
       (English (United States))                (Etc/UTC timezone)
3) [x] Network configuration             4) [x] Root password
       (Connected: enp2s0, enp1s0)              (Root account is disabled)
5) [ ] User creation
       (No user will be created)

Please make a selection from the above ['c' to continue, 'q' to quit, 'r' to
refresh]:

Specifically, with networks without DHCP you may get a [FAILED] Failed to start NetworkMan…[0m - Network Manager Wait Online. which you safely can ignore for now.

We continue with this form in the step after describing the Cockpit way of instantiation.

Alternative 2: Import comfortably via Cockpit

  1. Open Cockpit on your host system. The import expects the virtual hard disk at the final location. Therefore, copy the prepared customized disk image into the disk image pool, as you did in alternative 1 (CLI import). Select Terminal in the left navigation column to perform this step.

    Cockpit initial terminal
  2. Select "Virtual Machines" in the left navigation column and select "Import VM" at the right top of the central window area.

    Cockpit import screen

    Fill in the input fields as appropriate and leave "Connection" on "System" as preselected.

  3. If the VM to be created should only have one network interface connected to the internal libvirt bridge (virbr0), select Import and run. In all other cases, select Import and edit to set up the correct network connection before the first boot.

  4. Adjust the network connection setup. The screen changes and the VM overview page. Scroll down to Network interfaces. You see one Interface with Source default, i.e. virbr0. In order to easily manage the default route, this interface - the first one created - should connect to the public external network. Select Edit to modify the Source.

    Network re-configuration

    Modify Interface type to Direct attachment and Source to the physical host external interface. Leave Model and MAC address unchanged! Save brings you back to the Overview screen.

  5. In the row "Network interfaces" select Add network interface on the right side.

    Add network interface

    In the window that opens, the internal virtual network is already selected and correctly configured. Select Add to add the interface.

  6. Scroll up and select Run In the console window you will see the creation and startup of the virtual machine. Expand the console window.

    Final User Configuration

    Finally, the screen displays the same configuration menu as with a CLI setup. Continue with the minimal initial configuration.

Minimal initial configuration

You have to use the terminal for this step, whether you performed the instantiation via CLI or via Cockpit.

  1. Complete the first boot configuration

    ================================================================================
    ================================================================================
    
    1) [x] Language settings                 2) [x] Time settings
           (English (United States))                (Etc/UTC timezone)
    3) [x] Network configuration             4) [x] Root password
           (Connected: enp2s0, enp1s0)              (Root account is disabled)
    5) [ ] User creation
           (No user will be created)
    
    Please make a selection from the above ['c' to continue, 'q' to quit, 'r' to
    refresh]:

    The clear majority of the input options are already preset with values that correspond exactly to a default installation using the Anaconda Fedora Server Edition installation program. The ROOT account is locked, as is common security practice. The only mandatory remaining task is the creation of a user account granted with administrator privileges.

    The selection of a menu item to be edited is made via the digit in front of it. Somewhat unusual in these days and age. The process is unfortunately a bit cumbersome. A "5" navigates to the item "User creation" and a "1" then to the creation of a new user.

    ================================================================================
    ================================================================================
    
    User creation
    
    1) [x] Create user
    2) Full name
    3) User name
    4) [x] Use password
    5) Password
    6) [x] Administrator
    7) Groups
       wheel
    
    Please make a selection from the above ['c' to continue, 'h' to help, 'q' to
    quit, 'r' to refresh]:

    The "[x]" in front of Create user indicates that the user creation process is activ. Accordingly, password authentication is enabled for the new user as well as administrator privileges. Fill in the required information and in any case ensure to activate the adminstrator privileges! It automatically adds "wheel" to Groups.

    ================================================================================
    ================================================================================
    
    User creation
    
    1) [x] Create user
    2) Full name
       Peter
    3) User name
       peter
    4) [x] Use password
    5) Password
       Password set.
    6) [x] Administrator
    7) Groups
       wheel
    
    Please make a selection from the above ['c' to continue, 'h' to help, 'q' to
    quit, 'r' to refresh]:

    With all user options set, the 'c' returns back to the overview screen.

    All non-British users may grab the opportunity to adjust the time zone using option 2 now.

    Another "c" continues with the execution of the entire configuration process. The operation takes some time and then ends in a login prompt.

    ...
    ...
    [  OK  ] Finished Initial Setup configuration program.
    [  OK  ] Reached target Preparation for Logins.
    [  OK  ] Started Getty on tty1.
    [  OK  ] Started Serial Getty on ttyS0.
    [  OK  ] Reached target Login Prompts.
    [  OK  ] Reached target Multi-User System.
             Starting Record Runlevel Change in UTMP...
    [  OK  ] Finished Record Runlevel Change in UTMP.
    
    Fedora Linux 41 (Server Edition)
    Kernel 6.11.4-301.fc41.x86_64 on an x86_64 (ttyS0)
    
    Web console: https://localhost:9090/ or https://192.168.158.155:9090/
    
    linux login:

    In the first lines you may get 2 SELinux messages alike "systemd-gpt-auto-generator[xxxx]: Failed to dissect: Permission denied". You can savely ignore those messages.

    The virtual server is up and running now, and ready for log in. The initial configuration process is a bit idiosyncratic for these times. But eventually simple and straightforward.

  2. Optionally: Adjust locale and non-US keyboard layout

    Users of a non-US keyboard layout probably want to customize the keyboard layout first of all. This facilitates any subsequent operation. First, check the current locale configuration

    […]# sudo -i
    […]# localectl
    System Locale: LANG=en_US.UTF-8
        VC Keymap: us
       X11 Layout: us

    List available keyboard mappings filtered by your short county code part

    […]# localectl list-keymaps  | grep de-
    de-T3
    de-deadacute
    de-deadgraveacute
    de-deadtilde
    de-mac
    de-mac_nodeadkeys
    de-neo
    de-nodeadkeys
    ...

    Determine applicable key mapping and apply it

    […]# localectl set-keymap de-nodeadkeys

    The setting is immediately active.

  3. Set hostname

    A correct hostname is specifically important for DHCP of the internal network to work properly. A correct time is important for various tasks, specifically synchronization.

    1. Check hostname. You need a correct static hostname.

      […]# hostnamectl
    2. Set hostname if required:

      […]# hostnamectl  set-hostname  <YourFQDN>
  4. Check time zone and time synchronisation if you missed that previously

    1. Check time settings

      […]# timedatectl
    2. Correct time zone if necessary:

      […]# timedatectl set-timezone  <ZONE>
    3. If necessary, activate time synchronisation:

      […]# timedatectl set-ntp true
    4. Correct time if necessary:

      […]# timedatectl set-time  <TIME>
  5. Consolidate the network configuration

    1. At first check your interfaces

      If you followed the example installation above you should find

      […]# ip a
      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
          ....
      2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state ...
          link/ether 52:54:00:3e:0e:f0 brd ff:ff:ff:ff:ff:ff
          ...
      3: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 8000 qdisc fq_codel state ...
          link/ether 52:54:00:cc:e7:ba brd ff:ff:ff:ff:ff:ff
          inet 192.168.122.42/24 brd 192.168.122.255 scope global dynamic noprefixroute enp2s0
          ...

      If the external interface doesn’t provide DHCP you won’t find an assigned IP address for enp1s0. That’s what we would need to fix next.

    2. Next let’s check and fix NetworkManager naming

      […]# nmcli con
      NAME    UUID                                  TYPE      DEVICE
      'Wired connection 2'  8d971f49-033f-398a-9714-3a4e848178fb  ethernet  enp2s0
      'Wired connection 1'  8d971f49-033f-398a-9714-3a4e848178fb  ethernet  ---

      Most likely your interfaces are a named somewhat awkward way. Let’s fix that to make administration of network easier and more comfortable. Don’t forget to adjust the naming to your specific installation!

      […]# nmcli con mod 'Wired connection 1' connection.id enp1s0
      […]# nmcli con mod 'Wired connection 2' connection.id enp2s0
    3. In case DHCP is missing on an interface, configure a static network connection

      We take the external interface as an example here.

      […]# nmcli con mod enp1s0 ipv4.method manual \
           ipv4.address "xxx.xxx.xxx.xxx/yy" \
           ipv4.gateway "xxx.xxx.xxx.zzz" \
           ipv4.dns "xxx.xxx.xxx.vvv" \
           ipv6.method manual \
           ipv6.addresses xxxx:xxxx:xxxx:xxxx::yyyy/64 \
           ipv6.gateway xxxx:xxxx:xxxx:xxxx::zz \
           ipv6.dns "xxxx.xxxx.xxxx.xxxx::vvv"  \
           connection.zone "FedoraServer"
      […]# nmcli con up enp1s0
      […]# systemctl  restart  NetworkManager
    4. The interface enp2s0 for the internal libvirt network may show an IPv6 IP, which we don’t use. Therefore, you should disable IPv6 on the internal interface

      […]# nmcli con mod enp2s0 ipv6.method disabled \
           connection.zone "trusted"
      […]# nmcli con up enp2s0
      […]# systemctl  restart  NetworkManager
    5. Check the default routes if you have 2 interfaces, one with an external public connection, one with the internal network, which uses NAT by default. So you have 2 parallel connection paths to access the public network and will find something like

      […]# ip r
      default via 192.168.158.1 dev enp1s0 proto dhcp src 192.168.158.160 metric 100
      default via 192.168.122.1 dev enp2s0 proto dhcp src 192.168.122.107 metric 101
      192.168.122.0/24 dev enp2s0 proto kernel scope link src 192.168.122.107 metric 101
      192.168.158.0/24 dev enp1s0 proto kernel scope link src 192.168.158.160 metric 100

      Delete the NAT route to avoid issues because of ambigous routes by some application software.

      […]# nmcli con mod enp2s0 ipv4.never-default yes
      […]# nmcli con down enp2s0
      […]# nmcli con up enp2s0
      […]# systemctl reload NetworkManager
      […]# ip r
      default via 192.168.158.1 dev enp1s0 proto dhcp src 192.168.158.160 metric 100
      192.168.122.0/24 dev enp2s0 proto kernel scope link src 192.168.122.107 metric 101
      192.168.158.0/24 dev enp1s0 proto kernel scope link src 192.168.158.160 metric 100
  6. Adjust firewall setting of the internal interface

    The installer assigns all interfaces to the FedoraServer zone, which limits access to ssh (and Cockpit). For the internal, protected network a broader accessibility may be appropriate, depending on the use case. If appropriate, modify the configuration (check alternative zone and select a suitable one).

    […]# firewall-cmd   --get-active-zones
    […]# firewall-cmd   --permanent  --zone=trusted  --change-interface=<internalIF>
    […]# firewall-cmd   --reload
    […]# firewall-cmd   --get-active-zones
  7. Optionally adjust default editor

    By default nano is the default system editor in Fedora. Many experienced system administrators prefer vim. If you are among the latter, adjust the default editor.

    […]# dnf install vim-default-editor --allowerasing
  8. Finally perform an update and reboot

    […]# dnf update
    […]# reboot

If you opted for Cockpit to instantiate the VM you may use Cockpits graphical interface for the last 4 steps.

Anyway, you should now test to connect via ssh to the system, if it provides an external interface.

Set up storage

Fedora Server KVM follows the same storage organization principles as the base installation. The Fedora Server Installation Guide explains the principles and the available choices. You have to make the same choice here.

The distributed disk image features a disk size of about 7 gb. This is not intended as a default value to use but as a starting value for adaptation to the specific installation requirement. You have probably already adjusted the total desired size at the begin of installation. If not, shutdown the virtual machine and adjust the size now. As already noted, you need not to be too sparing in the choice. You can easiy enlarge the maximum size later. And thanks to the qcow2 format, it allocates just the space that is actually needed and doesn’t waste resources. On the other hand, there is also no reason to be overly generous.

At this point, we have to specify the allocation and adjustment of the intended maximum disc size. Unfortunately, Cockpit doesn’t provide graphical support for editing an existing partition table. So we are bound to CLI for the first step.

Login to the virtual machine and use the cfdisk utility to display the space allocation as distributed and adjusted pre installation.

[…]# cfdisk /dev/vda
                                 Disk: /dev/vda
               Size: 37 GiB, 39728447488 bytes, 77594624 sectors
          Label: gpt, identifier: BAD551E3-F483-4FB3-BF4C-EF516A914C13

    Device              Start         End     Sectors    Size Type
>>  /dev/vda1            2048        4095        2048      1M BIOS boot
    /dev/vda2            4096     2052095     2048000   1000M Linux filesystem
    /dev/vda3         2052096    14678015    12625920	   6G Linux LVM
    Free space       14678016    77594590    62916575     30G


 ┌────────────────────────────────────────────────────────────────────────────┐
 │Partition UUID: 0534CD20-25E4-481A-AD28-E643E5328FDE                        │
 │Partition type: BIOS boot (21686148-6449-6E6F-744E-656564454649)            │
 └────────────────────────────────────────────────────────────────────────────┘
     [ Delete ]  [ Resize ]  [  Quit  ]  [  Type  ]  [  Help  ]  [  Write ]
     [  Dump  ]
       Device is currently in use, repartitioning is probably a bad idea.
                      Quit program without writing changes

As you see, on the disk there is unused space, not associated to any partition. Quit cfdisk for now.

Partition vda3 contains a Volume Group (VG).

[…]# vgdisplay
  --- Volume group ---
  VG Name               sysvg
  System ID
  Format                lvm2
  ...
  VG Size               <6.02 GiB
  PE Size               4.00 MiB
  Total PE              1541
  Alloc PE / Size       1541 / <6.02 GiB
  Free  PE / Size       0 / 0
  VG UUID               ybQrEj-xSeB-SWxw-4BMM-VXAG-3re7-2rt3xr

As you see, the complete space is occupied by a Logical Volume (LV).

Check the logical volume

[…]# lvdisplay
  --- Logical volume ---
  LV Path                /dev/sysvg/root
  LV Name                root
  VG Name                sysvg
...
  LV Size                <6.02 GiB
  Current LE             1541
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:0

As you see, the Logical Volume is of the same size as the Volume Group, about 6 GiB.

Available alternatives

  1. Enlarge the LVM partition to file all of the free space and enlarge the root file system alike. In this way, there is no separation of system and user data. This is convenient, but in no way recommendable.

  2. Enlarge the LVM partition to file all of the free space and enlarge the root file system to a reasonable value between 10 and 15 gb, depending on the intended total size of the disc. The remaining space in the Volume Group remains free for now. Later, the administrator creates logical volumes for user data or applications as needed. This is the recommended way.

  3. Enlarge the existing VG and the root file system to a reasonable size. Create a new VG in the remaining region, which later accommodates LVs for user data. This pushes the separation even further.

  4. Enlarge the distributed virtual disk to a reasonable size to accommodate the root file system only and create one or more separate virtual disk(s) to accommodate user data.

Alternative 2: Enlarge the VG to fill the disk, and root LV to a reasonable size

  1. Enlarge the LVM partition to fill the disk

    […]# cfdisk /dev/vda
                                     Disk: /dev/vda
                   Size: 37 GiB, 39728447488 bytes, 77594624 sectors
              Label: gpt, identifier: BAD551E3-F483-4FB3-BF4C-EF516A914C13
    
        Device              Start         End     Sectors    Size Type
        /dev/vda1            2048        4095        2048      1M BIOS boot
        /dev/vda2            4096     2052095     2048000   1000M Linux filesystem
    >>  /dev/vda3         2052096    14678015    12625920      6G Linux LVM
        Free space       14678016    77594590    62916575     30G
    
    
     ┌────────────────────────────────────────────────────────────────────────────┐
     │ Partition UUID: AFADA0EB-4F01-46DE-A0F1-27A8FE850500                       │
     │ Partition type: Linux LVM (E6D6D379-F507-44C2-A23C-238F2A3DF928)           │
     │Filesystem UUID: 4X9IKV-1Qmj-KTYT-aRlj-G1sJ-vr3Y-SdTIhJ                     │
     │     Filesystem: LVM2_member                                                │
     └────────────────────────────────────────────────────────────────────────────┘
         [ Delete ]  [ Resize ]  [  Quit  ]  [  Type  ]  [  Help  ]  [  Write ]
         [  Dump  ]
    
                        Reduce or enlarge the current partition

    Select resize, confirm the suggested maximum size, and then write the change to disk.

  2. Enlarge the VG to fill up the partition

    […]# pvresize    /dev/vda3
      Physical volume "/dev/vda3" changed
      1 physical volume(s) resized or updated / 0 physical volume(s) not resized
    […]# vgdisplay  sysvg
      --- Volume group ---
      VG Name               sysvg
      System ID
      Format                lvm2
       ...
      VG Size               <36.00 GiB
      PE Size               4.00 MiB
      Total PE              9215
      Alloc PE / Size       1535 / <6.00 GiB
      Free  PE / Size       7680 / 30.00 GiB
      ...
    […]#
  3. Enlarge the LV. A recommended size is 8 - 15G max, depending on the total disk size. As an example, the new size is 12 G which leaves the rest free for further user data LVs.

    […]# lvextend -L 12G  /dev/mapper/sysvg-root
      Size of logical volume sysvg/root changed from <6.00 GiB (1535 extents) to 12.00 GiB (3072 extents).
    [ 1337.365631] dm-0: detected capacity change from 12574720 to 25165824
      Logical volume sysvg/root successfully resized.
  4. Enlarge the XFS root filesystem to fill the LV

    […]# xfs_growfs /dev/mapper/sysvg-root
    meta-data=/dev/mapper/sysvg-root isize=512    agcount=4, agsize=392960 blks
             =                       sectsz=512   attr=2, projid32bit=1
    ...
    data blocks changed from 1571840 to 3145728
    
    […]# df -h
    Filesystem              Size  Used Avail Use% Mounted on
    ...
    /dev/mapper/sysvg-root   12G  1.8G   11G  15% /
    ...

For the last 2 steps you can also switch to Cockpit. But the 2 lines may not be worth it unless you use the Cockpit terminal anyway.

Alternative 3: Create a separate Volume Group for user data

  1. Perform the steps described in alternative 2, but specify the size of the LVM partition by e.g. 20G and the root LV to 12G. In this way, there is still some room for disposition in case of surprises.

  2. Use cfdisk to create a new partition, /dev/vda4 in this example, of type 'Linux LVM' using the complete remaining diskspace.

  3. Create a Physical Volume (PV) in the new partition

    […]# pvcreate /dev/vda4
      Physical volume "/dev/vda4" successfully created.
  4. Create a Volume Group (VG) in the new Physical Volume

    […]# vgcreate usrvg /dev/vda4
      Volume group "usrvg" successfully created
    
    […]# vgs
      VG    #PV #LV #SN Attr   VSize   VFree
      sysvg   1   1   0 wz--n- <20.00g  <8.00g
      usrvg   1   0   0 wz--n- <16.00g <16.00g

Later, use usrvg to create LVs for user data as needed.

Alternative 4: Create a separate virtual disk for user data

The prerequisite is that the configuration of the system disk has been completed. Perform the steps described in alternative 2, but enlarge the distributed system virtual diskimage and correspondingly the VG to e.g. 20G and the root LV to 12G. In this way, there is still some room for disposition in case of surprises. With a separate data disk, alternative 1 would be an option, too.

You can use either CLI or Cockpit for this step.

Using CLI

  1. On the host system, create a new virtual disk in /var/lib/libvirt/images

    […]# qemu-img create -f qcow2 /var/lib/libvirt/images/${VM_NAME}-usr.qcow2  20G
    Formatting '/var/lib/libvirt/images/vm01-test-usr.qcow2', fmt=qcow2 cluster_size=65536 extended_l2=off compression_type=zlib size=21474836480 lazy_refcounts=off refcount_bits=16
    
    […]# qemu-img info  /var/lib/libvirt/images/${VM_NAME}-usr.qcow2
    file format: qcow2
    virtual size: 20 GiB (21474836480 bytes)
    disk size: 196 KiB
    cluster_size: 65536
    Format specific information:
        compat: 1.1
        compression type: zlib
        lazy refcounts: false
        refcount bits: 16
        corrupt: false
        extended l2: false
  2. Continue on the host and add the disk to the virtual machine. Use the first available diskname. The system disk is vda, so the next available disk name is vdb. If you are unsure check in the virtual machine, e.g. using 'lsblk'.

    […]# virsh attach-disk ${VM_NAME} /var/lib/libvirt/images/${VM_NAME}-usr.qcow2  vdb --cache default --persistent --targetbus=virtio --subdriver qcow2
    Disk attached successfully

    The command needs the absolute path to the image file as noted. Otherwise it will fail. The disk is available immediately.

    If you want to modify something, detach the file first.

    […]# virsh detach-disk ${VM_NAME}   vdb  --persistent
    Disk detached successfully
  3. On the virtual machine, use cfdisk to partition the disk according to your requirements. The example creates one partition spanning the entire disk capacity.

    First, cfdisk displays a list for selecting the partitioning type. Select GPT.

    […]# cfdisk  /dev/vdb
                                     Disk: /dev/vdb
                       Size: 192.5 KiB, 197120 bytes, 385 sectors
              Label: gpt, identifier: 2842C26B-A2F1-4946-9D89-AB8832E5FCEC
    
        Device                 Start        End      Sectors       Size Type
    >>  Free space                34        351          318       159K
    
    
    
               [   New  ]  [  Quit  ]  [  Help  ]  [  Write ]  [  Dump  ]
    
    
                          Create new partition from free space
  4. Create a Physical Volume (PV) in the new partition (adjust the device accordingly!)

    […]# pvcreate /dev/vdb1
      Physical volume "/dev/vdb1" successfully created.
  5. Create a Volume Group (VG) in the new Physical Volume (adjust the device accordingly!)

    […]# vgcreate  usrvg  /dev/vdb1

Later, use usrvg to create LVs for user data as needed.

Using Cockpit

  1. Open Cockpit on your host system, select Virtual Machines in the navigation column, and then select the machine to which you want to add a disk. Scroll down until you see the disk section. Finally, select Add disk on the right side of the subtitle bar.

    Cockpit add disk form

    Most of the input fields are suitably preconfigured. Enter a (file) name for the disk image. Use a consistent naming scheme to facilitate long-term system maintenance. Specify the intended maximum size of the disk and decide on "Always attach". It is best to leave the other properties untouched.

    Select Add to complete the task.

  2. Open Cockpit on the virtual machine you added the device to and select Storage. Cockpit assigns automatically the next disk identifier, /dev/vdb in case of Server VM.

    VM storage view
  3. Select the new disk and create a partition table and file system as needed.

    VM disk partitioning

Follow-up customization

It is advisable to review all the tasks in the general post-installation guide for virtual machines as well.