on
Virtualization on Linux
Today's entry is about how to set up a virtualization environment in Linux. There are many benefits to virtualization:
- Centralized administration
- Sharing environments
- Exploring new environments without impacting your own
- Isolating environments from others
The three primary advantages I'm looking for are experimentation with new environments, central administration and isolation. I'd like to host a service that requires data backup as well as isolation from other users on the network.
Goals
It's worth noting some goals:
- The hypervisor should run on a headless server running a flavour of Red Hat. The primary selection criteria for the distribution is simple experience.
- The guest machines should be usable over the network from a client.
- The network access must be secure.
- The network controls must be external. Things like VLANs and DHCP should exist external to this implementation.
Dependencies
Some external dependencies that exist and worth calling out:
- Custom certificate authority. Worth a later entry, but I have implemented a custom CA that provides any number of certificate+key pairs.
- DHCP / DNS server. Using dnsmasq all known endpoints on the network are handed an IP address; others are not.
- Enough storage/disk space for the installed OS as well as the install media.
- Spare cores/memory for the host OS + each guest OS.
Install
$ sudo dnf install @virtualization- Install the named group of packages for virtualization.$ sudo dnf install bridge-utils- Install utilities needed for goal number 4.
Configure
/etc/libvirt/libvirtd.confConfigure libvirtd to enable TLS over the network. This install depends on using an existing certificate authority and establishing trust of the CA on both the client and server.
# TLS x509 certificate configuration
...
key_file = path-to-pem-encoded-key
cert_file = path-to-pem-encoded-certificate
ca_file = path-to-pem-encoded-authority-certificate
...
/etc/libvirt/qemu.confConfigure QEMU to listen on the public/routable address for both VNC, as well as SPICE.
# VNC is configured to listen on 127.0.0.1 by default.
# To make it listen on all public interfaces, uncomment
# this next option.
#
# NB, strong recommendation to enable TLS + x509 certificate
# verification when allowing public access
#
...
vnc_listen = "0.0.0.0"
...
# SPICE is configured to listen on 127.0.0.1 by default.
# To make it listen on all public interfaces, uncomment
# this next option.
#
# NB, strong recommendation to enable TLS + x509 certificate
# verification when allowing public access
#
spice_listen = "0.0.0.0"
/etc/sysconfig/libvirtdConfigure libvirtd to listen on TCP/IP sockets in addition to the local socket. When troubleshooting connectivity or other service issues adding:--verbosecan be useful for generating log output.
--listen
/etc/NetworkManager/system-connections/bridge0.nmconnectionConfigure a network bridge:
[connection]
id=bridge0
uuid=819a28c5-75e0-4b74-9ff7-aa3f6291e2d0
type=bridge
autoconnect-ports=1
interface-name=bridge0
[ethernet]
[bridge]
[ipv4]
method=auto
[ipv6]
addr-gen-mode=default
method=auto
[proxy]
/etc/NetworkManager/system-connections/eth0.nmconnectionConfigure the connection being bridged:
[connection]
id=eth0
uuid=9c2f71f0-c8d7-4d4a-8609-8e25bf396848
type=ethernet
autoconnect-priority=-999
controller=bridge0 # see step 4
interface-name=eth0
port-type=bridge
timestamp=1764793260
[ethernet]
[bridge-port]
Run
$ sudo systemctl enable --now libvirtd-tls.socket$ sudo systemctl enable --now libvirtd
Connect and New
In addition to encryption; libvirt uses TLS for authentication. In order to use the running service; we need to set the CA as well as provide a certificate from the client:
/home/example/.pki/libvirt/cacert.pemPEM encoded ca certificate./home/example/.pki/libvirt/clientcert.pemPEM encoded client certificate./home/example/.pki/libvirt/clientkey.pemPEM encoded client key.
Once libvirtd-tls.socket is up and running you can use Virtual Machine Manager as a user interface to build your botnet:
- File -> Add Connection... -> Hypervisor: Custom URI
qemu://qemu.example.com/system- This will add a row in the interface. - qemu.example.com -> Right Click -> Details -> Storage -> Add Pool -> Type: dir: Filesystem Directory
path-to-media-stored-on-the-server- This will enable you to create VMs from media files stored on the server. - qemu.example.com -> Right Click -> Details -> Storage -> Add Pool -> Type: dir: Filesystem Directory
path-to-images-stored-on-the-server- This will enable you to store the image files used by QEMU on the filesystem. - qemu.example.com -> Right Click -> New -> Choose how...
Local install media...- This will create the VM and walk through the boot media and hardware selection process.
Epilogue
This setup worked well enough move my development workstation into a VM running Fedora 43. I have no issues with latency (everything is on a wired LAN) and can replicate all most engineering workflows.
What does not work:
- Remote video conferencing. I have not probed the feasibility of forwarding USB streams over the network.
- Some desktop applications needing GPU tuning or performance. I had difficulty with a web app installed as a Flatpak.
- Shared filesystem. The permissions model was insufficient for me to map directories from the host to the guest.
Refs
- Virtualization#Benefits_and_disadvantages
- Dnsmasq: Provides network infrastructure for small networks: DNS, DHCP, router advertisement and network boot.
- Fedora: Virtualization - Getting Started: Getting Started Guide
- Planet Virt Tools: Blogging about open source virtualization.
- libvirt: Virtualization API. Supports multiple implementations including KVM.
- libvirt: TLS (Encryption and Authentication): Manual TLS Setup
- QEMU: Machine emulator and virtualizer.
- Kernel Virtual Machine: Full virtualization for Linux on x86.
- SPICE: Remote access to virtual machines.