Gardenhouse

Gardenhouse Installer

Gardenhouse-installer is a utility that allows unattended installs of florist/gardenhouse images through various delivery methods.

Delivery Modes

  1. USB: Create bootable USB drives for simple deployment
  2. ISO: Generate ISO images for redistribution
  3. PXE: Set up iPXE-based network boot
  4. Factory: Build raw disk images ready for cloning onto hard drives

Installation Modes

The Gardenhouse Installer supports five ways to deliver and install Gardenhouse images.

USB Installer

Creates a bootable USB drive containing the stem installer and target OS images. The USB device is partitioned with a small EFI System Partition (ESP) for booting and a second data partition labeled STEMINST that holds the images.

Commands

Listing available USB drives:

root#gardenhouse-installer usb list

Creating an installer USB:

root#gardenhouse-installer usb create \
  --target-profile bamboo \
  --target-version 1.2.3 \
  --preset-values ./presets.txt \
  --output /dev/sdX \
  --force

Options

Option Description
--target-profile Target OS profile name (required)
--target-version Target OS version
--profiles-dir Directory containing Florist profile outputs
--preset-values Path to preset values file
--output Block device path (required)
--force Skip confirmation prompt

Boot Flow

  1. UEFI firmware loads BOOTX64.EFI from the ESP
  2. The stem UKI boots with root=stem
  3. Dracut mounts a tmpfs on /sysroot and runs stem-install
  4. stem-install finds the STEMINST labeled partition, locates the images, and installs to the target disk
  5. System reboots into the newly installed OS

ISO Image

Generates a UEFI-bootable ISO image.

Command

user$gardenhouse-installer usb iso \
  --target-profile bamboo \
  --preset-values ./presets.txt \
  --output ./installer.iso

Boot Flow

Identical to USB mode, except the ISO filesystem itself carries the STEMINST label. The stem-install.sh dracut hook mounts the ISO device directly to find the images.

PXE Network Boot

Sets up files for iPXE-based network boot. UEFI PXE chainloading works as follows:

  1. UEFI firmware downloads ipxe.efi via PXE
  2. iPXE loads boot.ipxe
  3. boot.ipxe fetches the stem UKI (stem-uki.efi) and boots it with stem.url=<server>/images/<profile>/
  4. The stem initramfs brings up networking and downloads images from the URL

Setup Server Files

root#gardenhouse-installer pxe setup \
  --target-profile bamboo \
  --preset-url http://config.example.com/presets/ \
  --output /var/www/html/ipxe/ \
  --generate-dhcp-config

This produces:

/var/www/html/ipxe/
├── ipxe.efi              # iPXE EFI binary
├── rootloaderx64.efi     # Rootloader (if available)
├── stem-uki.efi          # Stem UKI
├── boot.ipxe             # Main iPXE boot script
├── dhcpd.conf            # Sample DHCP config (optional)
└── images/
    └── bamboo/
        ├── gardenhouse-root_*.img
        ├── gardenhouse-root_*.verity
        ├── gardenhouse-efi_*.efi
        ├── manifest
        └── disk_layout.cfg

Generate Per-Device Scripts

user$gardenhouse-installer pxe generate-script \
  --mac 00:11:22:33:44:55 \
  --profile bamboo \
  --preset-url http://config.example.com/presets/ \
  --server-url http://pxe.example.com/ipxe \
  --output ./device-01.ipxe

iPXE Kernel Command Line

The generated scripts automatically include:

root=stem rd.neednet=1 ip=dhcp stem.profile=bamboo stem.url=http://pxe.example.com/ipxe/images/bamboo/

If you need static IPs instead of DHCP, pass a standard dracut ip= string on the kernel command line.

Factory Disk Image

Creates a complete raw disk image that can be flashed directly onto target devices. The image contains the full partition table, all partitions formatted, and all data written.

Command

root#gardenhouse-installer factory image \
  --target-profile bamboo \
  --preset-values ./factory.txt \
  --output ./factory.img \
  --compress zstd \
  --level 19

Options

Option Description
--layout Custom disk_layout.cfg file
--compress zstd, gzip, or xz
--level Compression level
--split Split output into chunks (e.g., 1G)

Media Verification

The verify command checks that installation media (USB directory, ISO file, factory image, or raw block device) matches the manifest.

root#gardenhouse-installer verify --media /dev/sdX1
root#gardenhouse-installer verify --media ./installer.iso --ignore-missing

It validates checksums for all files listed in the manifest and reports any mismatches.

Preset Values

Preset values allow zero-touch configuration of the target system. They are rendered at install time and written to the USERDATA partition as /preset_values. On first boot, the firstboot script reads this file and applies the settings.

Template Variables

The installer supports automatic substitution of these placeholders when creating installation media:

Variable Description
{{MAC}} First Ethernet MAC address detected during installation
{{SERIAL}} System serial number from dmidecode
{{UUID}} Random UUID (v4)
{{RANDOM}} 8-character alphanumeric random string
{{TIMESTAMP}} UTC timestamp in YYYYMMDDHHMMSS format
{{FACTORY_PASSWORD_HASH}} Optional hash passed via --factory-password-hash CLI flag
{{GENERATE}} Auto-generated sha512crypt password hash

Generating a Password Hash Manually

If you prefer not to use {{GENERATE}}, generate your own hash:

user$openssl passwd -6 "your_password"

Example Preset File

See examples/preset_values for a fully documented template. A minimal configuration looks like this:

Config preset_values Minimal preset values
FIRSTBOOT_UNATTENDED=yes
HOSTNAME=gh-{{RANDOM}}
MACHINE_ID={{UUID}}
TIMEZONE=UTC
ADMIN_USERNAME=admin
ADMIN_PASSWORD_HASH={{GENERATE}}
HOMECRYPT=no
ROOT_DISABLED=yes
SSH_AUTHORIZED_KEYS=""
FIRST_BOOT_SCRIPT=""

Required Fields for Zero-Touch

When FIRSTBOOT_UNATTENDED=yes, the firstboot script runs without prompting. These fields must be populated:

  • ADMIN_USERNAME
  • ADMIN_PASSWORD_HASH
  • HOSTNAME
  • TIMEZONE

If any required field is missing, firstboot exits with an error.

Preset File Format

Preset files are plain text with KEY=value pairs. Lines starting with # are treated as comments. Values can contain template variables which are replaced at install time.

Config Config format
# This is a comment
HOSTNAME=server-{{SERIAL}}
ADMIN_USERNAME=admin
ADMIN_PASSWORD_HASH=$6$rounds=5000$...

Multi-line values (like SSH_AUTHORIZED_KEYS) should use quoted strings:

Config SSH_AUTHORIZED_KEYS format
SSH_AUTHORIZED_KEYS="ssh-ed25519 AAAAC3NzaC... user@example.com
ssh-rsa AAAAB3NzaC... backup@example.com"

Firstboot Behavior

The firstboot OpenRC service runs once on the target system’s initial boot. It performs the following actions:

  1. Load presets from /user/preset_values
  2. Create the admin user (ADMIN_USERNAME)
  3. Set passwords
    • Admin password via ADMIN_PASSWORD_HASH (hash or plaintext)
    • Root password via ROOT_PASSWORD_HASH, or lock root if ROOT_DISABLED=yes
  4. Set hostname (HOSTNAME)
  5. Set timezone (TIMEZONE)
  6. Write machine ID (MACHINE_ID, or auto-generate)
  7. Install SSH authorized keys (SSH_AUTHORIZED_KEYS)
  8. Run first-boot script (FIRST_BOOT_SCRIPT) if set
  9. Mark completion by touching /user/.firstboot_completed

Password Hash Detection

firstboot automatically detects password hashes:

  • Values starting with $ (e.g., $6$rounds=5000$...) are applied with usermod -p
  • Plaintext values are applied with chpasswd

First-Boot Script

FIRST_BOOT_SCRIPT can be:

  • A local path: /lib/stem/post-install.sh
  • An HTTP(S) URL: https://config.example.com/scripts/post-install.sh

For URLs, the script is downloaded to /tmp/firstboot-script and executed with bash.

CLI Usage

Pass presets to any installer mode:

root#gardenhouse-installer usb create \
  --target-profile bamboo \
  --preset-values ./my_presets \
  --output /dev/sdX