I use Kernel-based Virtual Machines or KVM as my primary virtualization method in my development environment, and use cloud-init to prepare my virtual machine images. There's a variety of ways to procure cloud images, but a lot of times these registries are focused on Linux images, or hypervisor technology like VMWare or VirtualBox, and while normally useful for me at work (where I primarily work on Linux systems), I was very excited to find a well maintained site for BSD cloud images.
After downloading the image I want (in this case freebsd-13.0-zfs.qcow2
) to my image path in /var/lib/libvirt/images
, I create a project directory for my cloud-init scripts in ~/freebsd-cidata
:
instance-id: freebsd
local-hostname: freebsd
in a file called meta-data
, and in user-data
:
#cloud-config
users:
- name: root
lock_passwd: false
hashed_passwd: {PASSWD_HASH}
ssh_pwauth: true
- name: freebsd
ssh_authorized_keys:
- ssh-rsa ...
hashed_passwd: {PASSWD_HASH}
groups: wheel
ssh_pwauth: true
write_files:
- path: /usr/local/etc/sudoers
content: |
%wheel ALL=(ALL) NOPASSWD: ALL
append: true
This user-data updates the root password, creates a freebsd
user, adds that user to the wheel
group, adds its SSH public keys, and then updates the sudoers file to allow wheel
group passwordless sudo
access (common pattern in cloud images, but this can be done any way you'd like). I recommend taking a look at the cloud-init example for other options and automation you can bake into your user-data file.
For example, on my Ubuntu images, I like to do a little more that I am doing above for the selected FreeBSD image:
#cloud-config
users:
- name: ubuntu
ssh_authorized_keys:
- ssh-rsa ...
sudo: ['ALL=(ALL) NOPASSWD:ALL']
groups: sudo
shell: /bin/bash
runcmd:
- hostnamectl set-hostname $(openssl rand -hex 6)
- echo PubkeyAuthentication yes | sudo tee -a /etc/ssh/sshd_config
- echo PubkeyAcceptedKeyTypes=+ssh-rsa | sudo tee -a /etc/ssh/sshd_config
- systemctl restart ssh
write_files:
- content: |
Ubuntu 22.04 LTS \n \l
IPv4: \4{enp1s0}
path: /etc/issue
permissions: '0644'
where in this case, on Ubuntu systems, I like to generate a random hostname, things like updating SSH configuration options, and updating the console to show the IP address of the instance.
I like to use a password for the users, if you prefer only to use SSH keys, you can add a new list item for each key under ssh_authorized_keys
, but if you want to set a password as well, you can create the password hash using:
mkpasswd --method=SHA-512 --rounds=4096
and populating that value in your user-data file.
Once those files are saved, you can create the cloud-init iso:
sudo genisoimage -output /var/lib/libvirt/images/cidata-freebsd.iso -V cidata -r -J ./user-data ./meta-data
You can then, back in your /var/lib/libvirt/images
directory, proceed to create the VM, first by creating a clone of your cloud image for use on the new VM:
sudo qemu-img create -b freebsd-13.0-zfs.qcow2 -f qcow2 -F qcow2 ${your VM name}.img 80G
and then optionally using a too like virt-install to automate some of the work of using libvirt with KVM, consume both the disk image and the cloud-init ISO file along with your other VM specifications:
sudo virt-install --name=${VM_NAME} --ram=4196 --vcpus=2 --import --disk path=${VM_NAME}.img,format=qcow2 --disk path=cidata-freebsd.iso,device=cdrom --os-variant=freebsd13.0 --network bridge=br0,model=virtio --graphics vnc,listen=0.0.0.0 --noautoconsole
You can then view the spin up by running virsh list
, getting the VM ID, and attaching the console to watch for cloud-init errors, virsh console ${ID}
. The console output will contain a field like this:
/usr/local/bin/cloud-init startingCloud-init v. 21.2 running 'init' at Sat, 22 Oct 2022 19:41:45 +0000. Up 13.766839027404785 seconds.
ci-info: ++++++++++++++++++++++++++++++Net device info++++++++++++++++++++++++++++++
ci-info: +--------+------+----------------+------------+-------+-------------------+
ci-info: | Device | Up | Address | Mask | Scope | Hw-Address |
ci-info: +--------+------+----------------+------------+-------+-------------------+
ci-info: | lo0 | True | 127.0.0.1 | 0xff000000 | . | . |
ci-info: | lo0 | True | ::1/128 | . | . | . |
ci-info: | lo0 | True | fe80::1%lo0/64 | . | 0x2 | . |
ci-info: | vtnet0 | True | 192.168.0.115 | 0xffffff00 | . | 52:54:00:f4:32:c2 |
ci-info: +--------+------+----------------+------------+-------+-------------------+
ci-info:
containing your instance networking information, so you can attempt to connect via SSH (if you don't know the instance IP), or if you set a password, you can proceed to login from this console as well.
Top comments (1)
Thank you Joseph for mentioning BSD-Cloud-image.org, it's really appreciated! I would suggest to give a try to Virt-lightning which allow you to run any Cloud image locally through a simple CLI. It will handle the metadata part for you.