wheelhouse-seed.py#
Builds the small disk that installs a machine for you: an ISO 9660 image labelled
CIDATA — cloud-init's NoCloud label — holding a user-data cloud-config and whatever
it refers to. Attach it to the machine (a second disk on a virtual machine, a USB stick
on hardware), boot the Wheelhouse image, and
the installer finds it.
# from a cloud-config you wrote
tools/wheelhouse-seed.py --user-data seed.yaml --out seed.iso
# from the OPNsense router you are replacing, configuration and all
tools/wheelhouse-seed.py --opnsense config.xml --map lan=eth0,wan=eth1 \
--admin-password-file admin.pw --console-password-file console.pw \
--out seed.isoThis tool does not ship on the router. It runs on your workstation.
Options#
Exactly one of --user-data or --opnsense is required.
| Option | Default | Meaning |
|---|---|---|
--user-data FILE | — | A cloud-config you wrote yourself. Copied verbatim. |
--opnsense FILE | — | An OPNsense config.xml. The importer runs, and the seed is written around its output. |
--out FILE | seed.iso | The image to write. |
--out-dir DIR | — | Write the seed files into a directory instead of building an image. |
--label NAME | CIDATA | The filesystem label. WHEELHOUSE also works. |
--map | — | Interface mapping for the import: lan=eth0,wan=eth1. |
--disk | auto | The disk to install to. auto means the one disk that is not the boot medium. |
--hostname | from the import | Host name for the new machine. |
--timezone | UTC | Overridden by the import when the source configuration names one. |
--admin-password | — | The web UI password. Prefer the file form. |
--admin-password-file | — | |
--console-password | — | The console password. Prefer the file form. |
--console-password-file | — | |
--ssh-key FILE | — | A public key file for the console accounts. Repeatable. |
--include-source | off | Put the config.xml on the seed as opnsense-config.xml. |
--no-reboot | off | Stop after installing instead of rebooting. |
--on-error | halt | halt, poweroff, menu or shell. |
With --opnsense and no password given any way, and a terminal attached, it prompts
twice for each and refuses if the two entries differ. With no terminal, it refuses
outright rather than building a seed with an empty password.
What lands on the seed#
| File | Always | What |
|---|---|---|
user-data | yes | The cloud-config. Either yours, verbatim, or generated from the import. |
meta-data | yes | instance-id: wheelhouse-<pid>. cloud-init wants the file to exist beside user-data, even empty. |
config.commands | with --opnsense | The set lines the import produced. |
import-report.md | with --opnsense | The importer's report, so the record of what did not come across travels with the machine. |
authorized_keys | with --ssh-key | Every key, comments and blank lines stripped. Also appended to user-data as ssh_authorized_keys. |
opnsense-config.xml | with --include-source | The original file, so the installed machine can check itself against it months later. |
With --user-data, three files beside your cloud-config are picked up automatically
if they exist and copied onto the seed: config.commands, config.boot and
authorized_keys.
What the generated cloud-config looks like#
#cloud-config
# Wheelhouse unattended install. Written by wheelhouse-seed.py.
wheelhouse:
disk: auto
hostname: edge
timezone: Europe/Berlin
wan:
interface: eth1
addressing: dhcp
lan:
interface: eth0
address: 192.0.2.1/24
firewall: false
passwords:
admin: 'the web UI password'
console: 'the console password'
config:
commands: config.commands
reboot: true
on_error: haltThe host name and time zone are taken from the imported configuration's own
set system host-name and set system time-zone lines unless you override them, so the
new box keeps the old box's identity.
An image, or a directory#
| Form | Needs | Use it when |
|---|---|---|
--out seed.iso | xorrisofs, genisoimage or mkisofs — whichever is on the machine | You are attaching a virtual disk, or writing a stick with dd. |
--out-dir /media/stick | nothing | You formatted and labelled a stick yourself. Copy the files to its root and label it CIDATA or WHEELHOUSE. |
dd if=seed.iso of=/dev/sdX bs=4M status=progress && syncThe tool prints which image tool it used and the resulting size.
The seed is a credential#
Public keys are the way to keep a password from living on a stick longer than it has to:
--ssh-key ~/.ssh/id_ed25519.pub puts one on both console accounts, and the machine is
reachable the moment it boots.
Checking a seed before you use it#
python3 packaging/seed-to-answers.py user-data /tmp/work # what it converts to
sudo wheelhouse-install --answers /tmp/work/answers.conf --commands # what it would runSee also#
- Seed cloud-config keys — every key the generated file may hold.
- Where the installer looks for a seed
- Answer-file keys
opnsense-import.py— what--opnsenseruns.- Build a seed
- Unattended install
Checked against#
tools/wheelhouse-seed.py (main, TEMPLATE,
read_password, run_importer, make_image),
tools/tests/test_seed.py,
packaging/seed-to-answers.py,
packaging/wheelhouse-autoinstall,
docs/unattended-install.md.