Create Anaconda updates.img and Use inst.updates on RHEL 8–10

Tested on Rocky Linux 10.2 (Red Quartz)
Package lorax 40.5.15
cpio 2.15
pigz 2.8.
Applies to RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora
Privilege sudo or root
Scope Create Anaconda updates.img on RHEL 8–10, embed it in boot media with mkksiso, load it with inst.updates, and verify the installer overlay.
Related guides RHEL Image Builder
Kickstart
initrd.img update and rebuild guide
custom RHEL ISO guide
Kickstart PXE boot server guide

updates.img is a compressed CPIO archive whose files are added to or replace matching paths in the Anaconda installer runtime. It is mainly useful for testing installer fixes, loading Anaconda add-ons, injecting installer configuration, and troubleshooting installation-time behavior.

This guide covers RHEL 8, 9, and 10 and equivalent Anaconda-based Enterprise Linux installers on Rocky Linux, AlmaLinux, and CentOS Stream. Production overlays also include patched Python modules, D-Bus service files, and /etc/anaconda/conf.d/ snippets when you need real installer customization beyond a harmless test marker.


updates.img, product.img, initrd.img, and Kickstart compared

Method Main purpose Loaded when Typical content
updates.img Apply temporary updates to the Anaconda runtime Installer startup Anaconda add-ons, Python files, D-Bus files, configuration and test fixes
product.img Package installer product customization From images/ on boot media Branding, product configuration, add-ons and installer files
initrd.img Provide the early boot and installer environment Before Anaconda starts Drivers, dracut modules and early-boot files
Kickstart Automate installation choices Read by Anaconda Storage, packages, users, networking and post-install actions
Image Builder Produce supported customized RHEL media or images Before deployment Packages, configuration and image composition

This article focuses on updates.img. product.img uses a similar overlay layout but is a separate packaging workflow with its own .buildstamp expectations. A basic updates.img does not need .buildstamp.

IMPORTANT
Red Hat documents direct Anaconda customization, including updates.img and product.img, but supports installation-media customization through RHEL Image Builder. Use Kickstart for repeatable installation configuration whenever installer-runtime modification is not required.

Do not rebuild initrd.img when the change only needs to overlay the Anaconda runtime. For driver and early-boot changes, see the initrd.img update and rebuild guide. Do not use updates.img for changes that belong in Kickstart or the installed operating system.


How Anaconda applies updates.img

When Anaconda starts, it locates updates.img, extracts the compressed CPIO archive, and places files over matching paths in the installer runtime. New files become available to Anaconda during that installation only. The overlay does not automatically copy those files onto the target system under /mnt/sysroot.

The archive must reproduce the exact installer-runtime path. The installer environment is not the same as the target root that will be installed.

Intended installer path Path inside the working directory
/etc/anaconda/conf.d/99-custom.conf ./etc/anaconda/conf.d/99-custom.conf
/usr/share/anaconda/addons/example/ ./usr/share/anaconda/addons/example/
/usr/share/anaconda/dbus/services/example.service ./usr/share/anaconda/dbus/services/example.service

Red Hat still documents updates.img on RHEL 10, including HTTP, local disk or USB, installation-tree discovery, and embedding with mkksiso -u on releases that ship a current Lorax build.


Prepare the build environment

Install the packaging tools on a RHEL-family build host. Rocky Linux 10.2 ships them in the standard repositories.

bash
sudo dnf install cpio pigz lorax

Confirm the packages are present before you create the archive.

bash
rpm -q cpio pigz lorax

Sample output:

output
cpio-2.15-3.el10.x86_64
pigz-2.8-7.el10.x86_64
lorax-40.5.15-1.el10.rocky.0.4.x86_64

cpio creates the archive, pigz compresses it, and lorax provides mkksiso for ISO embedding. gzip works when pigz is unavailable; pick one compressor and use it consistently in the procedure.

Create a clean workspace separate from unrelated initrd experiments.

bash
mkdir -p ~/anaconda-updates/work
cd ~/anaconda-updates/work

Keep the source boot ISO outside the working tree, for example:

output
~/anaconda-updates/rhel-10-boot.iso

Do not build under a directory such as /tmp/custom_initrd. updates.img is an Anaconda runtime overlay, not an initrd.img rebuild.


Create a safe test customization

This walkthrough uses a marker file that proves the overlay was fetched, extracted, and applied without risking an invalid Anaconda configuration key. Production overlays commonly add /etc/anaconda/conf.d/ snippets, add-ons under /usr/share/anaconda/addons/, or patched Python modules after you compare the target installer version.

Create the archive path for the marker file.

bash
mkdir -p usr/share/golinuxcloud

Add a short text file whose contents you can verify in the installer shell.

bash
printf '%s\n' 'updates.img loaded successfully' \
  > usr/share/golinuxcloud/updates-image-test.txt

That file maps to /usr/share/golinuxcloud/updates-image-test.txt in the installer runtime.

WARNING
Anaconda configuration keys and internal Python modules can change between major releases. Before copying a real /etc/anaconda/conf.d/ file from an older release, inspect /etc/anaconda/anaconda.conf on the exact installer you are customizing.

Build and inspect updates.img

Run the archive command from the root of the working tree so paths stay relative.

bash
find . -print0 \
  | cpio --null -o -H newc \
  | pigz -9 > ../updates.img

The -print0 and --null pair safely handles unusual filenames, newc selects an explicit modern CPIO format, and building from the working root prevents an unwanted parent directory prefix.

Red Hat also documents a shorter equivalent:

bash
find . | cpio -c -o | pigz -9cv > ../updates.img

Check the resulting file type.

bash
file ../updates.img

Sample output:

output
../updates.img: gzip compressed data, max compression, from Unix, original size modulo 2^32 1024

List the archive contents without extracting it.

bash
pigz -dc ../updates.img | cpio -it

Sample output:

output
.
usr
usr/share
usr/share/golinuxcloud
usr/share/golinuxcloud/updates-image-test.txt

The first path component must match the installer-runtime layout. Reject archives that begin with a build-host prefix such as home/user/anaconda-updates/work/... or tmp/custom_updates_img/....

Do not add .buildstamp to this basic updates.img.


Add updates.img to a boot ISO

Current RHEL 10 versions of mkksiso support embedding an Anaconda updates image directly. Confirm that the installed version provides the option:

bash
mkksiso --help | grep -E -- '--updates|-u'

When the option is available, embed the image:

bash
sudo mkksiso \
  -u ~/anaconda-updates/updates.img \
  ~/anaconda-updates/rhel-10-boot.iso \
  ~/anaconda-updates/rhel-10-updated.iso

The -u option is a current RHEL 10 workflow and might not be available in the older Lorax packages shipped with RHEL 8 or RHEL 9. On those releases, load the image externally with inst.updates= or follow the custom RHEL ISO guide for release-specific ISO extraction and repackaging.

Confirm the output ISO exists after the command completes.

bash
ls -lh ~/anaconda-updates/rhel-10-updated.iso

Optionally inspect ISO metadata when isoinfo is installed:

bash
isoinfo -d -i ~/anaconda-updates/rhel-10-updated.iso

For manual xorrisofs, EFI partition, boot-catalog, and MD5 rebuild steps, see the custom RHEL ISO guide instead of duplicating that procedure here.

Boot the modified ISO

Attach the new ISO through your hypervisor, write it to USB media, or expose it through BMC virtual media. Boot the system and confirm that Anaconda starts normally before you rely on the overlay.


Load updates.img externally with inst.updates

Rebuilding the ISO is not required when the image is reachable during installer startup.

Load over HTTP or HTTPS

output
inst.updates=https://install.example.com/rhel/updates.img

Networking must be available before Anaconda can retrieve the file. Add ip=dhcp or other network boot options only when your boot environment requires them.

Load from USB or a local disk

By device name:

text
inst.updates=sda1:/images/updates.img

Prefer a stable UUID when the device name may change in the installer environment:

text
inst.updates=UUID=b4234403-dafb-44c1-b878-4d57b40c9843:/updates.img

Device naming in the installer can differ from the installed system, so UUID is usually safer.

Load from an installation tree

Anaconda can discover a correctly named updates.img from supported installation-tree locations. For network trees, keep the file name exactly updates.img. For NFS installations, current RHEL documentation recognizes paths such as images/updates.img and RHupdates/updates.img.

See the RHEL 10 boot options reference for the complete syntax across protocols.

Add inst.updates to PXE or GRUB

Append the option to the installer kernel command line. The bootloader directive may be linux, linuxefi, or another firmware-specific form.

text
linuxefi images/pxeboot/vmlinuz \
  inst.repo=https://install.example.com/rhel/10/BaseOS/x86_64/os/ \
  inst.ks=https://install.example.com/kickstart/server.ks \
  inst.updates=https://install.example.com/rhel/updates.img \
  ip=dhcp

Use current inst.* options instead of legacy ks= or ksdevice= syntax from RHEL 7 boot menus. For PXE server layout, see the Kickstart PXE boot server guide without repeating that full procedure here.


Verify that Anaconda loaded the image

Boot with the modified ISO or an inst.updates= option that points at your image.

Open the installer shell by switching to the tmux console:

text
Ctrl+Alt+F1

Then press Ctrl+b, release both keys, and press 2 to open the interactive root shell. To return to the graphical installer, use Ctrl+Alt+F6.

Check for the injected marker file.

bash
cat /usr/share/golinuxcloud/updates-image-test.txt

Expected output:

output
updates.img loaded successfully

Search installer logs for retrieval and application messages.

bash
grep -Ri 'updates' /tmp/anaconda.log /tmp/program.log /tmp/storage.log

On systems where journalctl is available in the installer environment:

bash
journalctl -b | grep -i updates

Successful download does not prove the customized file is valid. Verify both that the file exists in the installer runtime and that Anaconda accepts the customization. Installation logs normally live under /tmp during installation and are copied into the installed system after a successful install.


Extract and rebuild an existing updates.img

Create a new extraction directory for each rebuild. Using a timestamp avoids mixing files from an earlier extraction:

bash
extract_dir="$HOME/anaconda-updates/extracted-$(date +%Y%m%d-%H%M%S)"
mkdir -p "$extract_dir"
cd "$extract_dir"

Extract the archive.

bash
pigz -dc "$HOME/anaconda-updates/updates.img" | cpio -idmv

Modify the required files, then rebuild from inside the extraction root.

bash
find . -print0 \
  | cpio --null -o -H newc \
  | pigz -9 > "$HOME/anaconda-updates/updates-rebuilt.img"

Verify the rebuilt image before use.

bash
pigz -dc "$HOME/anaconda-updates/updates-rebuilt.img" | cpio -it

Sample output:

output
.
usr
usr/share
usr/share/golinuxcloud
usr/share/golinuxcloud/updates-image-test.txt

Extracting into a non-empty directory can leave stale files in the rebuilt image. Always extract into a new directory.


Troubleshoot updates.img loading failures

Installer cannot download updates.img

Check URL spelling and case, DNS resolution, installer networking, HTTP status, TLS trust, and proxy requirements.

From another system on the network:

bash
curl -I https://install.example.com/rhel/updates.img

Inside the installer shell, use the tools available in that runtime to confirm connectivity to the same URL.

Archive loads but files are missing

Inspect archive paths on the build host.

bash
pigz -dc updates.img | cpio -it

Common causes include building from the wrong working directory, absolute or parent paths in the archive, a misspelled installer path, placing files under the target-system tree instead of the installer runtime, or compressing the archive twice.

Anaconda fails after applying the image

Remove the image and boot the unmodified installer to confirm the overlay caused the failure. Inspect /tmp/anaconda.log, /tmp/program.log, /tmp/packaging.log, and journalctl when available.

Likely causes include Python or API incompatibility, an invalid Anaconda configuration option, a missing D-Bus service or policy file, a file from another RHEL major version, or replacing a critical installer file with an incompatible build.

PXE boot ignores inst.updates

Confirm the option appears on the final kernel command line, the URL is reachable from the installer rather than only from the PXE server, required networking options are present, and the boot entry you edited matches the firmware mode in use.

bash
cat /proc/cmdline
Symptom Likely cause Main verification
Image not downloaded Network or URL failure curl, installer logs
File absent after loading Incorrect archive path cpio -it
Anaconda crashes Incompatible customization /tmp/anaconda.log
PXE option ignored Wrong boot entry or command line /proc/cmdline
Modified ISO does not boot ISO build or label problem Rebuild with mkksiso
Changes appear in installed OS unexpectedly Confusion between installer and target roots Review overlay path and Kickstart

When product.img is the better choice

product.img is normally associated with installer product customization such as branding and pixmaps, GUI stylesheets, product or profile configuration, installer add-ons, and persistent Anaconda configuration packaged with the boot media. It is normally placed at images/product.img on the installation ISO.

Unlike the basic updates.img workflow, current Red Hat documentation associates .buildstamp with product customization and product.img. Documented product content paths include /usr/share/anaconda/pixmaps/, /usr/share/anaconda/addons/, /etc/anaconda/profile.d/, and /etc/anaconda/conf.d/.

Use a dedicated product.img guide when branding or persistent installer customization is the goal. inst.updates= can load a compatible overlay from another location even when the file name is not literally updates.img, but this article consistently names the artifact updates.img.

For supported RHEL media composition without hand-built installer overlays, see Cockpit Image Builder for custom RHEL ISO.


Conclusion

updates.img remains part of current Anaconda-based RHEL-family installers. Build it as a compressed CPIO archive whose paths mirror the installer runtime, omit .buildstamp for a basic overlay, embed it with mkksiso -u on RHEL 10 when that option is available, or load it with inst.updates= over HTTP, local disk, USB, or an installation tree. Verify the overlay inside the installer environment before you trust a full installation run.

Use Kickstart or Image Builder when runtime modification is unnecessary. RHEL 7 used older boot-option syntax; treat EL7 as legacy and follow current Red Hat documentation for RHEL 8, 9, and 10.


References

  • Red Hat Enterprise Linux 10 — Customizing Anacondaupdates.img, product.img, mkksiso -u, and overlay paths
  • Red Hat Enterprise Linux 10 — Boot options reference — inst.updates= syntax and supported sources
  • initrd.img update and rebuild guide — early-boot changes that do not belong in updates.img
  • Custom RHEL ISO guide — manual ISO rebuild workflows beyond mkksiso

Frequently Asked Questions

1. Is inst.updates still supported on RHEL 10?

Yes. RHEL 10 documents inst.updates for loading an updates.img file from a network location, local disk or USB device, and an installation tree.

2. Does updates.img need a .buildstamp file?

No. A basic updates.img is a compressed CPIO overlay and does not require .buildstamp. Red Hat documents .buildstamp as part of product and installer branding customization associated with product.img.

3. Does updates.img modify the installed operating system?

Not automatically. updates.img overlays files in the running Anaconda installer environment. Use Kickstart, packages, or post-install configuration when files must be installed on the target system.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)