Skip to content

ignition: Mount OEM partition so that Ignition doesn't have to do it#121

Merged
chewi merged 6 commits intoflatcar-masterfrom
chewi/ignition-mounting
Apr 15, 2026
Merged

ignition: Mount OEM partition so that Ignition doesn't have to do it#121
chewi merged 6 commits intoflatcar-masterfrom
chewi/ignition-mounting

Conversation

@chewi
Copy link
Copy Markdown
Contributor

@chewi chewi commented Apr 15, 2026

Mount OEM partition so that Ignition doesn't have to do it

Ignition no longer does its own mounting of the OEM partition for the oem:// scheme, so bootengine needs to mount it in advance. The oem:// scheme therefore now maps to /realinit/oem, but Ignition may also write to the same partition at /realinit/sysroot/oem.

The hope is to eventually drop even more patches from Ignition and use a new file:// scheme with Butane doing the mapping from oem:// to file:///oem.

Rather than shunting OEM data between /oem, /realinit/oem, and /realinit/sysroot/oem, mount /realinit/oem as a tmpfs from the start (for PXE) and turn /realinit/sysroot/oem into a bind mount.

We want to unmount the disk-based OEM partition before Ignition's disk stage, in case it gets wiped, and its mount stage, in case it gets remounted. This can be done more simply with findmnt.

However, we do want the disk-based OEM partition to be mounted while Ignition's fetch-offline and fetch stages run in case the user has put config there. This is now done with RequiresMountsFor now that Ignition no longer does it for us. The kargs stage can also use this mount to write grub.cfg rather than mounting it again in its own namespace.

The nodev option wasn't applied to PXE.

We only expect a disk-based OEM partition to be btrfs or ext4, so don't rely on the auto type.

Aside from these mount-related changes, the ignition-setup script has been dropped (also by upstream) as it is no longer needed, I have reworked the Ignition units to make them easier to compare against upstream, and I have changed the emergency.target job mode from isolate to replace-irreversibly.

The isolate job mode causes dev-mapper-usr.device and therefore sysusr-usr.mount to stop. We cannot stop the latter though because the emergency shell is hosted within it. It's not entirely clear why this happens because both units have IgnoreOnIsolate=yes. Trying to unmount doesn't break the shell, but it does show an unexpected error.

The usual approach of preventing the above with drop-in units doesn't seem to work for auto-generated mount units. However, I noticed that systemd itself has not used the isolate job mode for emergency.target since 2013. replace-irreversibly does not proactively stop all the other units, just the ones that would block the new target. This can actually make debugging easier in the event of an Ignition failure because the system will be in a closer state to the one when the failure occurred.

See flatcar/scripts#3934 for the associated Ignition changes (in scripts).

How to use

You can try variations on these configs:

variant: flatcar
version: 1.0.0
storage:
  filesystems:
    - path: /oem
      device: /dev/disk/by-label/OEM
      format: ext4
      wipe_filesystem: true
      label: OEM
      with_mount_unit: true
  files:
    - path: /oem/foo
      overwrite: true
      contents:
        inline: |
          bar
variant: flatcar
version: 1.0.0
storage:
  files:
    - path: /etc/baz
      overwrite: true
      contents:
        source: oem:///mybaz.txt

For the latter to work, you have to place mybaz.txt in the OEM partition of the image beforehand (use guestmount) or add it to an initrd alongside the config and append that initrd to the PXE image.

Note that Butane does not currently support oem:// so you actually need to put gs:// initially and then change it to oem:// in the resulting JSON.

You can also try loading alternative configs from the OEM partition by passing ignition.config.url=oem:///myconfig.ign on the kernel command line.

Testing done

Jenkins has passed with these changes alongside the associated Ignition changes. I have also done lots of manual testing.

chewi added 5 commits April 15, 2026 10:47
Signed-off-by: James Le Cuirot <jlecuirot@microsoft.com>
The "isolate" job mode causes dev-mapper-usr.device and therefore
sysusr-usr.mount to stop. We cannot stop the latter though because the
emergency shell is hosted within it. It's not entirely clear why this
happens because both units have IgnoreOnIsolate=yes. Trying to unmount
doesn't break the shell, but it does show an unexpected error.

The usual approach of preventing the above with drop-in units doesn't
seem to work for auto-generated mount units. However, I noticed that
systemd itself has not used the isolate job mode for emergency.target
since 2013. replace-irreversibly does not proactively stop all the other
units, just the ones that would block the new target. This can actually
make debugging easier in the event of an Ignition failure because the
system will be in a closer state to the one when the failure occurred.

Signed-off-by: James Le Cuirot <jlecuirot@microsoft.com>
No need to wait until ignition-setup.service runs.

Signed-off-by: James Le Cuirot <jlecuirot@microsoft.com>
config.ign is still used as the default OEM-based configuration file.
Stock Flatcar no longer ships base.ign or default.ign, but custom images
in the wild may use these, and Ignition still checks for them.

Supporting these can be done more easily using symlinks baked into the
initrd though. It doesn't matter that they are broken most of the time.

Note that upstream Ignition has already dropped this service.

Signed-off-by: James Le Cuirot <jlecuirot@microsoft.com>
This just reordering and consolidating lines.

Signed-off-by: James Le Cuirot <jlecuirot@microsoft.com>
@krnowak
Copy link
Copy Markdown
Member

krnowak commented Apr 15, 2026

Is wiping OEM partition in ignition essentially a noop, since some tmpfs will be wiped instead and then, at a later stage, we mount the disk-based OEM partition?

@chewi
Copy link
Copy Markdown
Contributor Author

chewi commented Apr 15, 2026

The tmpfs OEM is for PXE only where there is no Flatcar disk (yet). It wouldn't make sense to try and wipe it in that case. I don't know why anyone would want to wipe it even in the non-PXE case, but apparently that is supposed to work.

Comment thread dracut/51diskless-generator/diskless-generator Outdated
Ignition no longer does its own mounting of the OEM partition for the
oem:// scheme, so bootengine needs to mount it in advance. The oem://
scheme therefore now maps to /realinit/oem, but Ignition may also write
to the same partition at /realinit/sysroot/oem.

Rather than shunting OEM data between /oem, /realinit/oem, and
/realinit/sysroot/oem, mount /realinit/oem as a tmpfs from the start
(for PXE) and turn /realinit/sysroot/oem into a bind mount.

We want to unmount the disk-based OEM partition before Ignition's disk
stage, in case it gets wiped, and its mount stage, in case it gets
remounted. This can be done more simply with findmnt.

However, we do want the disk-based OEM partition to be mounted while
Ignition's fetch-offline and fetch stages run in case the user has put
config there. This is now done with RequiresMountsFor now that Ignition
no longer does it for us. The kargs stage can also use this mount to
write grub.cfg rather than mounting it again in its own namespace.

The `nodev` option wasn't applied to PXE.

We only expect a disk-based OEM partition to be btrfs or ext4, so don't
rely on the `auto` type.

Signed-off-by: James Le Cuirot <jlecuirot@microsoft.com>
@chewi chewi force-pushed the chewi/ignition-mounting branch from 27c2888 to 1b557b4 Compare April 15, 2026 13:31
@chewi chewi merged commit 003a67d into flatcar-master Apr 15, 2026
1 check passed
@chewi chewi deleted the chewi/ignition-mounting branch April 15, 2026 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants