- Ensure you have
qemu-utils
,grub2
, andsquashfs-tools
installed. - Start with a pre-configured
qcow2
image namedcustom.qcow2
.
- qemu-utils: Part of the QEMU software package.
- grub2: Provides GRUB boot loader.
- squashfs-tools: For SquashFS file systems.
- libguestfs-tools-c: Provides tools for accessing and modifying guest disk images.
- grub2-efi-x64-modules: GRUB2 modules for UEFI for x64 machines.
To install them:
sudo yum install qemu-img grub2 squashfs-tools libguestfs-tools-c grub2-efi-x64-modules
- qemu-utils: QEMU image management utilities.
- grub-efi-amd64-bin: GRUB EFI for AMD64 architectures.
- grub-pc-bin: General GRUB tools and modules.
- squashfs-tools: Tools for SquashFS file systems.
- libguestfs-tools: Tools for accessing and modifying guest disk images.
To install them:
sudo apt-get update
sudo apt-get install qemu-utils grub-efi-amd64-bin grub-pc-bin squashfs-tools libguestfs-tools
if lsblk | grep -q nbd1; then
echo "Cleaning up existing /dev/nbd1 connection..."
sudo qemu-nbd --disconnect /dev/nbd1
fi
sudo modprobe nbd max_part=16
sudo qemu-nbd --connect=/dev/nbd1 custom.qcow2
sudo mount /dev/nbd1p3 /mnt/myroot
ROOTFS_DEVICE=/dev/nbd1
#### Setup
```bash
sudo modprobe nbd max_part=16
export ROOT_DIR=/mnt/myroot
export USB_NBD=/dev/nbd1
export TMPSTORE=/tmp/store
mkdir -p $TMPSTORE
cd $TMPSTORE
dir_size=$(sudo du -sm /mnt/myroot | awk '{print $1}')
img_size=$((dir_size + 200))
dd if=/dev/zero of=rootfs.img bs=1M count=$img_size
mkfs.ext4 rootfs.img
sudo mkdir -p /mnt/rootimg
sudo mount -o loop rootfs.img /mnt/rootimg
sudo cp -a /mnt/myroot* /mnt/rootimg
sudo umount /mnt/rootimg
mkdir -p LiveOS
mv rootfs.img LiveOS/
mksquashfs LiveOS custom_root.squashfs -comp xz
create_squashfs_from_rootfs() { # Check if the directory exists if [ ! -d "$TMP_SQUASHFS_DIR/lib/modules/" ]; then echo "Directory $TMP_SQUASHFS_DIR/lib/modules/ does not exist" return 1 fi
# Calculate the size of the directory and create the rootfs image
dir_size=$(sudo du -sm "$TMP_SQUASHFS_DIR" | awk '{print $1}')
img_size=$((dir_size + 200))
dd if=/dev/zero of=rootfs.img bs=1M count=$img_size
mkfs.ext4 rootfs.img
# Mount the image and copy contents
sudo mount -o loop rootfs.img /mnt
sudo cp -a $TMP_SQUASHFS_DIR/* /mnt/
sudo umount /mnt
# Move rootfs.img into LiveOS directory
mkdir -p LiveOS
mv rootfs.img LiveOS/
# Create the SquashFS filesystem
sudo mksquashfs LiveOS "$SQUASHFS_OUTPUT_PATH" -comp xz
echo "SquashFS file system has been created as $SQUASHFS_OUTPUT_PATH"
}
These will be located in /mnt/myroot/boot
. Look for files named vmlinuz-*
and initramfs-*.img
.
export TMPSTORE=/tmp/store
mkdir -p $TMPSTORE
cp /mnt/myroot/boot/vmlinuz-* $TMPSTORE
cp /mnt/myroot/boot/initramfs-*.img $TMPSTORE
sudo mkdir -p $ROOT_DIR sudo mkdir -p $TMPSTORE sudo qemu-nbd --disconnect $USB_NBD sudo qemu-nbd --connect=$USB_NBD custom.qcow2 sudo mount "$USB_NBD"p3 $ROOT_DIR
cd $ROOT_DIR sudo mksquashfs /mnt/myroot custom_root.squashfs
sudo cp $ROOT_DIR/boot/vmlinuz-* $TMPSTORE sudo cp $ROOT_DIR/boot/initramfs-*.img $TMPSTORE
## 4. Create usb drive image
### 1. Create the QCOW2 Image:
```bash
qemu-img create -f qcow2 virtual_usb.qcow2 5G
Firstly, map the image to a loopback device:
sudo qemu-nbd --disconnect /dev/nbd0
sudo modprobe nbd max_part=16
sudo qemu-nbd --connect=/dev/nbd0 virtual_usb.qcow2
LOOP_DEVICE=/dev/nbd0
Script example:
if lsblk | grep -q nbd0; then
echo "Cleaning up existing /dev/nbd0 connection..."
sudo qemu-nbd --disconnect /dev/nbd0
fi
sudo modprobe nbd max_part=16
sudo qemu-nbd --connect=/dev/nbd0 virtual_usb.qcow2
LOOP_DEVICE=/dev/nbd0
Now, use parted
to set up partitions automatically:
sudo parted -s $LOOP_DEVICE mklabel gpt
sudo parted -s $LOOP_DEVICE mkpart primary fat32 1MiB 513MiB
sudo parted -s $LOOP_DEVICE set 1 esp on
sudo parted -s $LOOP_DEVICE mkpart primary ext4 513MiB 100%
Format the partitions:
sudo mkfs.vfat ${LOOP_DEVICE}p1
sudo mkfs.ext4 ${LOOP_DEVICE}p2
Mount the partitions:
sudo mkdir -p /mnt/virtual_usb_efi
sudo mkdir -p /mnt/virtual_usb_os
sudo mount ${LOOP_DEVICE}p1 /mnt/virtual_usb_efi
sudo mount ${LOOP_DEVICE}p2 /mnt/virtual_usb_os
Now you can copy your data, kernel, initramfs, and other necessary files into /mnt/virtual_usb_os
.
For both UEFI and BIOS boot:
sudo grub2-install --target=x86_64-efi --no-uefi-secure-boot --efi-directory=/mnt/virtual_usb_efi --boot-directory=/mnt/virtual_usb_os/boot --removable --modules="part_gpt part_msdos"
sudo grub2-install --target=i386-pc --boot-directory=/mnt/virtual_usb_os/boot $LOOP_DEVICE
Ensure you have the GRUB configuration set up correctly in /mnt/virtual_usb_os/boot/grub/grub.cfg
.
Unmount the partitions and detach the loopback device:
sudo umount /mnt/virtual_usb_efi
sudo umount /mnt/virtual_usb_os
sudo qemu-nbd --disconnect /dev/nbd0
sudo modprobe -r nbd
Now, virtual_usb.qcow2
should be ready to boot using QEMU/KVM.
- Mount the new
qcow2
image:
mkdir -p /mnt/virtual_usb
guestmount -a virtual_usb.qcow2 -m /dev/sda1 /mnt/virtual_usb
- Copy the
vmlinuz
,initramfs
, andcustom_root.squashfs
to it:
export TMPSTORE=/tmp/store
mkdir -p $TMPSTORE
cp /path/to/store/vmlinuz-* /mnt/virtual_usb/
cp /path/to/store/initramfs-*.img /mnt/virtual_usb/
cp /path/to/store/custom_root.squashfs /mnt/virtual_usb/
- Install GRUB2:
For BIOS:
grub2-install --target=i386-pc --boot-directory=/mnt/virtual_usb/boot /path/to/virtual_usb.qcow2
For UEFI:
grub2-install --target=x86_64-efi --efi-directory=/mnt/virtual_usb/EFI --boot-directory=/mnt/virtual_usb/boot /path/to/virtual_usb.qcow2
- Create a GRUB config file at
/mnt/virtual_usb/boot/grub/grub.cfg
:
menuentry 'Custom Boot' {
set root=(hd0,1)
linux /vmlinuz root=/dev/sda1 rootfstype=squashfs rootflags=loop real_root=/custom_root.squashfs
initrd /initramfs
}
sudo e2label /dev/sdx3 MY_LIVE_SYSTEM
Run:
qemu-kvm -hda virtual_usb.qcow2 -m 2048
If you've chosen the QCOW2 path and wish to transfer to a physical USB:
dd if=virtual_usb.qcow2 of=/dev/sdX bs=4M status=progress
Caution: Replace /dev/sdX
with your USB drive's device path. Ensure you pick the correct device to avoid data loss.
set timeout=10
set default=0
menuentry 'My Custom RHEL8' {
search --no-floppy --set=root --label MY_LIVE_SYSTEM
linux /boot/vmlinuz rootfstype=squashfs rootflags=loop real_root=/boot/myroot.squashfs
initrd /boot/initramfs
}