How `--defer-provisioning` Creates Users on First Boot in Omarchy

When --defer-provisioning is passed to omarchy apply system, the installer skips user creation during the ISO build and instead records group memberships to /var/lib/omarchy/provisioning/groups, deferring actual user creation until the first boot via the omarchy-provision-owner script.

This flag enables ISO builds without embedded credentials — a security-critical pattern for distributable installation media. Instead of baking a user account into the image, Omarchy stores provisioning intent and fulfills it interactively when the end user first powers on the machine.

What --defer-provisioning Changes in the Install Flow

Normally, omarchy apply system expects to run inside a target chroot with an install user already present. The --defer-provisioning flag alters this behavior at multiple points in bin/omarchy-apply-system.

Flag Detection and Variable Clearing

In bin/omarchy-apply-system lines 37-39, the flag sets defer_provisioning=1:


# Parsed from command-line arguments

defer_provisioning=1

When active, lines 66-68 clear the install_user variable and bypass username validation:


# With --defer-provisioning, no install user is expected

install_user=""

# Validation is skipped — the script proceeds without a pre-configured account

The hardware step receives the same flag (lines 20-22), ensuring hardware-specific scripts avoid calling usermod on a non-existent user.

Group Membership Persistence

Rather than applying group changes immediately, the installer records them under /var/lib/omarchy/provisioning/groups. This persisted state bridges the gap between ISO build and first boot.

First-Boot User Creation with omarchy-provision-owner

After the system boots, a systemd service generated during install launches bin/omarchy-provision-owner. This script handles the actual user creation that was deferred.

Reading Provisioning Data

The script reads the target username from $PROVISIONING_DIR/setup-user (written earlier by the installer) and checks if the account exists.

User Creation and Configuration

Lines 26-38 implement the core creation logic:


# Creates user if missing, or modifies existing user on retry

useradd [options] "$username"

# or usermod on subsequent attempts

The script then:

  • Retrieves groups via user_groups and applies them
  • Sets passwords interactively or from stored values
  • Installs sudoers rules (lines 43-49)
  • Copies SSH keys to ~/.ssh/authorized_keys
  • Configures autologin for the first session

Group Application from Persisted Data

The script reads /var/lib/omarchy/provisioning/groups and ensures the newly created user receives all group memberships that were recorded during the ISO build.

Security and UX Benefits

No credentials in the image. The installed disk contains no password hashes, SSH keys, or user IDs until the legitimate owner boots and configures the system.

Interactive first-boot wizard. The end user is prompted for:

  • Desired username
  • Password (with confirmation)
  • Optional SSH public keys

Automatic finalization. After provisioning, the system transitions from autologin to standard SDDM login for subsequent boots.

Practical Usage and Inspection

Building with Deferred Provisioning


# Create an ISO with no pre-configured user

omarchy apply system --defer-provisioning --first-install

Inspecting Provisioning State

If you need to verify what will be applied on first boot:


# View recorded group memberships

cat /var/lib/omarchy/provisioning/groups

# Confirm target username

cat /var/lib/omarchy/provisioning/setup-user

Manual Trigger (Recovery Scenario)

While normally invoked automatically, you can run the provisioning script directly:


# Only if first-boot service failed or was disabled

sudo /usr/local/bin/omarchy-provision-owner

Key Source Files

File Purpose
bin/omarchy-apply-system Parses --defer-provisioning, disables install-user validation, forwards flag to hardware configuration
bin/omarchy-provision-owner First-boot script that creates the user, applies groups, configures sudoers, SSH keys, and autologin
install/post-install/all.sh Invokes provisioning when defer_provisioning is active
install/config/all.sh Sets environment variables including OMARCHY_INSTALL
install/helpers/logging.sh Provides provisioning process logging

Summary

  • --defer-provisioning clears install_user and skips immediate account creation in omarchy-apply-system
  • Group changes are persisted to /var/lib/omarchy/provisioning/groups instead of applied live
  • omarchy-provision-owner runs on first boot via systemd, reading stored data to create the user
  • The flow ensures zero credentials in the ISO while preserving full configuration intent for interactive fulfillment

Frequently Asked Questions

What happens if I boot without running the provisioning script?

The system will have no usable login accounts. The first-boot service is designed to run automatically, but if disabled, you would need single-user mode or a live USB to manually invoke omarchy-provision-owner or create a user with standard Linux tools.

Can I use --defer-provisioning for automated deployments?

Yes, with preparation. The installer can pre-write /var/lib/omarchy/provisioning/setup-user and encrypted password data. The omarchy-provision-owner script will proceed non-interactively if valid provisioning data exists, making it suitable for unattended first-boot scenarios.

Is the persisted group data secure?

The /var/lib/omarchy/provisioning directory contains only group names and usernames — no passwords or keys. While not sensitive, it should have standard filesystem permissions (readable by root only) to prevent information disclosure about system configuration.

How does this compare to cloud-init's user creation?

Both defer user creation until first boot, but Omarchy's approach is distribution-specific and lighter. Cloud-init requires a full data source (metadata service, config-drive, or NoCloud); Omarchy stores minimal state on-disk and prompts interactively, making it ideal for bare-metal ISO installations without network dependencies.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →