Gardenhouse Installer
Gardenhouse-installer is a utility that allows unattended installs of florist/gardenhouse images through various delivery methods.
Delivery Modes
- USB: Create bootable USB drives for simple deployment
- ISO: Generate ISO images for redistribution
- PXE: Set up iPXE-based network boot
- 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
- UEFI firmware loads
BOOTX64.EFIfrom the ESP - The stem UKI boots with
root=stem - Dracut mounts a tmpfs on
/sysrootand runsstem-install stem-installfinds theSTEMINSTlabeled partition, locates the images, and installs to the target disk- 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:
- UEFI firmware downloads
ipxe.efivia PXE - iPXE loads
boot.ipxe boot.ipxefetches the stem UKI (stem-uki.efi) and boots it withstem.url=<server>/images/<profile>/- 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:
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_USERNAMEADMIN_PASSWORD_HASHHOSTNAMETIMEZONE
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.
# 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:
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:
- Load presets from
/user/preset_values - Create the admin user
(
ADMIN_USERNAME) - Set passwords
- Admin password via
ADMIN_PASSWORD_HASH(hash or plaintext) - Root password via
ROOT_PASSWORD_HASH, or lock root ifROOT_DISABLED=yes
- Admin password via
- Set hostname (
HOSTNAME) - Set timezone (
TIMEZONE) - Write machine ID (
MACHINE_ID, or auto-generate) - Install SSH authorized keys
(
SSH_AUTHORIZED_KEYS) - Run first-boot script
(
FIRST_BOOT_SCRIPT) if set - 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 withusermod -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