Intro

I have wanted to give VyOS a try for my home lab routing/firewall for some time. I have a Proxmox cluster to host all my VMs, and ideally, I would like to run VyOS as a VM.

Proxmox support qemu images, but the VyOS project only provides pre-built images to subscribers. Luckily, they make it pretty easy to build your own images and in this post, I will show you how to build a VyOS Qemu image.

Software Versions

The following software versions were used in this post.

  • Debian - 12 (Bookworm)
  • Python - 3.11.2
  • pip - 23.0.1
  • ansible - 6.7.0
  • ansible core - 2.13.11
  • VyOS - 1.4-rolling-202309070021

Build Machine

To build the image, I deployed a new Debian 12 (Bookworm) VM. There are a couple of pre-flight steps required before we can build our VyOS Qemu image.

Note
All work is performed from the /tmp/ directory.

ISO Download

VyOS IOS's are built at least once a day from the current git branch and are availalable here

Note
Although these are nightly builds, I have heard from multiple sources that they are very stable and any bugs are fixed very quickly. My first choice would be an LTS version, so I will see how this goes.

Use curl to download the desired ISO to the build VM.

cmd
curl -OL https://github.com/vyos/vyos-rolling-nightly-builds/releases/download/1.4-rolling-202309070021/vyos-1.4-rolling-202309070021-amd64.iso

Install PIP

Install PIP for Python3 as we will use this to install Ansible.

cmd
sudo apt install -y python3-pip

Install Ansible

The ansible version 7.3.0+dfsg-1 from apt fails with the following error:

error
TASK [install-grub : Mount and bind /dev /proc /sys and /mnt/wroot/boot to /mnt/inst_root] *****************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (ansible.legacy.command) module: warn. Supported parameters include: _raw_params, _uses_shell, argv, chdir, creates, executable, removes, stdin, stdin_add_newline, strip_empty_ends."}

I was unable to install a version that worked via apt so I am installing it via pip instead.

cmd
sudo pip install ansible==6.7.0 --break-system-packages
Note
I am installing ansible into the system version of python so --break-system-packages is required. This didn't break anything, but it is not really advisable to alter the system python packages. Alternatively, you could use a virtual environment.

Build Image

The VyOS team helpfully makes an Ansible git repo available to build the various images. We will use this to build our qemu image.

Git Repository

Get a copy of the Git repo by cloning it locally.

cmd
git clone https://github.com/vyos/vyos-vm-images.git

Change into directory

cmd
cd vyos-vm-images

Ansible

The Ansible playbook tries to download an ISO as part of the build process. That step fails with the following error:

error
TASK [download-iso : Download VyOS ISO release] ************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "dest": "/home/bradmin/vyos-1.4-rolling-202309070021-amd64-1.iso", "elapsed": 0, "msg": "Request failed", "response": "HTTP Error 403: Forbidden", "status_code": 403, "url": "https://s3.amazonaws.com/s3-us.vyos.io/rolling/current/vyos-rolling-latest.iso"}

This is why we downloaded the ISO locally so we don't need it to perform this task. Let's comment out the download-iso role in the qemu.yml file.

qemu.yml
- install-packages
# - download-iso
- mount-iso

Now run the playbook to build the image.

cmd
sudo ansible-playbook qemu.yml \
   -e disk_size=10 \
   -e iso_local=/tmp/vyos-1.4-rolling-202309070021-amd64.iso \
   -e grub_console=serial \
   -e cloud_init=true \
   -e cloud_init_ds=NoCloud \
   -e guest_agent=qemu \
   -e enable_ssh=true

This will build a qemu image with cloud-init enabled and save it to the /tmp/ directory.

You can now use the image as a base to deploy VMs. I used SCP to transfer the image to my Proxmox hosts and will cover the process to deploy VMs from the image in a future post.

Outro

In this post, I showed you how to build a VyOS qemu image from the nightly ISO via ansible. If you have the same/similar goals that I did, I hope this post helped get you there faster than I did.