Since virtual machines created with KVM/QEMU are not simple containers but quite isolated from the hosts environment, QEMU offers a companion service called
qemu-guest-agent for Linux guests. qemu-guest-agent acts as an interface between the VMs and the host system.
Some features like passing ACPI information for a clean guest shutdown are pretty well-known. However, did you know that you can even send commands to your VMs directly from your Proxmox host system?
Proxmox Virtual Environment uses KVM/QEMU as virtualization technology. Since calling the qemu-guest-agent interface is not very intuitive by itself, Proxmox provides the qm guest command which acts like a bridge between the host system and the VMs.
qm guest command requires
qemu-guest-agent to be installed inside your Linux guests. Since the guest agent is pretty essential in case you want to be able to do properly shut down the VMs without performing virtual powercuts or being able to create consistent backups, you want to install it on all of your Linux guests anyways.
In order to use the following commands, you need to get the VMID of your virtual machines. You can either get them from the Proxmox dashboard or by running the
qm list command on your host system.
Reset user passwords (including the root user)
I basically learned about
qm by accident. Usually, I tend to lock all local user accounts in order to make (virtual) console access impossible. Especially on VMs, this might not even be exactly helpful regarding security, but this is some sort of personal preference. Due to a configuration error on my end, I locked myself out of a VM running on my Proxmox host, so I was not able to SSH into it anymore.
The obvious solution would be to shut down the VM, boot a rescue environment or live distribution, mount the disk and fix the configuration there. I knew the VM was performing some maintenance tasks in the background which do not like sudden interruptions, so I needed some sort of backdoor.
This is where
qm guest passwd comes in handy. As the command suggests, it can be used to set user passwords in your VM, even if there’s no direct access to it anymore.
As an example, the following command resets the password for the user root on VMID 100:
qm guest passwd 100 root
After invoking this command, qm will interactively tell you how to set a new user password for the account in question. If the user was previously locked with
passwd -l, the user will be automatically unlocked.
Run arbitrary commands in your VM
As you might have noticed, we have full access to the guest operating system using the QEMU Guest Agent (or QGA for short). Therefore, we can pass any command to the guest. Side note: This is a friendly reminder that you really want to care about the security of your host system.
The command we are looking for is
qm guest exec (again using VMID 100 as an example):
qm guest exec 100 -- ping google.com -c 3
qm exec will pass the command to the VM, execute it and wait for the command to finish or break with an exit code. Afterwards, it will return the exit code as well as the contents of stdout and stderr in JSON format. Please be aware that all commands are executed with root privileges.
Long-running tasks can be sent to the background using the
--synchronous=0 parameter. You can check the state of the process by using the
qm guest exec-status $VMID $PID command.
Get additional VM information and perform low-level tasks
Next, let’s take a look at
qm guest cmd. Now, we are not executing commands within the guest operating system itself. Instead, with
cmd we call various QGA commands on a lower level. Those commands are more focused on maintenance and less on interaction with the guest operating system.
In order to use this feature, use the following command:
qm guest cmd $VMID $Command
I compiled a list of valid commands below. Just like the
qm guest exec command, the output will be JSON formatted.
|Send the |
|Query fsfreeze-status, returns ‘frozen’ or ‘thawed’|
|Thawing a frozen filesystem returns control to the guest operating system|
|Issue the TRIM command to the VM’s block device(s). The VM has to be configured with the |
|Returns all mounted filesystems|
|Returns the hostname of the guest system|
|Displays memory information|
|Displays memory information|
|Displays various OS information like the distribution, kernel version and architecture|
|Get the system time of the guest OS|
|Get the timezone set in the guest OS|
|Get all users currently logged into the guest OS|
|Get information about the assigned virtual CPUs|
|Return a list of available commands that can be issued through QGA|
|Return a list of configured network interfaces along with traffic statistics|
|Check if the VM is up and qemu-guest-agent is running. If this command times out, the VM is either offline or qemu-guest-agent is not working properly. Note: This is not a ‘traditional’ ping over a network connection. Instead, the host is trying to communicate with the VM over QGA.|
|Send the ACPI shutdown command to the VM|
|Send the suspend-to-disk command to the VM|
|Send the suspend-hybrid (faster suspend-to-disk?) to the VM|
|Send the suspend-to-ram command to the VM|
The QEMU Guest Agent provides an extensive interface for communication between the host system and the VMs.
You can either send any arbitray command to the guest systems or use QGA to get some details about the VMs themselves. It is also possible to go a bit more low-level, so you can shutdown your VMs or let the host system take control over the file system by essentially freezing it. This is especially helpful if you want to use Proxmox’ built-in snapshots. However, if you use the backup and snapshot functions from the Proxmox GUI, freezing and thawing is handled automatically.
Currently, only a subset of the QGA protocol is abstracted by the
qm command. Since calling the other commands supported by QGA is a little bit more complicated, I’ll cover this in a seperate article.