Skip to content

Migrating Windows Deployments from Curtin to Eikon

This page covers the Windows-specific notes for moving from Curtin to Eikon — image considerations, first-boot credentials, and verification. Do the migration itself (switch the application profile → deploy → roll back) from the shared Migrating from Curtin to Eikon guide. Your existing Windows image and its parameters carry over unchanged — nothing below is required to migrate; it explains the Windows specifics and one credential gotcha to avoid.

Image compatibility

You do not need to rebuild your Windows golden images to move to Eikon — the same generalized (sysprepped) image deploys under either engine, and your existing Curtin images stay valid as-is (see the note at the end of this section). Both engines stage drpcli and the first-boot scripts by writing into the image offline at deploy, so neither needs those baked in. What differs is a small set of image prerequisites that a profile swap can't change.

Base-image prerequisites: what changes

What the golden image needs Curtin Eikon
Generalized / sysprepped required required
Hardware drivers for the target baked in required required
cloudbase-init installed + configured required — deploy aborts if it's missing required only on the cloud-init path; droppable on the unattend-only path
C:\curtin directory pre-baked required not required — Eikon creates it at deploy
What drives Windows first-boot cloudbase-init (reads a NoCloud seed) unattend.xml always; cloudbase-init only on the cloud-init path
Image package format dd-gz / dd-tgz / dd-xz / dd-raw (no zstd) superset — adds dd-zst (recommended), tar-zst, qcow

Two things that are not migration differences: both engines inject drpcli, the runner scripts, and (on the cloud-init path) the NoCloud seed into the image at deploy time, so neither requires them pre-baked. And neither engine uses WinRM to reconnect a deployed machine — that's the drpcli agent + join-up. (If you see Waiting for WinRM in a log, that's a Packer image-build step, not a deploy step.)

Net effect: Eikon relaxes the image prerequisites. When you migrate you can optionally slim the golden image:

  • Drop the C:\curtin pre-bake — Eikon creates it at deploy on the cloud-init path and ignores it on the unattend path.
  • Drop cloudbase-init only if you adopt the unattend-only path (image-deploy/use-cloud-init=false). Keep it if you want cloud-init to apply hostname / SSH keys / cloud-init/user-data at first boot.

Your existing images still work unchanged. Slimming is optional. A current Curtin golden image — with C:\curtin and cloudbase-init already baked in — deploys under Eikon as-is: the baked C:\curtin is harmless (Eikon reuses it), and a present cloudbase-init is simply used on the cloud-init path and ignored on the unattend path. Migrate first, slim later (or never).

Configure Windows first-boot (Administrator password + agent)

On both paths, eikon's eikon-win-prep injects C:\Windows\Panther\unattend.xml (plus C:\Windows\Setup\Scripts\SetupComplete.cmd, which runs an agent batch that fetches and runs join-up) and C:\Windows\drpcli.exe. So the Administrator password is set the same way regardless of path — via the unattend:

Text Only
drpcli machines set <machine-uuid> param eikon/win-unattend-username to Administrator
drpcli machines set <machine-uuid> param eikon/win-unattend-password to '<password>'   # Secure param

Password complexity matters. The unattend sets it via a LocalAccount in the oobeSystem pass, which enforces the Windows policy (≥6 chars, 3 of {upper, lower, digit, symbol}, not the username). A non-compliant password is silently dropped → locked out (only trace: C:\Windows\Panther\setuperr.log).

What image-deploy/use-cloud-init (default true) actually controls is whether cloudbase-init is also configured at deploy — not the password:

  • true (cloud-init path) — eikon additionally writes a cloudbase-init NoCloud seed (meta-data/user-data + drpcli.ps1); cloudbase-init then applies hostname, SSH keys, and any cloud-init/user-data at first boot. Requires cloudbase-init installed in the image. Where the seed lands is set by image-deploy/cloud-init-base-url:
    • file:///curtin/ (default) → baked into C:\curtin (offline-capable; the dir name is inherited from curtin, created at deploy);
    • http(s)://… (e.g. {{.Machine.Url}}/) → cloudbase-init fetches the seed from DRP at boot (NoCloudNet); nothing baked in.
  • false (unattend-only path) — no cloudbase-init; just the unattend.xml + SetupComplete agent.

Do NOT seed image-deploy/admin-username/admin-password on the cloud-init path — it locks you out of Administrator. Mechanism (root-caused from the cloudbase-init log, not a guess): the seed value is fine, but seeding admin-username: Administrator makes cloudbase-init's CreateUserPlugin seize the built-in Administrator and give it a throwaway password (CreateUser only ensures the account; applying the metadata password is SetUserPasswordPlugin's job — and that plugin does not run in the MAIN stage on a typical image). So admin-password is never applied and Administrator is left unusable. With admin-* unset, cloudbase-init falls back to its own configured account and never touches Administrator, so the unattend-set password stands. Set the Administrator password only via eikon/win-unattend-password; let cloudbase-init own hostname/SSH-keys/user-data, not the password. (Verified on Server 2022 + 2025: seeding admin-* → locked out on both; win-unattend-password alone → clean login on both the cloud-init and unattend paths.)

Curtin → Eikon reference (Windows)

Concern Curtin (image-deploy) Eikon (eikon)
Engine selected by universal-application-image-deploy universal-application-eikon-image-deploy
Workflow universal-image-deploy universal-image-deploy (same)
Image type / URL image-deploy/image-type + image-deploy/image-url carry over — Eikon derives eikon/image-* from them (set eikon/image-type only to adopt dd-zst etc. post-migration)
Golden-image dir requires C:\curtin baked in optional; created at deploy if cloud-init path used
Windows first-boot cloudbase-init (NoCloud, file:///curtin/) cloud-init (default) or unattend.xml (use-cloud-init)
Admin credentials image-deploy/admin-username / -password eikon/win-unattend-username / -password on both paths (do not seed image-deploy/admin-password — see Troubleshooting)

Troubleshooting (Windows)

See also the common troubleshooting in the shared guide.

  • Windows boots but you can't log in (WinRM/RDP/console all reject the password) — two common causes:
  • The password failed Windows complexity in the unattend oobeSystem pass and was dropped — pick a compliant password (see first-boot). Trace: C:\Windows\Panther\setuperr.log.
  • You seeded image-deploy/admin-password on the cloud-init path — cloudbase-init took over the password and clobbered the unattend value. Remove image-deploy/admin-username / image-deploy/admin-password and redeploy; set the password only via eikon/win-unattend-password.

Verification

  1. After deploy, the machine reaches BootEnv: local and reboots into Windows.
  2. Windows completes specialize and sets the Administrator password.
  3. The machine reconnects to DRP via join-up (appears Runnable, agent online), and WinRM (5985) / RDP accept the configured Administrator credentials.

Lab-verified on DRP (universal image-deploy pipeline) deploying zstd raw Windows Server 2022 and 2025 images via Eikon on both the unattend.xml and cloud-init first-boot paths.