Skip to content

Eikon Image Deploy

Eikon is a storage and image deployment tool for Digital Rebar Provision (DRP) that automates deploying operating system images to bare metal in a repeatable, declarative way. The recommended approach is to use vendor-provided cloud images — the same images used in public clouds — converted for bare metal deployment.

Eikon supports two image deployment methods:

  • Raw disk images — a complete disk image written directly to the target device (dd-* types). Simpler to prepare; the partition layout is fixed in the image.
  • Rootfs archives — a filesystem archive extracted onto a custom storage configuration (tar-* types). More flexible; you define the partition layout, LVM, and RAID in the eikon/plan.

Image Considerations

Before deploying images with Eikon, review these requirements:

  • cloud-init / cloudbase-init — if using cloud-init or cloudbase-init for post-boot customization, the binaries must already be installed in the image at their default locations. If you provide a custom cloud-init/user-data on Windows, you must include the runcmd entry to start the DRP agent — see Cloud-Init Agent Startup.
  • Post-install tasks — if not using cloud-init, create custom DRP tasks to handle any OS configuration that would normally be done at first boot.
  • Drivers and early-boot packages — include all hardware drivers and storage controller modules in the image before capture. They cannot be reliably added during deployment.
  • Windows — on a default deploy you do not need to pre-create C:\curtin\; Eikon writes it and image-deploy-cleanup removes it once the agent joins. If you take the directory out of that path — by setting image-deploy/cleanup-curtin to false, or by pointing content at /curtin for boots after the first — create it in the image and apply the ACL from inside Windows. Eikon runs inside Sledgehammer (Linux) and cannot manage Windows filesystem permissions. See The curtin Directory on Windows.
  • Debian/Ubuntu grub packages — install grub-efi-amd64 (UEFI) or grub-pc (legacy BIOS) and cache them before image capture. This is especially important for airgap deployments. Also remove /usr/lib/grub/grub-multi-install from the image — it causes problems during bootloader installation.
  • Image cleanup — Eikon does not clean up images. Either clean up the OS before capture or create custom post-deploy tasks.

Cloud-Init Agent Startup

Eikon injects the DRP agent configuration into the deployed image during deployment so the agent can connect back to DRP after first boot.

Linux Agent Startup

For Linux deployments, Eikon installs the DRP agent as a systemd service inside the deployed image during the deployment phase (via eikon-chroot-agent-install). The agent starts automatically on first boot via systemd — no runcmd entry in cloud-init/user-data is required.

Windows Agent Startup

For Windows deployments, Eikon writes /eikon-win-agent.ps1 to the deployed image. This script configures and starts the DRP agent on first boot. When cloud-init/user-data is not set, Eikon generates the following default cloudbase-init user-data to trigger the script:

YAML
#cloud-config
runcmd:
  - 'powershell -noexit -file /eikon-win-agent.ps1'

If you provide a custom cloud-init/user-data, you must include this runcmd entry. Without it, the DRP agent will not start after deployment and the machine will not reconnect to DRP.

Example of a custom cloud-init/user-data that preserves agent startup:

YAML
cloud-init/user-data: |
  #cloud-config
  runcmd:
    - 'powershell -noexit -file /eikon-win-agent.ps1'
    - 'your-custom-command-here'

Cloud Image Deployment

Vendor cloud images (AlmaLinux, Rocky Linux, Ubuntu, Debian) are the recommended image source. They are maintained by the distribution vendors, regularly updated, and already configured for cloud-init.

The general workflow is:

  1. Download the vendor cloud image (QCOW2 or raw)
  2. Convert or extract to a format Eikon supports
  3. Compress with zstd
  4. Upload to DRP file storage
  5. Reference the image in an eikon/plan profile

Required Tools

Bash
# RHEL/AlmaLinux/Rocky
dnf install qemu-img zstd libguestfs-tools

# Debian/Ubuntu
apt install qemu-utils zstd libguestfs-tools

Cloud Image Sources

Distribution Cloud Image URL
AlmaLinux 10 https://repo.almalinux.org/almalinux/10/cloud/x86_64/images/AlmaLinux-10-GenericCloud-latest.x86_64.qcow2
Rocky Linux 9 https://dl.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2
Ubuntu 24.04 https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
Debian 12 https://cdimage.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.tar.xz

Preparing Raw Images

Raw images write the entire disk directly to the target device. The partition layout is whatever was in the cloud image — no additional storage configuration is needed.

AlmaLinux 10:

Bash
curl -Lo alma10.qcow2 https://repo.almalinux.org/almalinux/10/cloud/x86_64/images/AlmaLinux-10-GenericCloud-latest.x86_64.qcow2
qemu-img convert -O raw alma10.qcow2 alma10.raw
zstd alma10.raw -o alma10.raw.zst
drpcli files upload alma10.raw.zst as images/eikon/alma10.raw.zst

Rocky Linux 9:

Bash
curl -Lo rocky9.qcow2 https://dl.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2
qemu-img convert -O raw rocky9.qcow2 rocky9.raw
zstd rocky9.raw -o rocky9.raw.zst
drpcli files upload rocky9.raw.zst as images/eikon/rocky9.raw.zst

Ubuntu 24.04 (Ubuntu cloud images use a .img extension but are QCOW2 format):

Bash
curl -Lo ubuntu24.img https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
qemu-img convert -O raw ubuntu24.img ubuntu24.raw
zstd ubuntu24.raw -o ubuntu24.raw.zst
drpcli files upload ubuntu24.raw.zst as images/eikon/ubuntu24.raw.zst

Debian 12 (Debian distributes cloud images as a .tar.xz containing a raw disk):

Bash
curl -Lo debian12.tar.xz https://cdimage.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.tar.xz
tar xf debian12.tar.xz
zstd disk.raw -o debian12.raw.zst
drpcli files upload debian12.raw.zst as images/eikon/debian12.raw.zst

Once uploaded, the raw image plan is minimal — just reference the disk and image:

YAML
eikon/plan:
  disks:
    - name: d0
      path: /dev/sda
      grub_device: true
      image:
        type: dd-zst
        url: "{{ .ProvisionerURL }}/files/images/eikon/alma10.raw.zst"

See the example-eikon-*-cloud-raw profiles in the eikon content pack for ready-to-use examples for each distribution.

Preparing Rootfs Images

Rootfs images let you define a custom storage layout (partition sizes, LVM, RAID) independent of what the vendor image uses. Use virt-tar-out from libguestfs-tools to extract the filesystem from a cloud image.

AlmaLinux 10:

Bash
curl -Lo alma10.qcow2 https://repo.almalinux.org/almalinux/10/cloud/x86_64/images/AlmaLinux-10-GenericCloud-latest.x86_64.qcow2
virt-tar-out -a alma10.qcow2 / - | zstd -o alma10.tar.zst
drpcli files upload alma10.tar.zst as images/eikon/alma10.tar.zst

Rocky Linux 9:

Bash
curl -Lo rocky9.qcow2 https://dl.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2
virt-tar-out -a rocky9.qcow2 / - | zstd -o rocky9.tar.zst
drpcli files upload rocky9.tar.zst as images/eikon/rocky9.tar.zst

Ubuntu 24.04:

Bash
curl -Lo ubuntu24.img https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
virt-tar-out -a ubuntu24.img / - | zstd -o ubuntu24.tar.zst
drpcli files upload ubuntu24.tar.zst as images/eikon/ubuntu24.tar.zst

Debian 12:

Bash
curl -Lo debian12.tar.xz https://cdimage.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.tar.xz
tar xf debian12.tar.xz
virt-tar-out -a disk.raw / - | zstd -o debian12.tar.zst
drpcli files upload debian12.tar.zst as images/eikon/debian12.tar.zst

A rootfs plan defines the full storage layout. The image is extracted into the configured filesystems:

YAML
eikon/plan:
  disks:
    - name: disk1
      path: /dev/sda
      ptable: gpt
      grub_device: true
      partitions:
        - name: part1
          id: 1
          ptype: fat32
          size: 1G
          fs:
            name: fs1
            fstype: vfat
            mount: /boot/efi
        - name: part2
          id: 2
          ptype: ext4
          size: 1G
          fs:
            name: fs2
            fstype: ext4
            mount: /boot
        - name: part3
          id: 3
          ptype: ext4
          size: REST
          fs:
            name: fs3
            fstype: ext4
            mount: /
  images:
    - url: "{{ .ProvisionerURL }}/files/images/eikon/alma10.tar.zst"
      type: tar-zst

See the example-eikon-*-cloud-rootfs profiles in the eikon content pack for ready-to-use examples with more complex layouts (LVM, software RAID).

QCOW2 Images

Eikon can deploy QCOW2 images directly without converting them to raw first. Use eikon/image-type: qcow in the plan:

YAML
eikon/plan:
  disks:
    - name: d0
      path: /dev/sda
      grub_device: true
      image:
        type: qcow
        url: "{{ .ProvisionerURL }}/files/images/eikon/alma10.qcow2"

Windows Raw Images

Windows images must be raw disk images and are typically captured from a prepared VM rather than downloaded as cloud images. The plan format is simplified using the eikon/image-url and eikon/image-type params directly rather than a full eikon/plan:

YAML
Params:
  eikon/image-url: "{{ .ProvisionerURL }}/files/images/eikon/win2019.raw.zst"
  eikon/image-type: dd-zst
  eikon/install-dev: /dev/sda

See Creating Raw Images for instructions on capturing a Windows image.

Windows Unattend.xml

Eikon generates an unattend.xml answer file during Windows deployment using a built-in template. The following params customize it:

Param Default Description
eikon/win-unattend-username Administrator Local administrator account name
eikon/win-unattend-password Password123 Local administrator account password (set this before deploying to production)
eikon/win-unattend-locale en-US Windows locale/language (e.g. de-DE, fr-FR)
eikon/win-unattend-xml Full unattend.xml override — bypasses the template entirely

Add these to a profile alongside your image params. The eikon/win-unattend-password param is stored as a secure param.

Eikon always writes C:\Windows\Setup\Scripts\SetupComplete.cmd to call C:\eikon-win-agent.bat after Windows setup completes. If you provide a custom unattend.xml that bypasses SetupComplete.cmd — for example by using FirstLogonCommands — include an explicit call to C:\eikon-win-agent.bat to ensure the DRP agent starts after deployment.

The curtin Directory on Windows

On the Windows path, with image-deploy/use-cloud-init at its true default and image-deploy/cloud-init-base-url at its file:///curtin/ default, eikon writes the cloud-init seed that Cloudbase-Init reads on first boot into C:\curtinmeta-data and user-data.

meta-data carries image-deploy/admin-username, image-deploy/admin-password, cloud-init/x509-certs and access-keys. Treat the directory as part of the image's security posture.

Warning

eikon applies chmod 700 to C:\curtin, but that mode is discarded. The directory is written to NTFS from the Linux deployment OS, where POSIX mode bits are not ACLs, and a directory the image did not create inherits the volume root's ACL, which by default is readable by all local users. No chmod from the deployment OS can restrict it.

What closes the exposure is that the directory does not survive. Once the agent joins, the image-deploy-cleanup task deletes C:\curtin. eikon reaches that task through the image-deploy-cloud-init stage of the shared universal-image-deploy workflow, so it runs on an eikon deploy without any extra configuration.

You own hardening the directory if you take it out of that path — by setting image-deploy/cleanup-curtin to false, or by pointing custom cloud-init/user-data or unattend content at /curtin for boots after the first. In that case create the directory in the image and apply the ACL from inside Windows, where it takes effect. See The /curtin Directory for the icacls recipe and its limits.

On Linux there is no /curtin. eikon writes the NoCloud seed to /var/lib/cloud/seed/nocloud, created 0700 with 0600 files, and no hardening is needed.

On Windows the same task writes C:\var\lib\cloud\seed\nocloud too — the modes are discarded there for the same NTFS reason as C:\curtin, and unlike C:\curtin, nothing removes it: image-deploy-cleanup deletes C:\curtin, C:\root, and C:\usr, but not C:\var or C:\etc. Do not put secrets in cloud-init/user-data on the Windows eikon path until this gap closes (rackn/product-backlog#1581).

Getting Started

This walkthrough deploys a cloud image using the pre-built example profiles included in the eikon content pack.

Prerequisites

  • DRP server v4.14 or later
  • The eikon content pack and its prerequisites — drp-community-content, universal v4.15.7 or later, and image-deploy v4.16.5 or later. Installing eikon from the catalog pulls these in automatically; if you are loading content by hand, load them first.
  • Target machine registered and discovered in DRP
  • Image uploaded to DRP file storage (see Cloud Image Deployment)

Raw Image Deployment Example

  1. Upload the AlmaLinux 10 raw image (see Preparing Raw Images)
  2. Navigate to the target machine in the DRP UX
  3. Go to the Editor tab
  4. Under Collections → Profiles, add the profile example-eikon-alma10-cloud-raw
  5. Under Workflow Management → Pipeline, select eikon-image-deploy
  6. Under Workflow Management → Workflow, select universal-image-deploy

The deployment will:

  • Boot into Sledgehammer
  • Write the raw disk image directly to /dev/sda
  • Configure the bootloader
  • Reboot into the deployed system

Rootfs Deployment Example

  1. Upload the Ubuntu 24.04 rootfs image (see Preparing Rootfs Images)
  2. Navigate to the target machine in the DRP UX
  3. Go to the Editor tab
  4. Under Collections → Profiles, add the profile example-eikon-ubuntu24-cloud-rootfs
  5. Under Workflow Management → Pipeline, select eikon-image-deploy
  6. Under Workflow Management → Workflow, select universal-image-deploy

The deployment will:

  • Boot into Sledgehammer
  • Create the partition layout defined in the profile
  • Extract the rootfs archive into the configured filesystems
  • Install and configure the bootloader
  • Rebuild initramfs and update /etc/fstab
  • Reboot into the deployed system

Common Issues

Image not found — verify the image path. The URL in the profile must match the path used during drpcli files upload. Check <drp-host>:8091/files/images/eikon/ to confirm the file is present.

Boot failure (UEFI/Legacy mismatch) — Eikon deploys to both UEFI and legacy BIOS targets, but the layout has to match how the machine boots.

  • With no eikon/plan set, Eikon picks the layout from the machine's detected-bios-mode param — see Deploying Without a Plan. A machine whose firmware was switched after discovery will have a stale detected-bios-mode; re-run discovery so the value matches the firmware.
  • With an eikon/plan set, matching is yours. UEFI needs ptable: gpt and a vfat partition mounted at /boot/efi; legacy BIOS needs ptable: msdos with flag: boot on the boot partition.
  • For raw disk images the layout is fixed inside the image, so the image itself must have been built for the target's boot mode. Eikon cannot repartition around that.

If a UEFI target still fails to boot, confirm Secure Boot is disabled.

Machine does not come online — the deployed OS may not have network configured. Log in via console, enable networking, and restart the DRP agent:

Bash
systemctl restart drp-agent

Boot hangs after rootfs deployment — cloud images that include a bootcmd with a resume= argument (for hibernate/swap resume) may hang at boot because Eikon does not currently have a way to specify the resume device. Remove the resume= argument from the bootloader configuration or cloud-init bootcmd in the image before capture.

Deploying Without a Plan

You do not have to write an eikon/plan. When neither eikon/plan nor curtin/partitions is set, Eikon generates the storage configuration from a handful of params:

Param Purpose
eikon/install-dev Target disk path. Defaults to /dev/sda, or to image-deploy/install-disk when that is explicitly set. Give a full device path (/dev/vda, /dev/nvme0n1), not a bare disk name.
eikon/image-url HTTP/HTTPS URL to the image
eikon/image-type Image format
eikon/image-checksum Optional SHA256 of the image file

What gets generated depends on eikon/image-type.

A rootfs archivetar-zst, tgz, txz, tbz, or tar — gets a full partition layout, chosen from the machine's detected-bios-mode param:

Boot mode Partition table Layout
UEFI GPT 1G vfat at /boot/efi, 1G ext4 at /boot, remainder ext4 at /
Legacy BIOS MBR 1G ext4 at /boot carrying flag: boot, remainder ext4 at /

A whole-disk image — any dd-* type, or qcow — carries its own partition table, so no layout is generated. Eikon writes the image to eikon/install-dev as-is, and the image must already match the target's boot mode.

The example-eikon-minimal-rootfs profile in the eikon content pack is the rootfs case with a placeholder image URL. Copy it, replace eikon/image-url and eikon/image-type, and deploy.

YAML
Params:
  eikon/install-dev: /dev/sda
  eikon/image-url: "{{ .ProvisionerURL }}/files/images/eikon/alma10.tar.zst"
  eikon/image-type: tar-zst

Note

Setting eikon/plan — or curtin/partitions, which is translated from a Curtin config — disables generation entirely and your configuration is used verbatim.

Write an eikon/plan when you need something the generated layout does not give you: different partition sizes or filesystems, LVM, software RAID, more than one disk, a swap partition, or specific mount options.

Understanding eikon/plan

The eikon/plan parameter defines the full storage and image deployment configuration. It is used for rootfs deployments and for raw deployments where you need to specify a target device explicitly.

Raw Image Plan

The minimal form — write a complete disk image directly to a device:

YAML
eikon/plan:
  disks:
    - name: disk-0
      grub_device: true
      path: /dev/sda              # or by-id: /dev/disk/by-id/wwn-0x5002...
      image:
        type: dd-zst              # dd-raw, dd-gz, dd-bz2, dd-xz, dd-zst
        url: "https://..."
        checksum: <sha256>        # optional but recommended

Rootfs Plan

Define the full storage layout — partitions, LVM volumes, RAID arrays — then apply the image:

YAML
eikon/plan:
  disks:                    # physical disks and partitions
  vgs:                      # LVM volume groups and logical volumes
  swraids:                  # software RAID arrays (mdadm)
  images:                   # OS images to extract

Use size: REST on a partition to consume all remaining space. Use ptype: LVM2_member to assign a partition to an LVM volume group.

LVM Example

YAML
eikon/plan:
  disks:
    - name: disk1
      path: /dev/sda
      ptable: gpt
      grub_device: true
      partitions:
        - name: part1
          id: 1
          ptype: vfat
          size: 1G
          fs:
            name: fs1
            fstype: vfat
            mount: /boot/efi
        - name: part2
          id: 2
          ptype: xfs
          size: 1G
          fs:
            name: fs2
            fstype: xfs
            mount: /boot
        - name: part3
          id: 3
          size: 17G
          ptype: LVM2_member
  vgs:
    - name: vg1
      pvs:
        - part3
      lvs:
        - name: lv1
          size: 14G
          fs:
            name: fs3
            fstype: xfs
            mount: /
        - name: lv2
          size: 1G
          fs:
            name: fs5
            fstype: swap
  images:
    - url: "{{ .ProvisionerURL }}/files/images/eikon/alma10.tar.zst"
      type: tar-zst
      checksum: <sha256>

Software RAID Example

Arrays are declared under swraids. The member devices are also listed under disks so Eikon prepares them, and partitions, filesystems and images then hang off the array rather than off a disk:

YAML
eikon/plan:
  swraids:
    - name: swraid1
      devices:
        - /dev/sda
        - /dev/sdb
      raid_level: 1
      metadata: "1.0"
      ptable: gpt
      grub_device: true
      partitions:
        - name: part1
          id: 1
          ptype: fat32
          size: 1G
          fs:
            name: fs1
            fstype: vfat
            mount: /boot/efi
        - name: part2
          id: 2
          ptype: ext4
          size: REST
          fs:
            name: fs2
            fstype: ext4
            mount: /
  disks:
    - name: disk1
      path: /dev/sda
    - name: disk2
      path: /dev/sdb
  images:
    - url: "{{ .ProvisionerURL }}/files/images/eikon/debian12.tar.zst"
      type: tar-zst

Note

On Debian and Ubuntu set metadata: "1.0". That writes the array metadata to the end of the member devices so UEFI firmware can still read their partition tables. The default 1.2 metadata sits near the front and hides them.

The deployed image needs mdadm and the matching kernel modules to assemble the array at boot, and vendor cloud images generally ship neither. eikon-chroot-packages installs what the plan implies — mdadm for swraids, lvm2 for vgs, btrfs-progs for btrfs filesystems, cryptsetup for LUKS — which requires the image's own repositories to be reachable from the deployment network. Set eikon/skip-chroot-packages to true when there is no such access, or when the image already carries the tools. The example-eikon-debian12-cloud-rootfs-swraid profile shows the whole arrangement.

Generated fstab

For rootfs deployments, eikon-chroot-fstab writes /etc/fstab in the target from the plan rather than using whatever the image shipped. Every filesystem with a mount becomes an entry, swap filesystems and a top-level swap file are appended, and devices are written as UUID= values read off the filesystems Eikon just created — so the target boots regardless of how the kernel enumerates disks.

Per-entry columns come from the filesystem's mount_options, dump and pass fields:

YAML
fs:
  name: fs3
  fstype: ext4
  mount: /
  mount_options: "defaults,noatime"   # default: defaults
  dump: "0"                           # default: 0
  pass: "1"                           # default: 1 for /, 2 elsewhere

Plan Reference

The plan has five top-level keys — disks, vgs, swraids, images and swap. Sizes accept a suffix (1G, 512M, 17G) or REST to consume all remaining space.

Disk — an entry in disks:

Field Description
name Identifier referenced elsewhere in the plan
path Device path, e.g. /dev/sda
path_by_id, path_by_uuid, path_by_path Select the device by stable identifier instead of path. Preferred where kernel device names are not stable.
ptable gpt or msdos
grub_device Install the bootloader to this disk
partitions List of partitions
fs Filesystem applied to the whole disk, with no partition table
image Image written to the whole disk. Must be a raw format, or qcow for QCOW2.
wipe Remove existing PVs, VGs and filesystems first. Implied by image.
zero Also zero the device. Implied by image. Slow on large disks.

Partition — an entry in a partitions list:

Field Description
id Partition number
size Partition size, or REST
start, end Explicit bounds, as an alternative to size
ptype Partition type, e.g. ext4, fat32, xfs, LVM2_member
name GPT partition label. Set via sgdisk --change-name; Ubuntu's grub tooling uses it to identify boot partitions. Ignored on MBR.
flag One or more flags, comma-separated — see below
fs Filesystem to create on the partition
image Image written to the partition

flag accepts several values in one string, e.g. "boot,bios_grub". On GPT each maps to an sgdisk type code — bios_grub (ef02), boot (ef00), lvm (8e00), raid (fd00), swap (8200), home (8302), linux (8300), msftres (0c01), prep (4100). When more than one is given the type code is chosen by precedence: bios_grub, prep, boot, lvm, raid, swap, home, msftres, linux. On MBR, boot sets the bootable bit, swap sets type 82, extended and logical control the partition kind, GPT-only flags are ignored, and prep is an error.

FileSystem — an fs block on a disk, partition or logical volume:

Field Description
name Identifier referenced elsewhere in the plan
fstype ext4, xfs, vfat, btrfs, swap, …
mount Mount point in the deployed system
mount_options, dump, pass fstab columns — see Generated fstab
label, uuid Filesystem label and UUID
force, quick, quiet Add the corresponding arguments to the mkfs command for this filesystem type
image Archive extracted into this filesystem

Image — an image block, or an entry in images:

Field Description
url HTTP/HTTPS source URL
type dd-raw, dd-gz, dd-bz2, dd-xz, dd-zst, dd-tar, dd-tgz, dd-txz, dd-tbz, qcow, tar, tgz, txz, tbz, tar-zst
checksum SHA256 of the source. Optional, recommended.
path Where the image is placed. Only meaningful for a stand-alone image; when the image sits on a disk, partition, array or filesystem, that container's path wins.

Volume group — an entry in vgs. Each entry in lvs takes name, size, path, fs and image:

Field Description
name Volume group name
pvs Names of plan partitions to use as physical volumes
lvs Logical volumes

Software RAID — an entry in swraids:

Field Description
name Name of the md device
devices Member disks or partitions. Each must also be defined in the plan.
raid_level 0, 1, 5, 6, or 10
metadata Superblock style, passed to mdadm. Defaults to default. Use "1.0" for UEFI on Debian/Ubuntu.
spare_devices Hot spares. Each must also be defined in the plan.
ptable gpt or msdos. Required to partition the array; omit it to put a filesystem on the array directly.
grub_device Install the bootloader to the array's members
partitions, fs As for a disk
image Image written to the array. Must be a raw format.
path Device path
wipe One of superblock, superblock-recursive, pvremove, zero, random
preserve Reuse an existing array. A new one is created if what is on disk does not match.

Swap file — the top-level swap key, for a swap file. For a swap partition, give a partition an fs with fstype: swap instead:

Field Description
filename Path in the target. Defaults to /swap.img.
size Swap file size. Omit it to size from system memory the way Curtin does; set 0 to disable swap.
maxsize Cap on the computed size. Rejected if size exceeds it.
force Skip the check that the target filesystem supports swap files

Note

disks and swraids entries also report a size when Eikon dumps the storage it found on a machine. That is a derived value — setting it in a plan has no effect.

Airgap Bundle Support

Images can be included in an offline deployment bundle using the --include-file flag:

Bash
drpcli airgap build \
  --platform=amd64/linux \
  --catalog=https://repo.rackn.io \
  --versions=v4.15.0 \
  --include-file=https://your-image-server/alma10.raw.zst::files/images/eikon

The --include-file flag takes <source-url>::<destination-path> — the destination path is relative to the DRP file store. If the filename is omitted from the destination, it is treated as a directory.

See Airgap Install for full airgap bundle documentation.

Authenticated Image Access

Basic Auth

Add credentials directly to the image URL:

Text Only
https://user:pass@my-image-server/image.tar.zst

To avoid storing credentials in plain text in the profile, use ParamExpand to inject them at render time:

YAML
images:
  - url: '{{ if .ParamExists "secure-basic-auth" }}https://{{ .ParamExpand "secure-basic-auth-param" }}@{{ regexReplaceAll "^https?://" .ProvisionerURL "" }}{{ else }}{{ .ProvisionerURL }}{{ end }}/files/images/eikon/alma10.tar.zst'
    type: tar-zst
secure-basic-auth-param: 'user:pass'

mTLS

Provide a client certificate, key, and optional CA cert as base64-encoded values:

Bash
eikon/tls-cert      # base64-encoded client certificate
eikon/tls-key       # base64-encoded client private key
eikon/tls-ca-cert   # base64-encoded CA certificate (to validate the server)

Creating Custom Images

Use this approach when you need to build images from scratch, incorporate proprietary software, or capture a system that has been configured manually. Cloud images are preferred when available.

Creating Rootfs Archives

Install your OS on a physical machine or VM, then capture the filesystem:

  1. Boot into the installed system
  2. Install compression tools:
    Bash
    # RHEL/AlmaLinux/Rocky
    dnf install zstd
    
    # Debian/Ubuntu
    apt install zstd
    
  3. Create the tar archive from the root filesystem:
    Bash
    cd /
    tar --exclude={proc,sys,tmp,dev,run,var/tmp}/* \
        --exclude={*.tar,root/post-install.log} \
        --numeric-owner \
        --acls \
        --selinux \
        --xattrs \
        --xattrs-include=* \
        -cvf my-rootfs.tar .
    
  4. Compress:
    Bash
    zstd my-rootfs.tar
    

Note

The following tar flags are used to preserve filesystem metadata:

  • --numeric-owner — preserves UIDs/GIDs
  • --acls — preserves Access Control Lists
  • --selinux — preserves SELinux contexts
  • --xattrs --xattrs-include=* — preserves extended attributes

Creating Raw Images

Direct disk capture — boot from external media and image the disk while it is not mounted:

Bash
dd if=/dev/sda | zstd -o my-image.raw.zst

Convert from a VM disk image:

Bash
# From QCOW2
qemu-img convert -f qcow2 -O raw disk.qcow2 system.raw

# From VMDK (VMware)
qemu-img convert -f vmdk -O raw "Virtual Disk.vmdk" system.raw

# From VDI (VirtualBox)
qemu-img convert -f vdi -O raw disk.vdi system.raw

# Compress the result
zstd system.raw -o system.raw.zst

Note

Building the OS in a VM first is the recommended approach for custom raw images. It avoids hardware-specific issues during capture and allows clean shutdown before imaging.

Windows raw images are built the same way — install Windows in a VM, configure as needed (installing cloudbase-init if required, and pre-creating C:\curtin\ only if you have taken it off the cleanup path — see The curtin Directory on Windows), shut down cleanly, then convert the VM disk:

Bash
qemu-img convert -f vmdk -O raw "Windows Server 2019.vmdk" win2019.raw
zstd win2019.raw -o win2019.raw.zst
drpcli files upload win2019.raw.zst as images/eikon/win2019.raw.zst

Additional Assistance

For support, open a Zendesk ticket with the following information:

  • Set rs-debug-enable: true on the machine to enable debug logging
  • Rerun the pipeline to capture detailed logs
  • Run drpcli support machine-bundle $UUID to collect a machine support bundle
  • Capture console output for any error messages visible during deployment