Missing files in your Packer built image? You might be skipping graceful shutdowns.

Are your files and folders missing after you run the newly created image? This is a common issue when building images with Packer. It is a widely used tool for creating machine images in a repeatable and automated way. When using the QEMU builder
to generate local or CI-friendly images, it's common to upload files with the file provisioner
and configure systems using shell provisioner
. One often overlooked but critical part of this workflow is how the virtual machine shuts down after provisioning. Without a proper shutdown, the resulting image can be unstable, incomplete, or even unbootable.
Let’s see why graceful shutdowns matter.
After provisioning completes, Packer snapshots the virtual disk to produce the final image. If the guest operating system is not properly shut down before this snapshot, you risk file system corruption, lost configuration changes, services failing to start, or persistent files missing entirely - especially those written during the final steps of provisioning. These issues often go unnoticed until the image is deployed in staging or production environments, where the consequences are far more disruptive.
By default, the shutdown_command
is set to an empty string (""
). This means Packer does not attempt a clean shutdown unless you explicitly configure one. Instead, the virtual machine is forcefully terminated, which is equivalent to abruptly cutting power on a physical machine - a common cause of data loss and image inconsistency.
To prevent this, you must define a shutdown_command
that instructs the OS to shut down safely after provisioning. This ensures that services have time to stop, file operations complete, and the system reaches a stable state before the image is captured.
Correct usage of shutdown_command
A clean shutdown requires a properly formed command with the necessary privileges, and the exact command you use depends on the operating system inside the virtual machine. Most Linux distributions support the shutdown
command, but the syntax, required privileges, and available tools can vary slightly.
Here’s a reliable example in HCL2 for a Debian/Ubuntu based image:
... shutdown_command = "echo 'packer' | sudo --stdin shutdown --poweroff now" ...
This command assumes the use of a user with password-based sudo
access. It triggers a privileged system shutdown, allowing services to stop cleanly and file buffers to flush before power-off. The --poweroff
flag ensures the machine actually powers off, which is essential for clean termination when using virtual hardware emulation. Adjust the password to match your base image setup.
If you're using a different base image - such as CentOS, RHEL, or Alpine - the shutdown binary might be located elsewhere, require different flags, or use an alternative like poweroff
or halt
. You may also need to configure sudoers
to avoid prompts or password issues during provisioning.
Always test the shutdown command interactively inside a VM before inserting it into your template. It should work silently and reliably in the automated provisioning context.
Conclusion
To sum up, graceful shutdowns are a necessary safeguard when building machine images with the QEMU builder
in Packer. Skipping this step or relying on Packer’s default behavior (which can forcibly terminate the VM) introduces the risk of unstable and corrupted images. By using a proper shutdown_command
, you ensure the system shuts down in a controlled way, preserving the integrity of the file system and producing a clean, bootable image.
This practice is simple to implement and greatly improves reliability in both development and production environments. If you're managing CI pipelines or building images for downstream automation, it's a foundational step that prevents subtle and costly failures later in the lifecycle.