Skip to main content
Version: v4 (current)

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 wget

    export 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 rsa
  • Create 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.yaml
  • Create 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 runner to 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_PORT to connect to the VM.