I was, frankly, shocked at just how easy Linux VMs are to set up and manage.
PreparationIf the hardware supports hardware virtualization...
$ egrep -c '(vmx|svm)' /proc/cpuinfo 2 // A result of '0' means no. '1' or higher means yes
...then reboot into BIOS and turn it on.
Creating the first VM:Once virtualization is turned on, then from zero to fully operating is just three commands. The host is Ubuntu 17.10. The guest will also be 17.10, but that is merely because I lack imagination.
1) Install KVM, qemu, virt-manager and all the other tools you need. The are all dependencies of a single package:
$ sudo apt install uvtool
2) Download a cloud image of Ubuntu 17.10. Cloud images are headless - shell only. The download takes a few minutes (approximately 350 MB), so don't panic:
$ uvt-simplestreams-libvirt sync release=artful arch=amd64
3) Create and start VM Guest 'test1'
$ uvt-kvm create test1 release=artful
Starting, Stopping, Suspending, and Resuming the VM Guest from Host
$ virsh list // Check status Id Name State ---------------------------------------------------- 1 test1 running $ virsh suspend test1 Domain test1 suspended $ virsh resume test1 Domain test1 resumed $ virsh shutdown test1 Domain test1 is being shutdown $ virsh list --all // Use --all to show inactive VMs Id Name State ---------------------------------------------------- - test1 shut off $ virsh start test1 Domain test1 started $ virsh list Id Name State ---------------------------------------------------- 2 test1 running
Under the hood looking at storage
We didn't set up a any virtual storage, and we don't know where that Ubuntu Cloud image went. Let's take a moment and figure it out using virsh...
$ virsh dumpxml test2 | grep file <disk device="disk" type="file"> <source file="/var/lib/uvtool/libvirt/images/test1.qcow"></source> <backingstore index="1" type="file"> <source file="/var/lib/uvtool/libvirt/images/x-uvt-b64-Y29tLnVidW50dS5jbG91ZDpzZXJ2ZXI6MTcuMTA6YW1kNjQgMjAxODAzMTQ="></source> <disk device="disk" type="file"> <source file="/var/lib/uvtool/libvirt/images/test1-ds.qcow"></source> </disk></backingstore>
There are the images for the virtual storage devices, and for the original cloud image ('backingstore') too. Looks like they are all in the same directory.
$ ls -l /var/lib/uvtool/libvirt/images/ total 1490572 -rw------- 1 libvirt-qemu kvm 458752 Mar 14 22:06 test1-ds.qcow -rw------- 1 libvirt-qemu kvm 490471424 Mar 15 08:14 test1.qcow -rw------- 1 libvirt-qemu kvm 1035468800 Mar 14 22:05 x-uvt-b64-Y29tLnVidW50dS5jbG91ZDpzZXJ2ZXI6MTcuMTA6YW1kNjQgMjAxODAzMTQ=
Aha. There's the cloud image is the third line - that's where it went! The actual VM Guest storage is the first and second lines - they are simply diffs from the original cloud image. Multiple Guests can base off the same cloud image, keeping storage tidy...and small.
Let's add another Guest VM and see how it changes.
$ uvt-kvm create test2 release=artful $ ls -l /var/lib/uvtool/libvirt/images/ total 1491344 -rw------- 1 libvirt-qemu kvm 458752 Mar 14 22:06 test1-ds.qcow -rw------- 1 libvirt-qemu kvm 490471424 Mar 15 08:29 test1.qcow -rw------- 1 libvirt-qemu kvm 458752 Mar 15 08:34 test2-ds.qcow -rw------- 1 libvirt-qemu kvm 393216 Mar 15 08:34 test2.qcow -rw------- 1 libvirt-qemu kvm 1035468800 Mar 14 22:05 x-uvt-b64-Y29tLnVidW50dS5jbG91ZDpzZXJ2ZXI6MTcuMTA6YW1kNjQgMjAxODAzMTQ=
A whole fresh VM takes less than 1 MB. Of course, it will grow quickly once you start giving it work to do.
And here you can see how to destroy a VM Guest properly. The guest files are deleted, the cloud image is not.
$ uvt-kvm destroy test2 $ ls -l /var/lib/uvtool/libvirt/images/ total 1490572 -rw------- 1 libvirt-qemu kvm 458752 Mar 14 22:06 test1-ds.qcow -rw------- 1 libvirt-qemu kvm 490471424 Mar 15 08:29 test1.qcow -rw------- 1 libvirt-qemu kvm 1035468800 Mar 14 22:05 x-uvt-b64-Y29tLnVidW50dS5jbG91ZDpzZXJ2ZXI6MTcuMTA6YW1kNjQgMjAxODAzMTQ=
Securing VM Guest with a new admin account and SSH Keysuvt-created guests start with the 'ubuntu' admin user, so you can start the process of customization without a lot of hassle. But they are insecure, so let's add our own admin user and delete that default fellow.
Step 1. On the HOST, login insecurely to the Guest
host$ uvt-kvm ssh test1
Step 2. On the GUEST, add the new admin user. Let's call her 'adminnnn', and let's make her part of the 'sudo' group (since she's an admin, of course). The 'adduser' command below asks a few questions, including a password. Give a password. We will need it once later to set up SSH keys, and --of course-- to use sudo in the Guest.
test1$ sudo adduser adminnnn --ingroup sudo
Step 3. Edit the SSH settings to briefly permit insecure login so we can place the ssh key. We will change this back in a later step. I use nano - you use whatever editor you wish.
test1$ sudo nano /etc/ssh/sshd_config
PubKey Authentication yes Password Authentication yes ChallengeResponseAuthentication no UsePAM yes (Remember to save your changes!)
Step 4. Restart SSH so the sshd config changes take effect, and logout from the 'ubuntu' user
test1$ sudo service sshd restart test1$ exit
Step 5. Create an SSH key if you don't already have one. If you already have a key then use it, of course. Learn the IP address of the Guest. Copy the key across to the Guest. Login using the new key
host$ ssh-keygen host$ uvt-kvm ip test1 192.168.122.249 host$ ssh-copy-id email@example.com host$ ssh firstname.lastname@example.org
Step 6. Test adminnnn's new sudo powers. If they work then delete the 'ubuntu' user.
test1$ sudo apt update test1$ sudo apt upgrade test1$ sudo deluser ubuntu
Step 7. Tighten ssh to allow keys only. Finally, we will exit so the sshd changes take effect.
test1$ sudo nano /etc/ssh/sshd_config
PubKey Authentication yes Password Authentication no ChallengeResponseAuthentication no UsePAM no (Remember to save your changes!) test1$ sudo service sshd restart test1$ exit
...and that's all you need
Let's add a full Desktop EnvironmentIn this case, let's add Lubuntu.
host$ ssh email@example.com test1$ sudo apt install lubuntu-desktop --no-install-recommends test1$ exit
A reboot is necessary for the new desktop to launch at startup. Let's use virt-viewer to watch the reboot process. We could also use remmina since we know the IP address.
host$ virt-viewer test1 test1$ sudo reboot
After reboot, the desktop should come up.
To eliminate the desktop, including another way to reboot:
host$ ssh firstname.lastname@example.org test1$ sudo apt remove lubuntu-desktop test1$ sudo apt autoremove test1$ exit host$ virsh reboot test1
It's poor practice to leave your system littered with old experiments. When finished playing, here's how to clean up. All of these commands, of course, are done on the HOST.
To delete just one Guest VM, but leave the VM Host software on your system:
$ uvt-kvm destroy test1
To delete the VM Host software from your system (Ubuntu), but leave guest Virtual Disks intact:
$ sudo apt remove uvtool $ sudo apt autoremove
To delete any remaining Virtual Disks, including the cloud image(s) they are based upon.
sudo rm -r /var/lib/uvtool