Skip to content

Instantly share code, notes, and snippets.

@usrbinkat
Created October 24, 2025 19:13
Show Gist options
  • Select an option

  • Save usrbinkat/e8ba7f52cd1c835ce30e2345e7104a78 to your computer and use it in GitHub Desktop.

Select an option

Save usrbinkat/e8ba7f52cd1c835ce30e2345e7104a78 to your computer and use it in GitHub Desktop.
KubeVirt Fedora 42 Gnome xRDP VDI Demo
---
#cloud-config
hostname: fedora
fqdn: fedora.home.arpa
ssh_pwauth: true
disable_root: false
# User configuration
chpasswd:
list: |
root:kc2admin
kc2user:kc2user
expire: False
users:
- default
- name: kc2user
gecos: Kargo Compute User
shell: /bin/bash
lock_passwd: false
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
groups: wheel,adm,systemd-journal,docker,libvirt,kvm,qemu,xrdp,audio,video
ssh_import_id:
- gh:usrbinkat
# Disk expansion
growpart:
mode: auto
devices: ["/"]
ignore_growroot_disabled: true
# System configuration
timezone: UTC
# Fix DNS timing: Make cloud-config.service wait for network-online.target
# This ensures NetworkManager finishes configuring DNS before package operations
write_files:
- path: /etc/systemd/system/cloud-config.service.d/wait-network-online.conf
content: |
[Unit]
After=network-online.target
Wants=network-online.target
owner: root:root
permissions: "0644"
# Reload systemd early so cloud-config.service picks up the drop-in
bootcmd:
- [systemctl, daemon-reload]
package_update: false
package_upgrade: false
# Note: packages list disabled because cloud-config stage runs before DNS ready
# All package operations moved to runcmd (cloud-final stage) with DNS wait
# Repository configuration
yum_repos:
docker-ce:
name: Docker CE Stable
baseurl: https://download.docker.com/linux/fedora/$releasever/$basearch/stable
enabled: true
gpgcheck: true
gpgkey: https://download.docker.com/linux/fedora/gpg
# Commands to run
runcmd:
# Wait for DNS to be functional before continuing
- |
echo "Waiting for DNS resolution..."
for i in {1..60}; do
if getent hosts fedoraproject.org >/dev/null 2>&1; then
echo "DNS is working!"
break
fi
echo "DNS not ready, waiting... (attempt $i/60)"
sleep 2
done
- sudo dnf update -y
- sudo dnf upgrade -y
# Add Microsoft Edge repository
- sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
- sudo dnf config-manager addrepo --from-repofile='https://packages.microsoft.com/yumrepos/edge/config.repo'
# Install all packages after DNS is ready
- |
sudo dnf install -y \
vim git tmux htop btop ncdu tree curl wget unzip tar rsync \
lnav jq socat net-tools bind-utils traceroute telnet nmap tcpdump screen \
qemu-guest-agent \
gnome-extensions-app \
gnome-shell-extension-appindicator gnome-shell-extension-dash-to-dock \
xrdp xorgxrdp \
libvirt virt-manager virt-viewer \
docker-ce docker-ce-cli containerd.io docker-compose-plugin \
gcc make python3 python3-pip nodejs npm \
gnome-terminal gnome-terminal-nautilus \
nautilus nautilus-extensions \
f42-backgrounds f42-backgrounds-gnome f42-backgrounds-base \
fedora-jam-backgrounds fedora-jam-backgrounds-gnome \
fedora-workstation-backgrounds fedorainfinity-backgrounds \
desktop-backgrounds-gnome \
microsoft-edge-stable
# Install desktop environment (large group install)
- sudo dnf groupinstall -y "Workstation" "Virtualization"
# Create user directories
- mkdir -p /home/kc2user/.ssh
- mkdir -p /home/kc2user/.kube
- mkdir -p /home/kc2user/.config
- chown -R kc2user:kc2user /home/kc2user
- chmod 700 /home/kc2user/.ssh
# Import SSH keys from GitHub
- curl -fsSL https://github.com/usrbinkat.keys >> /home/kc2user/.ssh/authorized_keys
- chmod 600 /home/kc2user/.ssh/authorized_keys
- chown kc2user:kc2user /home/kc2user/.ssh/authorized_keys
# Configure QEMU guest agent
- systemctl enable qemu-guest-agent
- systemctl start qemu-guest-agent
# Configure Docker
- systemctl enable docker
- systemctl start docker
- usermod -aG docker kc2user
# Configure libvirt
- systemctl enable libvirtd
- systemctl start libvirtd
- usermod -aG libvirt kc2user
- usermod -aG kvm kc2user
- usermod -aG qemu kc2user
# Configure XRDP for GNOME
- systemctl enable xrdp
- systemctl enable xrdp-sesman
- echo "allowed_users=anybody" >> /etc/X11/Xwrapper.config
- echo "gnome-session" > /home/kc2user/.Xclients
- chmod +x /home/kc2user/.Xclients
- chown kc2user:kc2user /home/kc2user/.Xclients
# Configure firewall for XRDP
# firewall-cmd --permanent --add-port=3389/tcp
# firewall-cmd --permanent --add-port=443/tcp
# firewall-cmd --permanent --add-port=80/tcp
# firewall-cmd --permanent --add-port=22/tcp
# firewall-cmd --reload
- systemctl start xrdp
# Set default target to graphical
- systemctl set-default graphical.target
# Enable automatic login for kc2user (optional)
- |
cat > /etc/gdm/custom.conf <<EOF
[daemon]
AutomaticLoginEnable=false
AutomaticLogin=kc2user
[security]
[xdmcp]
[chooser]
[debug]
EOF
# Configure GNOME settings for kc2user
- |
sudo -u kc2user dbus-launch gsettings set org.gnome.desktop.session idle-delay 0
- |
sudo -u kc2user dbus-launch gsettings set org.gnome.desktop.screensaver lock-enabled false
# Create welcome message
- |
cat > /etc/motd <<EOF
╔═══════════════════════════════════════════════════════════╗
║ ║
║ Fedora 42 Workstation VM ║
║ with XRDP and GNOME Desktop ║
║ ║
║ User: kc2user ║
║ Pass: kc2user ║
║ ║
║ XRDP Port: 3389 ║
║ SSH Port: 22 ║
║ ║
║ RDP, Docker, Libvirt Ready ║
║ ║
╚═══════════════════════════════════════════════════════════╝
EOF
# Final status marker
- echo "$(date) - Cloud-init provisioning complete" > /root/provisioning-complete
- echo "$(date) - Cloud-init provisioning complete" > /home/kc2user/provisioning-complete
- chown kc2user:kc2user /home/kc2user/provisioning-complete
# Final message
final_message: "Fedora 42 Workstation VM provisioning complete after $UPTIME seconds"
---
# Fedora 42 Workstation VM with XRDP and GNOME Desktop
# Uses containerDisk from docker.io/containercraft/fedora:42
# Comprehensive device configuration for multi-OS compatibility
# Network: enp1s0 bridged to br0 with DHCP (enables nested virtualization)
#
# Quick Deployment (Recommended):
# ================================
# Use the deployment script to handle secrets and VM creation:
#
# ./examples/fedora/deploy.sh
#
# Or with custom SSH key and userdata files:
#
# ./examples/fedora/deploy.sh \
# --ssh-key ~/.ssh/my_custom_key.pub \
# --userdata ./my-custom-userdata.yaml \
# --vm-manifest ./my-custom-vm.yaml
#
# Manual Deployment:
# ==================
#
# 1. Create SSH public key secret for kc2user:
# kubectl create secret generic kargo-sshpubkey-kc2user \
# --from-file=key1=$HOME/.ssh/id_ed25519.pub \
# --namespace=default
#
# 2. Create cloud-init userdata secret:
# kubectl create secret generic fedora-42-userdata \
# --from-file=userdata=examples/fedora/fedora-42-userdata.yaml \
# --namespace=default
#
# 3. Verify network attachment definition exists:
# kubectl get net-attach-def br0-network-attachment
#
# 4. Deploy the VirtualMachine:
# kubectl apply -f examples/fedora/fedora-42-vdi-xrdp-gnome-br0-containerdisk.yaml
#
# 5. Monitor VM startup:
# kubectl get vm,vmi,dv,pvc
# kubectl get vmi fedora-42-xrdp-gnome -o yaml
#
# 6. Watch cloud-init progress (once VM is running):
# virtctl console fedora-42-xrdp-gnome
# # Or check logs inside VM: tail -f /var/log/cloud-init-output.log
#
# 7. Get VM IP address:
# kubectl get vmi fedora-42-xrdp-gnome -o jsonpath='{.status.interfaces[0].ipAddress}'
#
# 8. Connect via SSH:
# ssh kc2user@<VM_IP>
#
# 9. Connect via RDP:
# xfreerdp /v:<VM_IP>:3389 /u:kc2user /p:kc2user /cert:ignore
# # Or use any RDP client: rdesktop, remmina, Microsoft Remote Desktop, etc.
#
# Cleanup:
# ========
# kubectl delete vm fedora-42-xrdp-gnome
# kubectl delete pvc fedora-42-volume-vda-root
# kubectl delete dv fedora-42-volume-vda-root
# kubectl delete secret fedora-42-userdata
# kubectl delete secret kargo-sshpubkey-kc2user
#
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: fedora-42-xrdp-gnome
namespace: default
labels:
app: fedora-42-xrdp-gnome
os: fedora
version: "42"
role: workstation
annotations:
description: "Fedora 42 Workstation with XRDP and GNOME Desktop"
spec:
# Automatically start the VM
runStrategy: Always
# DataVolume for persistent root disk
dataVolumeTemplates:
- metadata:
name: fedora-42-volume-vda-root
spec:
pvc:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 64Gi
storageClassName: hostpath-provisioner
source:
registry:
url: docker://docker.io/containercraft/fedora:42
template:
metadata:
labels:
app: fedora-42-xrdp-gnome
os: fedora
version: "42"
role: workstation
annotations:
vm.kubevirt.io/os: "fedora"
spec:
# Enable SSH key injection via qemu-guest-agent
accessCredentials:
- sshPublicKey:
propagationMethod:
qemuGuestAgent:
users:
- kc2user
source:
secret:
secretName: kargo-sshpubkey-kc2user
hostname: fedora-42-xrdp-gnome
terminationGracePeriodSeconds: 30
domain:
# Machine type for modern features and compatibility
machine:
type: q35
# Firmware configuration
firmware:
uuid: f7a8b944-9559-4c4c-b7d7-6e4f3e5a9c3d
serial: fedora-42-xrdp-gnome-001
bootloader:
bios: {}
# CPU configuration: 4 cores, host-passthrough for best performance
cpu:
cores: 4
sockets: 1
threads: 1
model: host-passthrough
dedicatedCpuPlacement: false
# Clock and timer configuration
clock:
utc: {}
timer:
hpet:
present: false
pit:
tickPolicy: delay
rtc:
tickPolicy: catchup
hyperv: {}
# Memory configuration: 16GB
resources:
requests:
memory: 16Gi
devices.kubevirt.io/kvm: "1"
limits:
memory: 16Gi
# Features for modern OS support
features:
acpi: {}
apic: {}
smm:
enabled: true
# Device configuration
devices:
autoattachPodInterface: false
autoattachSerialConsole: true
autoattachGraphicsDevice: true
networkInterfaceMultiqueue: true
rng: {}
# Disk configuration
disks:
- name: root-disk
bootOrder: 1
disk:
bus: virtio
- name: cloudinitdisk
disk:
bus: virtio
# Network interface with stable MAC address
interfaces:
- name: enp1s0
bridge: {}
model: virtio
macAddress: "52:54:00:fe:d0:42"
# USB tablet for better pointer handling
inputs:
- type: tablet
bus: usb
name: tablet
# Network configuration
networks:
- name: enp1s0
multus:
networkName: br0-network-attachment
# Volume configuration
volumes:
- name: root-disk
dataVolume:
name: fedora-42-volume-vda-root
- name: cloudinitdisk
cloudInitNoCloud:
networkData: |
version: 2
renderer: NetworkManager
ethernets:
enp1s0:
dhcp4: false
dhcp6: false
bridges:
br0:
interfaces: [enp1s0]
dhcp4: true
dhcp6: true
dhcp-identifier: mac
secretRef:
name: fedora-42-userdata
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment