Skip to main content

HashiCorp Packer with Virtualbox (Autoinstall)

TST, Hong Kong

Preparation

We’re using the new AutoInstall method for Ubuntu 20.04. Previous versions use debian-installer preseeding, but that method didn’t immediately work with the new ISO. You must also set the http_directory configuration option to specify which directory on your filesystem hosts the files you want the HTTP server to serve. We have a directory called ubuntu-20.04 within that directory, and that in turn contains a user-data file which contains our AutoInstall config. I also found that AutoInstall expects a file called meta-data to be present, although it doesn’t require any content so I simply have an empty file called meta-data alongside user-data.

Our user-data file looks like this

#cloud-config
autoinstall:
  version: 1
  apt:
    geoip: true
    preserve_sources_list: false
    primary:
    - arches: [amd64, i386]
      uri: http://gb.archive.ubuntu.com/ubuntu
    - arches: [default]
      uri: http://ports.ubuntu.com/ubuntu-ports
  identity:
    hostname: ubuntu2004
    username: vagrant
    password: <encrypted password>
  ssh:
    allow-pw: true
    install-server: true
  locale: en_US
  keyboard: 
    layout: gb
  storage:
    layout:
      name: direct
    config:
      - type: disk
        id: disk0
        match:
          size: largest
      - type: partition
        id: boot-partition
        device: disk0
        size: 500M
      - type: partition
        id: root-partition
        device: disk0
        size: -1
  late-commands:
    - "echo 'Defaults:vagrant !requiretty' > /target/etc/sudoers.d/vagrant"
    - "echo 'vagrant ALL=(ALL) NOPASSWD: ALL' >> /target/etc/sudoers.d/vagrant"
    - "chmod 440 /target/etc/sudoers.d/vagrant"

Note that the vagrant bits are somewhat unique to us. We create a user called vagrant as part of the install. That’s so we can use this image as a vagrant box later on. Note also at the end that we add vagrant to the sudo config and ensure that it doesn’t require a password to run sudo commands. This ensures that when the image is used in vagrant, it doesn’t prompt for a password before running a command with root privileges.

Then we come to the provisioners. For this base image, we run two scripts, one to update all the packages, and the other cleans up a few things:

apt.sh

sudo apt-get update
sudo apt upgrade -y
sudo apt install apt-transport-https -y

cleanup.sh

sudo apt-get clean
FILE=/etc/cloud/cloud.cfg.d/50-curtin-networking.cfg
if test -f "$FILE"; then
  sudo rm $FILE
fi

FILE=/etc/cloud/cloud.cfg.d/curtin-preserve-sources.cfg
if test -f "$FILE"; then
  sudo rm $FILE
fi

FILE=/etc/cloud/cloud.cfg.d/subiquity-disable-cloudinit-networking.cfg
if test -f "$FILE"; then
  sudo rm $FILE
fi

Template File

{
  "builders": [
    {
      "type": "virtualbox-iso",
      "vboxmanage": [
        [ "modifyvm", "{{.Name}}", "--memory", "{{ user `ram` }}" ],
        [ "modifyvm", "{{.Name}}", "--vram", "36" ],
        [ "modifyvm", "{{.Name}}", "--cpus", "{{ user `cpus` }}" ]
      ],
      "guest_os_type": "Ubuntu_64",
      "disk_size": "{{ user `virtualbox_disk_size` }}",
      "headless": "{{ user `headless` }}",
      "iso_url": "{{ user `iso_url` }}",
      "iso_checksum": "{{ user `iso_checksum` }}",
      "iso_checksum_type": "sha256",
      "vm_name": "ubuntu-2004",
      "boot_command": [
        " <wait><enter><wait>",
        "<f6><esc>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs><bs><bs><bs><bs><bs><bs><bs>",
        "<bs><bs><bs>",
        "/casper/vmlinuz ",
        "initrd=/casper/initrd ",
        "autoinstall ",
        "ds=nocloud-net;s=http://{{.HTTPIP}}:{{.HTTPPort}}/ubuntu-20.04/ ",
        "<enter>"
      ],
      "boot_wait": "5s",
      "http_directory": "../scripts/ubuntu/http",
      "shutdown_command": "sudo systemctl poweroff",
      "ssh_password": "vagrant",
      "ssh_port": 22,
      "ssh_username": "vagrant",
      "ssh_timeout": "10000s",
      "ssh_handshake_attempts": "30",
      "guest_additions_mode": "disable",
      "format": "ova"
    }
  ],
  "provisioners": [
      {
        "type": "shell",
        "execute_command": "echo 'vagrant' | {{.Vars}} sudo -S -E sh -eux '{{.Path}}'",
        "scripts": [
            "../scripts/ubuntu/apt.sh",
            "../scripts/ubuntu/cleanup.sh"
        ]
      }
  ],
  "variables": {
    "headless": "true",
    "iso_checksum": "<Checksum of ISO using the algorithm specified in iso_checksum_type above>",
    "iso_url": "<URL to ISO>",
    "version": "0",
    "ram": "2048",
    "cpus": "2",
    "virtualbox_disk_size": "8192",
    "vmware_disk_size": "8291"
  }
}