Guestfish lets you open, inspect, and modify virtual machine disk images without booting the VM. Need to inject an SSH key into a cloud image, fix a broken /etc/fstab, reset a root password, or pull log files from a crashed guest? Guestfish handles all of that from the hypervisor host, with the VM powered off.
It’s part of the libguestfs toolkit and works with qcow2, raw, VMDK, VHD, and any format QEMU understands. This guide covers installation, practical use cases, and every operation you’ll actually need when managing KVM virtual machines.
Tested March 2026 | guestfish 1.48.6 on Proxmox VE 8.4, Rocky Linux 10.1 guest image (qcow2)
Install Guestfish
Guestfish is part of the libguestfs toolkit. Install it on the KVM host (not inside the guest). The package name differs between distributions.
On Ubuntu/Debian/Linux Mint:
sudo apt install -y libguestfs-tools
On Rocky Linux/AlmaLinux/RHEL 10:
sudo dnf install -y guestfs-tools
Note the different package names: libguestfs-tools on Debian-based, guestfs-tools on RHEL-based. Both install the same guestfish binary and companion tools (virt-cat, virt-ls, virt-edit, etc.).
Verify the installation:
guestfish --version
On our Debian-based Proxmox host this returned guestfish 1.48.6. On Rocky Linux 10.1 it installed version 1.56.1.
Before You Start
The VM must be shut down before modifying its disk image. Running guestfish against a live VM’s disk will corrupt the filesystem. Shut it down first:
sudo virsh shutdown myvm
Find the disk image path:
virsh dumpxml myvm | grep "source file"
This returns the full path to the qcow2 or raw image. On Proxmox with LVM-thin storage, the path looks like /dev/pve/vm-100-disk-0.
Opening a Disk Image
Guestfish can open images in read-only or read-write mode. The -i flag auto-detects the OS and mounts all partitions.
Read-only (safe for inspection, no changes possible):
sudo guestfish --ro -i -a /path/to/disk.qcow2
Read-write (for modifications):
sudo guestfish --rw -i -a /path/to/disk.qcow2
You can also reference a libvirt domain by name instead of the image path:
sudo guestfish --ro -i -d myvm
After connecting, the guestfish shell displays the detected OS and mounted partitions:
Welcome to guestfish, the guest filesystem shell for
editing virtual machine filesystems and disk images.
Type: 'help' for help on commands
'man' to read the manual
'quit' to quit the shell
Operating system: Rocky Linux 10.1 (Red Quartz)
/dev/sda4 mounted on /
/dev/sda3 mounted on /boot
/dev/sda2 mounted on /boot/efi
><fs>
The ><fs> prompt is where you type commands. One important difference from a regular shell: there is no concept of a current working directory. You cannot cd into a directory. All paths must be absolute, starting with /. Tab completion works for paths.
Inspect the Guest OS
Read the OS release info:
cat /etc/os-release
On our Rocky Linux 10.1 test image:
NAME="Rocky Linux"
VERSION="10.1 (Red Quartz)"
ID="rocky"
ID_LIKE="rhel centos fedora"
VERSION_ID="10.1"
PRETTY_NAME="Rocky Linux 10.1 (Red Quartz)"
Query OS metadata programmatically (useful in scripts):
inspect-get-distro /dev/sda4
rocky
inspect-get-product-name /dev/sda4
Rocky Linux 10.1 (Red Quartz)
inspect-get-hostname /dev/sda4
guestfish-test
inspect-get-type /dev/sda4
linux
List Devices, Partitions, and Filesystems
See all block devices:
list-devices
/dev/sda
List partitions:
list-partitions
/dev/sda1
/dev/sda2
/dev/sda3
/dev/sda4
Map partitions to filesystem types:
list-filesystems
/dev/sda1: unknown
/dev/sda2: vfat
/dev/sda3: xfs
/dev/sda4: xfs
Check disk usage inside the guest:
df-h
This shows the same output you’d get from running df -h inside the VM:
Filesystem Size Used Avail Use% Mounted on
/dev/sda4 19G 953M 18G 6% /sysroot
/dev/sda3 936M 187M 750M 20% /sysroot/boot
/dev/sda2 200M 13M 187M 7% /sysroot/boot/efi
For images with LVM, use pvs, vgs, and lvs to list physical volumes, volume groups, and logical volumes.
Browse and Read Files
List directory contents:
ls /root
.bash_logout
.bash_profile
.bashrc
.cshrc
.ssh
.tcshrc
For detailed output with permissions and sizes, use ll instead:
ll /root
Read a file:
cat /etc/hostname
Modify Files and Directories
These operations require read-write mode (--rw). The most common real-world use cases:
Inject an SSH Key
This is probably the most frequent reason to use guestfish. Inject a public key so you can SSH into the VM after boot. Run this from the host (not inside the guestfish shell):
sudo guestfish --rw -i -a /path/to/disk.qcow2 \
mkdir-p /root/.ssh : \
write /root/.ssh/authorized_keys "ssh-ed25519 AAAAC3... your-key" : \
chmod 0700 /root/.ssh : \
chmod 0600 /root/.ssh/authorized_keys
The colon (:) separates multiple commands on the guestfish command line. Verify the key was written:
sudo guestfish --ro -i -a /path/to/disk.qcow2 cat /root/.ssh/authorized_keys
Change the Hostname
Overwrite the hostname file from within the guestfish shell:
write /etc/hostname "new-hostname
"
cat /etc/hostname
new-hostname
Edit Configuration Files
The edit command downloads the file, opens it in your local $EDITOR, then uploads it back:
edit /etc/fstab
This is ideal for fixing a broken /etc/fstab that prevents a VM from booting.
Create Files and Directories
Create a directory structure and write a script into it:
mkdir-p /opt/scripts
write /opt/scripts/hello.sh "#!/bin/bash
echo Hello from guestfish
"
chmod 0755 /opt/scripts/hello.sh
Verify the file:
cat /opt/scripts/hello.sh
#!/bin/bash
echo Hello from guestfish
Delete a directory with rmdir (must be empty) or rm-rf (recursive delete).
Copy Files Between Host and Guest
Upload a File to the Guest
Push a file from the host into the guest filesystem:
upload /tmp/host-file.txt /root/from-host.txt
Verify it landed:
cat /root/from-host.txt
Uploaded from host at Thu Mar 26 15:18:34 EAT 2026
Download a File from the Guest
Pull a file from the guest to the host:
download /etc/os-release /tmp/guest-os-release
After exiting guestfish, the file is on the host at /tmp/guest-os-release.
Copy Entire Directories
Pull a directory from the guest to the host:
copy-out /var/log /tmp/guest-logs
Push a local directory into the guest:
copy-in /tmp/configs /etc/
Pack and Download as Tarball
Export a guest directory as a compressed tar archive:
tar-out /var/log /tmp/guest-logs.tar.gz compress:gzip
To unpack after exiting guestfish:
tar xzf /tmp/guest-logs.tar.gz
The reverse operation pushes a local tarball into the guest:
tar-in backups.tar.gz /tmp compress:gzip
Quick Commands Without the Interactive Shell
The libguestfs package includes several standalone commands that skip the interactive shell entirely. These are faster for scripting and one-off tasks.
Read a single file:
sudo virt-cat -a /path/to/disk.qcow2 /etc/hostname
List a directory:
sudo virt-ls -a /path/to/disk.qcow2 /root/
List all filesystems with sizes:
sudo virt-filesystems -a /path/to/disk.qcow2 --all --long --human-readable
On our test image:
Name Type VFS Label Size Parent
/dev/sda1 filesystem unknown - 2.0M -
/dev/sda2 filesystem vfat EFI 200M -
/dev/sda3 filesystem xfs BOOT 936M -
/dev/sda4 filesystem xfs rocky 18G -
/dev/sda device - - 20G -
Edit a file in one command (opens in $EDITOR):
sudo virt-edit -a /path/to/disk.qcow2 /etc/fstab
Copy files into a guest image:
sudo virt-copy-in -a /path/to/disk.qcow2 /tmp/local-file.txt /root/
Copy files out of a guest image:
sudo virt-copy-out -a /path/to/disk.qcow2 /etc/os-release /tmp/
SELinux Considerations (RHEL/Rocky/Alma)
When you modify files in a RHEL-family guest using guestfish, the new files may not have the correct SELinux labels. The guest will relabel them on next boot if autorelabel is enabled, but this adds boot time.
To trigger a relabel on the next boot, create the /.autorelabel file inside the guestfish shell:
touch /.autorelabel
Alternatively, use virt-customize which handles SELinux relabeling automatically. This runs from the host:
sudo virt-customize -a /path/to/disk.qcow2 \
--run-command 'echo modified > /etc/hostname' \
--selinux-relabel
Guestfish Command Reference
Common commands inside the guestfish shell:
| Command | Description |
|---|---|
ls /path | List directory contents |
ll /path | Long listing with permissions |
cat /file | Display file contents |
write /file "content" | Write string to file |
edit /file | Edit file in local $EDITOR |
upload local remote | Copy file from host to guest |
download remote local | Copy file from guest to host |
copy-in /local /guest | Copy directory from host to guest |
copy-out /guest /local | Copy directory from guest to host |
mkdir-p /path | Create directory (with parents) |
chmod 0755 /file | Change file permissions |
chown uid gid /file | Change file ownership |
rm /file | Delete a file |
rm-rf /path | Recursive delete |
tar-out /dir file.tar.gz compress:gzip | Export directory as tarball |
tar-in file.tar.gz /dir compress:gzip | Import tarball into guest |
df-h | Disk usage |
list-filesystems | List all filesystems |
list-devices | List block devices |
inspect-get-distro /dev | Get OS distribution name |
help command | Get help on a command |
exit | Quit guestfish |
For the full list of all available commands:
help --list
Related tools for KVM image management: