Vagrant Boxes from official Ubuntu Cloud Images

At some point Ubuntu stopped providing official, Vagrant Box images on their cloud image repository. Fortunately, they still provide official Virtual Box images. With a few easy steps, it's a simple matter to convert these to Vagrant Box images.

All we need to do is:

  1. Retrieve the official Virtual Appliance (OVA) file
  2. Rename the virtual machine (OVF) file to box.ovf
    a. In practice, we extract the OVF file, rename it, and then add it back to the OVA
  3. Add a metadata.json file to the OVA
  4. Import the appliance (OVA) file into Vagrant
  5. Have Vagrant add the vagrant user to the VM at the very start of the vagrant up process

Retrieve the official Virtual Appliance (OVA) file

Start by grabbing the OVF from the official, Ubuntu Cloud Image repository
curl -LO https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.ova

> curl -LO https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.ova
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
> tar --list -f noble-server-cloudimg-amd64.ova
ubuntu-noble-24.04-cloudimg.ovf
ubuntu-noble-24.04-cloudimg.mf
ubuntu-noble-24.04-cloudimg.vmdk

Rename the Virtual Machine file

tar --extract -f noble-server-cloudimg-amd64.ova ubuntu-noble-24.04-cloudimg.ovf
tar --delete -f noble-server-cloudimg-amd64.ova ubuntu-noble-24.04-cloudimg.ovf
mv ubuntu-noble-24.04-cloudimg.ovf box.ovf
tar --append -f noble-server-cloudimg-amd64.ova box.ovf
rm box.ovf

> tar --list -f noble-server-cloudimg-amd64.ova
ubuntu-noble-24.04-cloudimg.mf
ubuntu-noble-24.04-cloudimg.vmdk
box.ovf

Add a metadata.json file

echo '{ "provider": "virtualbox" }' > metadata.json
tar --append -f noble-server-cloudimg-amd64.ova metadata.json
rm metadata.json

> tar --list -f noble-server-cloudimg-amd64.ova
ubuntu-noble-24.04-cloudimg.mf
ubuntu-noble-24.04-cloudimg.vmdk
box.ovf
metadata.json

Import the box into Vagrant

vagrant box add --name noble64 ./noble-server-cloudimg-amd64.ova

> vagrant box add --vagrant box add --name noble64 ./noble-server-cloudimg-amd64.ova
==> box: Box file was not detected as metadata. Adding it directly...
==> box: Adding box 'noble64' (v0) for provider:
    box: Unpacking necessary files from: file:///example/noble-server-cloudimg-amd64.ova
==> box: Successfully added box 'noble64' (v0) for ''!
> vagrant box list
jammy64    (virtualbox, 0)
noble64    (virtualbox, 0)

Add the vagrant user on UP

This is where we take advantage of the Cloud-Init functionality in Vagrant. At the top of the box definition tree, right next to the file Vagrantfile, create user-data.yaml with the following contents:

users:
  - name: vagrant
    gecos: Vagrant User
    groups: users
    sudo: ALL=(ALL) NOPASSWD:ALL
    shell: /bin/bash
    lock_passwd: true
    ssh_authorized_keys:
      - "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key"

Then add the following line to your Vagrantfile
config.vm.cloud_init content_type: "text/cloud-config", path: "./user-data.yaml

Example

> ls
Config/  README.md  Vagrantfile  user-data.yaml

> cat Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure('2') do |config|
  config.vm.box = 'noble64'

  config.vm.cloud_init content_type: "text/cloud-config", path: "./user-data.yaml"

  config.vm.provider 'virtualbox' do |v|
    v.customize [ 'modifyvm', :id, '--cpus', '2' ]
    v.customize [ 'modifyvm', :id, '--memory', '4096' ]
    v.customize [ 'modifyvm', :id, '--graphicscontroller', 'vmsvga' ]
    v.customize [ 'modifyvm', :id, '--vram', '22' ]
  end

  config.vm.hostname = 'noble'
  config.vm.network 'private_network', type: 'dhcp'

  config.vm.provision :shell, path:   'Config/SetAuthKey.sh'
end

Bring up the Vagrant Box

That's all there is to it. Now just vagrant up

> vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'noble64'...
==> default: Generating MAC address for NAT networking...
==> default: Setting the name of the VM: Noble_default_1720918230504_59569
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
    default: Adapter 2: hostonly
==> default: Forwarding ports...
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Preparing user data for cloud-init...
==> default: Configuring storage mediums...
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Connection reset. Retrying...
    default:
    default: Vagrant insecure key detected. Vagrant will automatically replace
    default: this with a newly generated keypair for better security.
    default:
    default: Inserting generated public key within guest...
    default: Removing insecure key from the guest if it's present...
    default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
==> default: Waiting for cloud init to finish running
==> default: Checking for guest additions in VM...
    default: The guest additions on this VM do not match the installed version of
    default: VirtualBox! In most cases this is fine, but in rare cases it can
    default: prevent things such as shared folders from working properly. If you see
    default: shared folder errors, please make sure the guest additions within the
    default: virtual machine match the version of VirtualBox you have installed on
    default: your host and reload your VM.
    default:
    default: Guest Additions Version: 6.0.0 r127566
    default: VirtualBox Version: 7.0
==> default: Setting hostname...
==> default: Configuring and enabling network interfaces...
==> default: Mounting shared folders...
    default: /vagrant => /example/Vagrant/Noble
==> default: Running provisioner: shell...
    default: Running: /tmp/vagrant-shell20240713-719922-97lcvr.sh

> vagrant ssh
Welcome to Ubuntu 24.04 LTS (GNU/Linux 6.8.0-36-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of Sun Jul 14 00:59:50 UTC 2024

  System load:  0.33              Processes:               121
  Usage of /:   16.7% of 8.65GB   Users logged in:         0
  Memory usage: 4%                IPv4 address for enp0s3: 10.0.2.15
  Swap usage:   0%


Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


vagrant@noble:~$ sudo su -
root@noble:~#