Introduction
Fedora Server provides an enterprise-grade virtualization platform using KVM (Kernel-based Virtual Machine) and libvirt - the same technologies that power major cloud providers and hypervisors like Proxmox and OpenStack. Unlike proprietary solutions (VMware ESXi) or dedicated hypervisors (Proxmox), Fedora Server offers a complete Linux environment with virtualization capabilities, giving you flexibility for both VM hosting and container workloads.
Why Choose Fedora as a Virtualization Host?
| Feature | Fedora Server | Proxmox VE | VMware ESXi |
|---|---|---|---|
| Base System | Full Linux OS | Debian-based | Proprietary |
| License Cost | Free | Free (paid support) | Paid |
| Hypervisor | KVM/QEMU | KVM/QEMU | ESXi |
| Container Runtime | Podman (native) | LXC/Docker | None |
| Web Management | Cockpit | Proxmox UI | vCenter |
| CLI Access | Full Linux shell | Limited | Very limited |
| Package Updates | dnf (latest) | apt (stable) | VMware patches |
Architecture Overview
The virtualization stack consists of several layers:
- KVM - Kernel module that turns Linux into a Type-1 hypervisor
- QEMU - Hardware emulator that provides virtual hardware devices
- libvirt - Virtualization API and daemon for managing VMs
- virt-manager - Desktop GUI for VM management
- Cockpit - Web-based administration interface
Setup Fedora VM Server
The @virtualization group installs all necessary packages including QEMU, libvirt, virt-install, and related tools.
1sudo dnf install @virtualization2sudo systemctl enable --now libvirtdVerify KVM Hardware Support
Before creating VMs, verify that your CPU supports hardware virtualization (Intel VT-x or AMD-V):
1# Check if KVM modules are loaded2lsmod | grep kvm3
4# Verify hardware virtualization support5egrep -c '(vmx|svm)' /proc/cpuinfo6# Output > 0 means virtualization is supported7
8# Detailed CPU flags check9cat /proc/cpuinfo | grep -E '(vmx|svm|ept|npt)'Expected output for Intel CPUs shows kvm_intel, for AMD shows kvm_amd:
1kvm_intel 458752 02kvm 1339392 1 kvm_intel3irqbypass 12288 1 kvmConfigure libvirt for Non-Root Access
Add your user to the libvirt group to manage VMs without sudo:
1# Add current user to libvirt group2sudo usermod -aG libvirt $(whoami)3
4# Apply group changes (or logout/login)5newgrp libvirt6
7# Verify access8virsh list --allNetwork Configuration
libvirt creates a default NAT network (virbr0). For production servers, you may want to configure bridged networking:
1# View existing networks2virsh net-list --all3
4# View default network details5virsh net-info default6
7# Start and autostart default network8virsh net-start default9virsh net-autostart defaultFor bridged networking (VMs get IPs from your LAN DHCP):
1# Create bridge interface using NetworkManager2sudo nmcli connection add type bridge ifname br0 con-name br03sudo nmcli connection add type ethernet ifname eth0 master br04
5# Activate the bridge6sudo nmcli connection up br0Storage Pool Configuration
Configure dedicated storage pools for VM images:
1# Create directory for VM images2sudo mkdir -p /var/lib/libvirt/images3
4# Define and start a storage pool5virsh pool-define-as default dir --target /var/lib/libvirt/images6virsh pool-start default7virsh pool-autostart default8
9# View pool information10virsh pool-info defaultTools
Cockpit provides a modern web interface for server administration, and the cockpit-machines module adds VM management capabilities.
1sudo dnf install cockpit cockpit-machines2sudo systemctl enable --now cockpit.socketAccessing Cockpit
After installation, access the web interface at https://your-server-ip:9090. The interface provides:
- Virtual Machines - Create, start, stop, and console access
- Storage - Manage disks and storage pools
- Networking - Configure network interfaces and bridges
- Terminal - Web-based terminal access
- Users - System user management
- Services - systemd service control
Firewall Configuration
If firewalld is active, allow Cockpit access:
1# Allow Cockpit through firewall2sudo firewall-cmd --permanent --add-service=cockpit3sudo firewall-cmd --reload4
5# Verify6sudo firewall-cmd --list-servicesAdditional Cockpit Modules
Extend Cockpit functionality with additional packages:
1# Storage management (LVM, RAID, etc.)2sudo dnf install cockpit-storaged3
4# Container management5sudo dnf install cockpit-podman6
7# Performance monitoring (PCP)8sudo dnf install cockpit-pcp9
10# Software updates11sudo dnf install cockpit-packagekitCreating Virtual Machines
Using virt-install (CLI)
Create VMs from the command line for automation and scripting:
1# Download Fedora cloud image2curl -LO https://download.fedoraproject.org/pub/fedora/linux/releases/42/Cloud/x86_64/images/Fedora-Cloud-Base-42-1.1.x86_64.qcow23
4# Create VM from cloud image5virt-install \6 --name fedora-vm \7 --memory 4096 \8 --vcpus 2 \9 --disk path=/var/lib/libvirt/images/fedora-vm.qcow2,size=40 \10 --os-variant fedora42 \11 --network network=default \12 --graphics vnc \13 --import \14 --noautoconsoleCommon virt-install Options
| Option | Description | Example |
|---|---|---|
--name | VM name | --name myvm |
--memory | RAM in MB | --memory 8192 |
--vcpus | CPU cores | --vcpus 4 |
--disk | Storage config | --disk size=50 |
--cdrom | ISO installer | --cdrom /path/to.iso |
--network | Network type | --network bridge=br0 |
--os-variant | OS optimization | --os-variant ubuntu24.04 |
--graphics | Display type | --graphics spice |
virsh Management Commands
1# List all VMs2virsh list --all3
4# Start a VM5virsh start vm-name6
7# Graceful shutdown8virsh shutdown vm-name9
10# Force stop11virsh destroy vm-name12
13# Delete VM (keeps disk)14virsh undefine vm-name15
16# Delete VM with storage17virsh undefine vm-name --remove-all-storage18
19# Console access20virsh console vm-name21
22# View VM configuration23virsh dumpxml vm-namePodman Container
Podman is a daemonless container engine that's fully compatible with Docker but runs rootless by default, providing enhanced security.
1sudo dnf install podman2podman machine init3podman machine startRootless Container Execution
Podman's primary advantage is running containers without root privileges:
1# Verify rootless setup2podman info | grep -i rootless3
4# Run container as regular user5podman run --rm alpine:latest id6# Output: uid=0(root) gid=0(root) - root inside, your user outside7
8# Check user namespace mapping9podman unshare cat /proc/self/uid_mapContainer Networking
Podman supports multiple networking modes for different use cases:
1# Default bridge networking with port mapping2podman run -d -p 8080:80 --name webserver nginx:alpine3
4# Connect to multiple networks with static IPs5podman run --network net1:ip=10.89.1.5 --network net2:ip=10.89.10.10 alpine ip addr6
7# Host networking (container uses host network stack)8podman run --network host nginx:alpine9
10# Create custom network11podman network create mynetwork12podman run --network mynetwork alpineVolume Mounts and Persistence
1# Mount host directory with SELinux context2podman run -v ~/data:/data:Z alpine:latest ls -la /data3
4# Named volumes for persistence5podman volume create mydata6podman run -v mydata:/app/data alpine7
8# Bind mount with read-only access9podman run -v /etc/hosts:/etc/hosts:ro alpine cat /etc/hostsPodman Compose
Use Docker Compose files with Podman:
1# Install podman-compose2sudo dnf install podman-compose3
4# Run compose file5podman-compose up -d6
7# Or use podman's built-in compose8podman compose up -dSystemd Integration
Generate systemd service files for containers:
1# Generate systemd unit for existing container2podman generate systemd --name mycontainer --files3
4# Enable container to start on boot5systemctl --user enable container-mycontainer.service6systemctl --user start container-mycontainer.service7
8# For rootful containers9sudo systemctl enable container-mycontainer.serviceContainer Resource Limits
1# Limit CPU and memory2podman run --cpus 2 --memory 1g nginx:alpine3
4# CPU shares (relative weight)5podman run --cpu-shares 512 nginx:alpine6
7# Memory with swap limit8podman run --memory 1g --memory-swap 2g nginx:alpinePerformance Tuning
CPU Pinning for VMs
Pin virtual CPUs to physical cores for consistent performance. Edit VM configuration:
1<vcpu placement='static'>4</vcpu>2<cputune>3 <vcpupin vcpu="0" cpuset="2"/>4 <vcpupin vcpu="1" cpuset="3"/>5 <vcpupin vcpu="2" cpuset="4"/>6 <vcpupin vcpu="3" cpuset="5"/>7 <emulatorpin cpuset="0-1"/>8</cputune>Apply with: virsh edit vm-name
Hugepages for Memory Performance
Enable hugepages for VMs with large memory allocations:
1# Check current hugepage configuration2cat /proc/meminfo | grep Huge3
4# Allocate hugepages (2MB pages, allocate 4GB worth)5echo 2048 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages6
7# Make persistent in /etc/sysctl.conf8echo "vm.nr_hugepages = 2048" | sudo tee -a /etc/sysctl.confI/O Tuning
Use virtio drivers for best I/O performance:
1# Create VM with virtio disk and network2virt-install \3 --name fast-vm \4 --memory 8192 \5 --vcpus 4 \6 --disk path=/var/lib/libvirt/images/fast-vm.qcow2,size=100,bus=virtio,cache=writeback \7 --network network=default,model=virtio \8 --os-variant fedora42 \9 --cdrom /path/to/fedora.isoBackup and Snapshots
VM Snapshots
1# Create snapshot2virsh snapshot-create-as vm-name snapshot1 "Before update"3
4# List snapshots5virsh snapshot-list vm-name6
7# Revert to snapshot8virsh snapshot-revert vm-name snapshot19
10# Delete snapshot11virsh snapshot-delete vm-name snapshot1Backup VM Images
1# Shutdown VM for consistent backup2virsh shutdown vm-name3
4# Copy disk image5cp /var/lib/libvirt/images/vm-name.qcow2 /backup/6
7# Export VM configuration8virsh dumpxml vm-name > /backup/vm-name.xml9
10# Compress backup11qemu-img convert -c -O qcow2 vm-name.qcow2 vm-name-backup.qcow2Monitoring and Troubleshooting
Resource Monitoring
1# VM statistics2virt-top3
4# Detailed VM info5virsh dominfo vm-name6virsh domstats vm-name7
8# CPU usage9virsh cpu-stats vm-name10
11# Memory stats (requires balloon driver)12virsh dommemstat vm-nameLog Files
Key log locations for troubleshooting:
| Log | Path | Purpose |
|---|---|---|
| libvirtd | /var/log/libvirt/libvirtd.log | libvirt daemon logs |
| QEMU | /var/log/libvirt/qemu/vm-name.log | Per-VM QEMU logs |
| Cockpit | journalctl -u cockpit | Cockpit service logs |
| Podman | podman logs container-name | Container stdout/stderr |
1# Enable debug logging for libvirt2sudo virsh -c qemu:///system managedsave-define --config \3 "<libvirtd><log_level>1</log_level></libvirtd>"4
5# View QEMU process for specific VM6ps aux | grep qemu | grep vm-name