Golden Images with Packer
Packer is a powerful tool for automating the creation of machine images across multiple platforms. This blog post will help you set up Packer to build custom images for both x86 and ARM64 architectures.
Installation
Packer supports both x86
and arm64
architectures. We've provided an installation function that detects distro / cpu architecture and installs the appropriate packages.
source <(curl -fsSL https://raw.githubusercontent.com/michielvha/PDS/main/bash/common/software/hashicorp.sh)
install_packer
If you are not on linux or you just prefer the official installation guide you may find it here.
Creating Images with our Packer Templates
Packer Template Structure
Our Packer templates define how to build custom images. Key components include:
- Source Configuration: Specifies the base image, VM settings, and QEMU parameters
- Build Configuration: Defines provisioners for customization and post-processors for output format
- Variable Definitions: Parameters that can be customized per build
Cloud-init Configuration
The Cloud-init configuration is packed into the image as a virtual CD-ROM (ISO):y
- The
cd_files
directive specifies the path to theuser-data
andmeta-data
files. - The
cd_label
is set tocidata
, which Cloud-Init expects for NoCloud configuration. - When the VM boots, Cloud-Init reads these files to configure the instance.
Extra Provisioning Scripts
In addition to Cloud-init, we use shell scripts to perform additional customization:
- Install packages
- Configure system settings
- Set up custom motd messages
- Any other specialized configuration needed
You can use our provided scripts or create your own.
Build Instructions
To build the image:
cd build/packer/ubuntu-cloud-image/
sudo packer init
sudo packer build -var-file=variables.pkrvars.hcl .
TIP
Add the following alias to your shell config to make your life easier: alias pb='sudo packer build -var-file=variables.pkrvars.hcl .'
After running the Packer build, you'll find the final raw image in the output-$distro
directory.
Testing & Troubleshooting
Connect to image via VNC during build
If you're on a Linux system with graphical capabilities:
Install TigerVNC Viewer:
bashsudo apt-get install tigervnc-viewer # Ubuntu/Debian sudo dnf install tigervnc # Fedora
Connect to the VNC server:
bashvncviewer 127.0.0.1:5956
SSH Tunnel for Remote Shell Use
For headless environments, tunnel VNC through SSH:
Create an SSH tunnel:
bashssh -N -L 5956:127.0.0.1:5956 remote_user@remote_host
Connect via VNC locally:
bashvncviewer 127.0.0.1:5956
For Windows users: Use MobaXterm as VNC viewer.
Troubleshoot image after creation
Use QEMU to Boot Images
The way to boot the images varies slightly depending on the os architecture.
sudo qemu-system-x86_64 \
-drive file=/path/to/output-noble/ubuntu-noble.img,format=qcow2 \
-smp cores=4,sockets=1 \
-m 4G \
-net nic -net user,hostfwd=tcp::2222-:22 \
-nographic
sudo qemu-system-aarch64 -m 2048 -cpu cortex-a72 \
-M virt \
-drive file=/path/to/armbian-image.img,format=raw \
-serial mon:stdio \
-netdev user,id=user.0 \
-device virtio-net,netdev=user.0,romfile=
Shell Access via chroot
To inspect the image filesystem without booting:
Create a mount directory:
bashsudo mkdir /mnt/image
Mount the image:
bashsudo mount -o loop /path/to/your/image.raw /mnt/image
For images with multiple partitions:
bashsudo fdisk -l /path/to/your/image.img # Find partition offset # Calculate offset: start_sector * 512 sudo mount -o loop,offset=<calculated_offset> /path/to/your/image.img /mnt/image
Enter chroot environment:
bashsudo chroot /mnt/image /bin/bash
Exit and unmount:
bashexit sudo umount /mnt/image
Advanced Topics
Automating Future Builds
TODO: show extended integrations here once finished
Once you have your Packer templates configured, you can automate builds through CI/CD pipelines:
- Use GitHub Actions or Equivalent to trigger builds when configurations change
- Schedule regular builds to incorporate security updates
- Implement testing frameworks to validate image functionality