Linux (Cloud-Image)
Cloud-Images are lightweight (usually under 700Mb) snapshots of a configured OS created by a publisher for use with public and private clouds. These images provide a way to repeatably create identical copies of a machine across platforms. Cloud-Image based systems are best used for ephemeral or immutable workloads and then discarded after each run. We will use Cloud-Init to customize the cloud-image immediately upon booting, prior to user-space initialization.
Download a Cloud-Image
Choose a cloud-image to use as the base OS:
Debian:
12: 'https://laotzu.ftp.acc.umu.se/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2'
Ubuntu:
jammy: 'https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img'Download the image with
wgetexport CLOUD_IMAGE_URL="https://laotzu.ftp.acc.umu.se/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2"
export CLOUD_IMAGE_NAME=$(basename -- "$CLOUD_IMAGE_URL")
wget -c -O "$CLOUD_IMAGE_NAME" "$CLOUD_IMAGE_URL" -q --show-progress
VM Setup
Configure VM options
# The name of the Virtual Machine
export VM_NAME="gameci"
# The name of the user to create
export VM_USER="vmadmin"
# Number of physical CPU cores to allocate to the VM
export PHYSICAL_CORES="2"
# Number of threads per core.
# Set this to `1` for CPUs that do not support hyper-threading
export THREADS="1"
export SMP=$(( $PHYSICAL_CORES * $THREADS ))
# Amount of Disk Space to allocate to the VM.
# Cannot exceed available on host.
export DISK_SIZE="32G"
# Amount of RAM to allocate to the VM.
# Cannot exceed available RAM on host.
export MEMORY="8G"
# IP address where host may be reached. Do not use `localhost`.
export HOST_ADDRESS="SOME IP HERE"
# Port used by SSH on the host
export HOST_SSH_PORT="22"
# Port to use when forwarding SSH to the VM
export VM_SSH_PORT="1234"
# Port number to expose on the host for VNC
export VNC_PORT="0"
Credentials
Create an SSH Key
yes |ssh-keygen -C "$VM_USER" \
-f runner \
-N '' \
-t rsaCreate a password
# Install the mkpasswd utility
sudo apt install -y whois
read PW_STRING
export PASSWORD=$(mkpasswd -m sha-512 --rounds=4096 "$PW_STRING" -s "saltsaltlettuce")
Cloud-init Config
Create a Cloud-Init file
See the Cloud-Init official docs for more information about Cloud-Init. More advanced templates are available in the Host Provisioning directory.
VM_KEY=$(cat runner.pub)
/bin/cat << EOF > cloud-init.yaml
#cloud-config
hostname: runner
disable_root: false
network:
config: disabled
users:
- name: ${VM_USER}
groups: users, admin, sudo
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
lock_passwd: false
passwd: ${PASSWORD}
ssh_authorized_keys:
- ${VM_KEY}
EOF
Disks
Create a Cloud-Init disk
cloud-localds seed.img cloud-init.yamlCreate a virtual disk using the cloud-image as a read-only backing file.
qemu-img create -b ${CLOUD_IMAGE_NAME} -f qcow2 \
-F qcow2 disk.qcow2 \
"$DISK_SIZE" 1> /dev/null
Create the VM
New guest
sudo qemu-system-x86_64 \
-machine accel=kvm,type=q35 \
-cpu host \
-smp $SMP,sockets=1,cores="$PHYSICAL_CORES",threads="$THREADS",maxcpus=$SMP \
-m "$MEMORY" \
-serial stdio -vga virtio -parallel none \
-device virtio-net-pci,netdev=network \
-netdev user,id=network,hostfwd=tcp::"${VM_SSH_PORT}"-:"${HOST_SSH_PORT}" \
-object iothread,id=io \
-device virtio-blk-pci,drive=disk,iothread=io \
-drive if=none,id=disk,cache=none,format=qcow2,aio=threads,file=disk.qcow2 \
-drive if=virtio,format=raw,file=seed.img,index=0,media=disk \
-bios /usr/share/ovmf/OVMF.fd \
-usbdevice tablet \
-vnc "$HOST_ADDRESS":"$VNC_PORT"Boot existing guest
sudo qemu-system-x86_64 \
-machine accel=kvm,type=q35 \
-cpu host \
-smp $SMP,sockets=1,cores="$PHYSICAL_CORES",threads="$THREADS",maxcpus=$SMP \
-m "$MEMORY" \
-serial stdio -vga virtio -parallel none \
-device virtio-net-pci,netdev=network \
-netdev user,id=network,hostfwd=tcp::"${VM_SSH_PORT}"-:"${HOST_SSH_PORT}" \
-object iothread,id=io \
-device virtio-blk-pci,drive=disk,iothread=io \
-drive if=none,id=disk,cache=none,format=qcow2,aio=threads,file=disk.qcow2 \
-bios /usr/share/ovmf/OVMF.fd \
-usbdevice tablet \
-vnc "$HOST_ADDRESS":"$VNC_PORT"
Connect to the VM
Connect over SSH
Copy the ssh private key
runnerto the machine you wish to connect to the VM with.Connect to the VM using the format
ssh -i runner $VM_USER@$HOST_ADDRESS -p$VM_SSH_PORT
Connect using VNC
In your VNC software use the address format
$HOST_ADDRESS:$VNC_PORTto connect to the VM.