Hashicorp makes some cool tools for playing in the cloud or a virtualized environment, especially if you want to build out an Infrastructure as Code approach and make infrastructure updates a CI process. Packer is a tool that let’s you define a server - OS, cores, storage, packages, and all - in a script that can be built on demand. You can even define your environment, like LAMP, in the packer script and load your application files.
A very practical use of Packer would be to use it to build a custom AWS AMI for your company. You want every EC2 instance to look like this image, so it might include security settings or agents, centralized logging setup, connections to centralized authentication, and other common resources. I would probably load any required data files when the EC2 instance is instantiated, maybe through Cloud Formation.
Packer scripts are written in HCL (Hashi Corp Language? Dunno.), which ends up looking like YAML.
I built a Packer repo that builds a simple Ubuntu server for VMWare Workstation. It should be simple enough to customize this, including having it output an AWS AMI (Amazon Machine Image). It is tested and works with Pop! 22.04 with a 5.19 kernel and VMWare Workstation 16.2.4.
The packer file (custom.pkr.hcl in my example) can be broken into three parts. The first section defines the virtual machine, including the installation media and the CD image with customization steps. It looks like this:
source “vmware-iso” “jammy-development” { iso_urls =[ “file:/media/brent/Ventoy/ubuntu-22.04.1-live-server-amd64.iso”, “https://releases.ubuntu.com/22.04.1/ubuntu-22.04.1-live-server-amd64.iso”] iso_checksum = “sha256:10f19c5b2b8d6db711582e0e27f5116296c34fe4b313ba45f9b201a5007056cb” iso_target_path = “/media/brent/Ventoy” version = “16” memory = 4096 cd_files = [ “./http/meta-data”, “./http/user-data”] cd_label = “cidata” cpus = 1 cores = 2 disk_type_id = 0 network = “nat” network_adapter_type = “vmxnet3” vm_name = “Ubuntu2204-dev” ssh_username = “vmadmin” ssh_password = “Password” shutdown_command = “sudo shutdown -P now”
Ubuntu can be booted into an autoinstall script (“user-data” in this example). Typically the way this is done is by placing a file (user_data in this case) into the http folder. Packer makes that folder available through a local Apache installation. However, I could not get the VM to “see” the website and draw down the file. I tried several iterations of network configuration to no avail. One other approach I took was to take the auto-install files and place them in an ISO image, then attaching the image to the VM. To do this, I installed the cloud utilities from Ubuntu. I used cloud-localds to put the two data files into a small ISO.
sudo apt install cloud-image-utils cloud-localds ./seed.iso user-data meta-data
Later I discovered that this can be done in the packer specification:
cd_files = [ “./http/meta-data”, “./http/user-data”] cd_label = “cidata”
The second part of the packer file describes how to interact with the server as it boots. You can actually specify and and walk through an entire installation wizard. With Ubuntu, I found that to be fragile. As I made changes to the network to try to get it to see the local webserver, the installation prompts changed and broke the sequence. Instead of walking through the wizard, this script boots into the custom setup and tells it to load the autoinstall script from the CD-image.
boot_wait = "5s"
boot_command = [
"c<wait>",
"linux /casper/vmlinuz ds=nocloud-net s=/cidata",
"<enter>",
"initrd /casper/initrd",
"<enter>",
"boot<enter><wait60>",
"yes<wait120>"
]
} boot_wait = “5s” boot_command = [ “c”, “linux /casper/vmlinuz ds=nocloud-net s=/cidata”, “”, “initrd /casper/initrd”, “”, “boot”, “yes” ] }
The third piece is the autoinstall script (user-data). This describes some of the setup attributes, like keyboard, and the initial set of packages to be loaded.
autoinstall:
version: 1 apt: geoip: true disable_components: [] preserve_sources_list: false primary: - arches: [amd64, i386] uri: http://us.archive.ubuntu.com/ubuntu - arches: [default] uri: http://ports.ubuntu.com/ubuntu-ports early-commands: - sudo systemctl stop ssh locale: en_US keyboard: layout: us identity: hostname: jammy-daily username: vmadmin password: $6$Da/Bin6we2OOJCVD$HM00JdEP47D.cVfSYzwf71khVHPD8NqbYLGw/iXPswndEqI2TNsMELWRCt0tA2.mVMPjFZlPI0B/xOBO9OhF01 ssh: install-server: true allow-pw: true packages: - openssh-server - open-vm-tools - cloud-init - whois - zsh - wget - tasksel user-data: disable_root: false timezone: UTC late-commands: - sed -i -e ’s/^#?PasswordAuthentication.*/PasswordAuthentication yes/g’ /target/etc/ssh/sshd_config - echo ‘vmadmin ALL=(ALL) NOPASSWD:ALL’ > /target/etc/sudoers.d/vmadmin - curtin in-target –target=/target – chmod 440 /etc/sudoers.d/vmadmin - “lvresize -v -l +100%FREE /dev/mapper/ubuntu–vg-ubuntu–lv” - “resize2fs -p /dev/mapper/ubuntu–vg-ubuntu–lv”
My repo is linked and you can grab the original files there and build on them. Packer is free and open-source and works with a variety of local and cloud backends, including VMWare, VirtualBox, HyperV, KVM, and AWS. This is an easy way to produce repoducable server environments and treat your servers like “cattle not cats”.