To customize your virtual machine images, such as running terminal scripts,
updating boot parameters, transferring binaries, or installing GPU drivers, you
can define specific helper actions inside the spec.steps block of your
customization recipe (imagebuilder.yaml).
Overview
During the execution phase of an Image Builder build, the
orchestrator runs the steps declared in your customization recipe (spec.steps)
sequentially on the temporary worker VM.
Each step must specify a name, an action, and an inputs block tailored to
that action type. Image Builder supports the following
customization actions:
Shell: Executes inline terminal scripts or commands on the worker guest OS.UpdateKernelCommandLine: Modifies boot parameters and kernel command-line flags.FileCopy: Transfers configuration files, scripts, or assets from Cloud Storage or local workspaces onto the VM.InstallGPU: Downloads, compiles, and registers NVIDIA GPU drivers.
Shell action
The Shell action lets you execute inline terminal scripts or single shell
commands on the guest OS of the temporary worker VM to perform customizations
like updating packages, configuring user accounts, or compiling software.
Specify either of the following inputs under steps.inputs:
inlineScript(string): Raw multiline shell commands to execute.command(string): A single system command string or relative path to a binary file executable.
Sample configurations
The following tabs show sample step configurations for running an inline script versus running a single command:
Run an inline script
The following configuration runs a multiline script that updates packages
using apt:
- name: "Update guest packages and configure groups"
action: Shell
inputs:
inlineScript: |
#!/bin/bash
apt-get update -y
apt-get install -y fail2ban build-essential
groupadd -r adminusers
Run a single command
The following configuration runs a single shell command to verify the active operating system kernel version:
- name: "Log kernel identifier"
action: Shell
inputs:
command: "uname -a"
Special behaviors
When you run Shell actions, the customization provisioner manages security auditing
and automated system reboots as described in the following sections:
Security auditing
To prevent sensitive tokens, secrets, or proprietary code from leaking into
execution logs, the customization provisioner doesn't print the raw lines of your
scripts unless interactive debugging is enabled (debug: true). Instead, it logs the SHA-256 integrity hash of your script
payload to the build logs. This hash provides an immutable audit trace of exactly
what code ran on the image.
System reboots (Exit Code 3010)
Some shell actions, such as kernel patch updates or storage partition adjustments, require a system reboot before subsequent steps can run.
To request a system reboot during customization, your shell script must end with
the command exit 3010. When the customization provisioner receives exit code 3010,
it handles the reboot lifecycle as follows:
- The provisioner detects exit code
3010, pauses execution, and marks the step progress index. - The provisioner reboots the worker VM.
- After the VM restarts, the provisioner mounts the workspace and automatically resumes the pipeline at the next step in the queue.
Reboot example:
The following example shows a step configuration that updates packages and requests a reboot:
- name: "Install core updates and request reboot"
action: Shell
inputs:
inlineScript: |
#!/bin/bash
echo "Applying configuration package upgrades..."
apt-get dist-upgrade -y
# Terminate with return code 3010 to trigger a system reboot
exit 3010
- name: "Post-reboot verification"
action: Shell
inputs:
command: "uname -r"
UpdateKernelCommandLine action
The UpdateKernelCommandLine action locates, replaces, inserts, or removes
command-line flags passed to the kernel at system boot, such as when you
configure console logs or adjust kernel parameters.
Specify the following properties under the steps.inputs map:
oldArguments(string, Required): The exact command-line arguments to locate, remove, or replace inside the bootloader config.newArguments(string, Optional): The replacement arguments to write in place of the target flags. If you omit thenewArgumentsproperty, Image Builder removes the parameters configured in theoldArgumentsproperty entirely from the boot line.
Sample configurations
The following tabs show sample step configurations for replacing or removing kernel boot arguments:
Replace boot arguments
The following configuration locates the kernel log level key loglevel=4
and replaces it with more verbose parameters loglevel=6 console=ttyS0:
- name: "Configure detailed boot logging"
action: UpdateKernelCommandLine
inputs:
oldArguments: "loglevel=4"
newArguments: "loglevel=6 console=ttyS0"
Remove boot arguments
The following configuration searches for the parameter quiet and removes
it from the boot arguments to enable verbose logging during startup check
phases:
- name: "Enable verbose startup diagnostics"
action: UpdateKernelCommandLine
inputs:
oldArguments: "quiet"
OS-specific execution details
The following tabs describe how the customization provisioner handles image modifications depending on the source guest operating system:
Container-Optimized OS (COS)
Because COS features a read-only partition layout, it omits standard configuration tools. The customization provisioner does the following:
- Determines the active boot device path.
- Mounts partition 12, the EFI partition, of the boot device.
- Directly updates bootloader parameters inside
/efi/boot/grub.cfg. - Safely unmounts partition 12.
Ubuntu
On Ubuntu images, the customization provisioner does the following:
- Opens
/etc/default/gruband files under/etc/default/grub.d/*.cfg. - Inserts, modifies, or deletes the target arguments under the
GRUB_CMDLINE_LINUXblock. - Runs the package command
update-grubto regenerate the bootloader configurations.
FileCopy action
The FileCopy action copies configuration files, binaries, or certificates from
a remote bucket or your local repository to your custom image. The customization
provisioner downloads or reads the source file, writes it to your specified guest path
on the worker VM, and configures the permissions.
Specify the following inputs under steps.inputs:
destination(string, Required): The absolute path in the guest OS where the file is created.permissions(string, Required): The octal representation of the target configuration permissions, such as"0755"or"0644".- Specify either of the following source properties:
gcsSourcePath(string): The Cloud Storage URI of the source file, which must follow the formatgs://BUCKET_NAME/OBJECT_NAME.localSourcePath(string): The relative path to the file inside the local workspace repository folder. Path traversal using../is blocked for security.
Sample configurations
The following tabs show sample step configurations for copying a file from Cloud Storage versus copying from your local workspace:
Cloud Storage
The following configuration copies a configuration template from a Cloud Storage bucket onto the guest VM image:
- name: "Import licensing configuration"
action: FileCopy
inputs:
gcsSourcePath: "gs://enterprise-configs-bucket/licensing/license.key"
destination: "/etc/app/license.key"
permissions: "0600"
Local workspace
The following configuration copies an application script compiled during previous Cloud Build steps:
- name: "Deploy setup automation daemon"
action: FileCopy
inputs:
localSourcePath: "bin/setup-daemon"
destination: "/usr/local/bin/setup-daemon"
permissions: "0755"
OS-specific guidelines
The following tabs describe file location guidelines depending on the target guest operating system:
Container-Optimized OS (COS)
COS images contain a read-only partition layout for security purposes. Some
standard system targets, such as /usr/ or /bin/, are write-protected.
When configuring file destinations on COS:
- Specify files only inside writable stateful locations, such as
/varor/home. - Refer to the official Container-Optimized OS Disks and file system reference to identify appropriate paths.
Ubuntu
Ubuntu images feature a standard Linux read-write root partition layout (/).
You can specify file destinations inside any standard system path, such as
/etc, /usr/local/bin, /var, or /home, provided the user profile or
destination folder has appropriate configuration permissions on the worker VM.
InstallGPU action
Use the InstallGPU action to build VM images optimized for machine learning,
data science, or scientific workloads. Image Builder downloads,
compiles, and registers NVIDIA GPU drivers on your custom images. Depending on
your base image type and target hardware, you can choose between installing
precompiled drivers or compiling custom driver .run files.
Specify one of the following inputs under steps.inputs:
version(string): The target NVIDIA driver version number, such as"595.129.03". If you specify onlyversion, the orchestrator downloads the driver from the official NVIDIA repository (https://us.download.nvidia.com/tesla/<version>).gcsRunfile(string): The Cloud Storage path of a custom NVIDIA driver installer file, which must use the formatgs://BUCKET_NAME/OBJECT_NAME.run.sourceRunfile(string): The relative path to an installer.runfile inside the local workspace repository folder.
Sample configurations
The following tabs show sample step configurations for installing a specific pre-packaged driver version versus installing a custom runfile:
Standard version download
The following configuration downloads and installs a specified NVIDIA driver version from the official repository:
- name: "Configure default NVIDIA drivers"
action: InstallGPU
inputs:
version: "<var>DRIVER_VERSION</var>"
Cloud Storage runfile
The following configuration deploys a custom NVIDIA driver .run installer directly from a Cloud Storage bucket:
- name: "Deploy custom GPU driver from Cloud Storage"
action: InstallGPU
inputs:
gcsRunfile: "gs://<var>BUCKET_NAME</var>/drivers/NVIDIA-Linux-aarch64-<var>DRIVER_VERSION</var>.run"
Local workspace runfile
The following configuration deploys a custom NVIDIA driver .run installer from your local repository workspace:
- name: "Deploy custom GPU driver from workspace"
action: InstallGPU
inputs:
sourceRunfile: "drivers/NVIDIA-Linux-x86_64-<var>DRIVER_VERSION</var>.run"
Configuration methods
The following tabs describe the supported methods for configuring NVIDIA GPU drivers on your custom images:
Precompiled drivers
We recommend using pre-packaged driver versions to avoid the compute overhead and build time of compiling drivers from scratch.
Container-Optimized OS (COS): If you specify a driver version pre-packaged by Google, the customization provisioner runs the guest tool
cos-extensions install gputo activate it.To see the list of supported precompiled driver versions for your COS release, run
sudo cos-extensions liston a running COS instance, or refer to Identify the GPU driver version.Ubuntu: To save build time on Ubuntu, we recommend selecting pre configured base images from the public
ubuntu-os-accelerator-imagesproject where NVIDIA drivers are preinstalled.To list available accelerator images, run the following command in the
gcloudCLI:gcloud compute images list \ --project=ubuntu-os-accelerator-images \ --no-standard-images
Custom runfiles
If you must install a custom driver version that isn't precompiled by Google or Canonical, you can specify direct installer run files for compilation as follows:
- Ubuntu: Performs in-guest compilation. The customization provisioner
automatically installs the matching kernel headers
(
linux-headers-$(uname -r)), compiles the NVIDIA driver.runfile on the worker VM, and registers it with Dynamic Kernel Module Support (DKMS). Registering with DKMS ensures the drivers remain active across minor kernel updates. - Container-Optimized OS (COS): The compilation behavior varies
depending on the CPU architecture of your source base VM image:
- ARM64 Images: Because ARM64 COS VMs don't support in-guest header
compilation, Image Builder automatically cross-compiles
your custom driver
.runutility inside the build container and installs the resulting bundle into/var/lib/nvidiaon the worker VM. - x86-64 Images: Performs in-guest compilation directly on the worker VM.
- ARM64 Images: Because ARM64 COS VMs don't support in-guest header
compilation, Image Builder automatically cross-compiles
your custom driver
What's next
- Review top-level schema blocks in the Image customization file schema.
- Configure pipeline orchestration parameters in the Cloud Build configuration file schema.
- Follow the tutorial to Create an Image Builder pipeline.