// Module included in the following assemblies: // // * machine_configuration/mco-coreos-layering.adoc ifeval::["{context}" == "installing-"] :install: endif::[] :_mod-docs-content-type: PROCEDURE [id="coreos-layering-install-time_{context}"] = Applying a custom layered image during {product-title} installation [role="_abstract"] You can use the standard {product-title} installation process to apply a custom layered image to your nodes by adding a `MachineOSConfig` custom resource (CR) YAML and a push secret YAML to the `/manifests/` directory. This allows you to use {image-mode-os-lower} to apply additional functionality to specific nodes upon cluster installation. ifdef::install[] With {image-mode-os-lower}, you can extend the functionality of your base {op-system-first} image by layering additional images onto the base image. This layering does not modify the base RHCOS image. Instead, it creates a custom layered image that includes all {op-system} functionality and adds additional functionality to specific nodes in the cluster. For example, you can create custom layered images to apply hotfixes, RHEL packages, or third-party RPMs to the nodes your cluster. For more information on {image-mode-os-lower}, see the "Additional resources" section. endif::install[] After the installation, if you modify a machine config pool or update the {product-title} version, the Machine Config Operator (MCO) builds and applies a new custom layered image, and pushes the updated image to your repository. .Prerequisites * You have a custom layered image in a repository that your cluster can access. + .Example containerFile for a custom layered image [source,yaml] ---- FROM quay.io/centos/centos:stream9 AS centos RUN dnf install -y epel-release FROM [rhel-coreos image] AS configs COPY --from=centos /etc/yum.repos.d /etc/yum.repos.d COPY --from=centos /etc/pki/rpm-gpg/RPM-GPG-KEY-* /etc/pki/rpm-gpg/ RUN sed -i 's/\$stream/9-stream/g' /etc/yum.repos.d/centos*.repo && \ rpm-ostree install cowsay && \ ostree container commit ---- * You have a repository and any needed secret where the MCO can push any updated custom layered images. .Procedure include::snippets/coreos-layering-on-callouts.adoc[] . Create a YAML file for the push secret similar to the following: + [source,yaml] ---- apiVersion: v1 kind: Secret metadata: name: push-secret namespace: openshift-machine-config-operator data: .dockerconfigjson: secret type: kubernetes.io/dockerconfigjson ---- . When the `manifests` directory is available, add the `MachineOSConfig` YAML to the directory by using a command similar to the following: + [source,terminal] ---- $ cp .yaml manifests/ ---- where: + `file-name`:: Specifies the YAML file for the `MachineOSConfig` object. . Add the push secret YAML to the `manifests` directory by using a command similar to the following: + [source,terminal] ---- $ cp .yaml manifests/ ---- where: + `file-name`:: Specifies the YAML file for the push secret. . Continue with the installation process as usual. .Verification * After the installation is complete, check that the `MachineOSConfig` object displays the `PreBuiltImageSeeded` status as `True` and contains a reference to the custom layered image by using the following command: + [source,terminal] ---- $ oc get machineosconfigs.machineconfiguration.openshift.io -o yaml ---- + .Example output [source,yaml] ---- apiVersion: v1 items: - apiVersion: machineconfiguration.openshift.io/v1 kind: MachineOSConfig metadata: annotations: machineconfiguration.openshift.io/current-machine-os-build: worker-4cedbc10da849ae7019288febc3a2d17 # ... status: conditions: - lastTransitionTime: "2025-11-19T13:32:17Z" message: MachineOSConfig seeded with pre-built image "quay.io/myorg/custom-rhcos@sha256:abc123..." reason: PreBuiltImageSeeded status: "True" type: Seeded currentImagePullSpec: image-registry.openshift-image-registry.svc:5000/openshift-machine-config-operator/layered-rhcos@sha256:3c8fc667adcb432ce0c83581f16086afec08a961dd28fed69bb6bad6db0a0754 ---- where: + -- `items.status.conditions.reason.PreBuiltImageSeeded.True`:: Specifies that the associated nodes were created using your custom layered image. `items.status.currentImagePullSpec`:: Specifies the digested image pull spec for the new custom layered image. --