-
Notifications
You must be signed in to change notification settings - Fork 2
ze install
Pre-Alpha. This page describes behavior that may change.
ze install remote is a one-command, zero-touch provisioning (ZTP) server that PXE-boots target machines with a gokrazy appliance image containing Ze. It is part of the build-host ze-setup binary, not the on-device ze binary. The whole installer is Go (the install verbs local, systemd, remote, and the initrd-side disk writer all register through the install dispatcher); there is no shell installer.
Warning: the provisioning network MUST be isolated. Run
ze install remoteonly on a dedicated segment with no other DHCP server. On a shared network a foreign DHCP server (for example a corporate one) can win the boot-time race and hand the target a lease with no route back toze.server. See Foreign DHCP recovery.
- The operator runs
ze install remoteon an existing Ze device connected to the provisioning network. - Ze generates a config enabling DHCP (with PXE extensions), TFTP, and an HTTP image server, then forks itself (
ze -) with the config piped to stdin. - A target machine PXE-boots: DHCP assigns an IP and directs it to the TFTP bootloader, which chain-loads the installer kernel and initrd via HTTP.
- The installer writes the gokrazy image to disk, injects the credential
database.zefs, and reboots. - The target boots into Ze in bootstrap mode: discovers all interfaces, enables a DHCP client on each ethernet NIC, and starts SSH for operator access.
ze install remote \
--interface eth0 \
--network 192.168.1.0/24 \
--image /path/to/gokrazy.img \
--ssh-username admin \
--ssh-password changemeThis starts three servers on eth0:
| Protocol | Port | Purpose |
|---|---|---|
| DHCP | 67/udp | IP assignment with PXE options (bootfile, next-server). |
| TFTP | 69/udp | Bootloader delivery (iPXE for BIOS/UEFI), read-only per RFC 1350. |
| HTTP | 80/tcp | Disk image and boot file serving (supports Range requests). |
The server IP is resolved from the interface's first IPv4 address. If the interface has no IPv4 address, the address from --network is added via netlink and removed again on exit. When --network is a network address such as 192.168.1.0/24, the first host (192.168.1.1) is used. Pass --address to override.
The DHCP pool scales with the subnet size and excludes the server IP:
| Network | Server | Pool start | Pool stop |
|---|---|---|---|
| 10.0.0.0/24 | 10.0.0.1 | 10.0.0.2 | 10.0.0.254 |
| 192.168.1.0/28 | 192.168.1.1 | 192.168.1.2 | 192.168.1.14 |
| 10.1.1.0/30 | 10.1.1.1 | 10.1.1.2 | 10.1.1.2 |
| Flag | Required | Default | Description |
|---|---|---|---|
--interface |
Yes | Network interface to bind all servers. | |
--network |
Yes | Provisioning subnet CIDR (/8 to /30). | |
--image |
Yes | Path to gokrazy disk image file. | |
--ssh-username |
Yes | Admin username for the installed target. | |
--ssh-password |
Yes | Admin password (bcrypt-hashed, cost 10, before embedding). | |
--address |
No | First IPv4 on interface (or first host of --network) |
Server IP override. |
--kernel |
No | Path to installer kernel (copied to the boot directory). | |
--initrd |
No | Path to installer initrd (copied to the boot directory). |
--kernel and --initrd copy the installer files to /var/lib/ze/install/boot/. Stock iPXE binaries from tools/ipxe-binaries/ are staged to /var/lib/ze/install/tftp/ automatically. Once staged from a previous run, omit both flags.
The --ssh-password plaintext is never written to disk or config (only its bcrypt hash is embedded), but it is visible in the process listing (ps aux) while the server runs.
The DHCP server detects PXE clients via option 60 (PXEClient:) and reads option 93 (client architecture) to select the bootfile.
| Architecture | Bootfile |
|---|---|
| BIOS (type 0) | ipxe.pxe |
| UEFI (type 6, 7, 9) | ipxe.efi |
iPXE chainloading is automatic. The DHCP server detects iPXE via the option 77 user-class prefix iPXE and, instead of the TFTP binary, returns the HTTP boot-script URL pointing at a dynamically generated boot.ipxe. That script sets the kernel command line with ze.server, ze.image (lexicographically last .img), ze.port (when not 80), and ip=dhcp. A static boot.ipxe in the boot directory takes precedence for operator customization. This two-stage chainload (firmware -> iPXE via TFTP -> boot.ipxe via HTTP) removes the need for custom-embedded iPXE builds.
The TFTP server implements RFC 2347 option negotiation (OACK), required for UEFI PXE boot.
The initrd carries no kernel modules, so the kernel it boots alongside must have NIC drivers, disk drivers, ext4, devtmpfs, initramfs and ip=dhcp autoconfiguration all built in (=y). Stock distro/cloud kernels ship these as modules and cannot boot the initrd. Ze deliberately ships no installer kernel: the right kernel is site-specific. Build one with ze appliance kernel (two profiles: qemu for tests, hardware for bare metal) and the build script fails loudly if a required option did not resolve to =y. See Appliance for the kernel build.
The target PXE-boots an installer kernel plus initrd, not the disk image directly. The installer initrd (tools/installer-initrd/) is a single static busybox image that performs the disk write on the target:
- Parses
ze.source,ze.server,ze.port,ze.image,ze.target, andze.media-idfrom the kernel command line. - In HTTP (PXE) mode, downloads the gokrazy disk image over HTTP from the install server.
- Writes it to the first non-removable block device (selected via the sysfs
removableattribute; virtual, optical, floppy, andmtdblockflash devices are skipped). Supported targets include/dev/sda,/dev/vda,/dev/nvme0n1, and/dev/mmcblk0. - In HTTP mode, mounts partition 4 (ext4,
/perm) and writes the pre-provisioneddatabase.zefs(SSH credentials) to/perm/ze/database.zefs. - Reboots (HTTP mode) or powers off (ISO mode, so the media can be removed first).
Build it with:
make -C tools/installer-initrdOn a missing server IP, no writable disk, or a download that fails three times, the init script drops to a debug shell instead of rebooting.
The installer fans its progress and FATAL: lines to every console listed in /sys/class/tty/console/active, not just the single /dev/console the kernel marks preferred. On a headless box the preferred console can be a dead VGA tty while kernel messages still reach the serial line, which would otherwise hide all installer output. The generated boot.ipxe selects the console set per client architecture: x86 clients get console=tty0 console=ttyS0, while arm64 also keeps console=ttyAMA0. The rescue shell on error is bound to a real working console, preferring serial since headless installs are driven over serial.
On the server side, ze install remote runs at info log level by default, so the terminal shows the live boot sequence:
-
dhcpserver logs each lease:
dhcpserver: lease request=DISCOVER reply=OFFER mac=... ip=... bootfile=... -
tftpserver logs each bootloader fetch:
tftpserver: read request file=ipxe.efi client=... -
imageserver logs each HTTP request and, at startup, the image it serves with its build identity:
imageserver: image to install image=ze-<ts>.img built=<ts> ze-version=... sha256=...
If you see the iPXE downloads (boot.ipxe, vmlinuz, initrd.img.gz) but never an /install/image/<name> request, the target booted the kernel but its initrd could not reach the server to pull the image (commonly a foreign DHCP lease on a non-isolated network) and the install did not complete.
On some hardware (for example Intel I226-V) the kernel ip=dhcp autoconfiguration races against NIC carrier detection, and on a non-isolated network it can win a lease from a foreign DHCP server whose default route cannot reach ze.server. The initrd guards against both:
- It trusts the kernel-provided default route only when
ze.serveractually answers an HTTP probe. - If there is no default route, or the route present cannot reach the server, it brings up all non-loopback interfaces, waits up to 10 seconds for carrier, and runs
udhcpcon each interface, verifying the server is reachable before accepting the lease. - Interfaces that obtain a lease but cannot route to
ze.server:ze.portare flushed and skipped. - If no interface produces a working route, the installer drops to a debug shell.
Even after the network is up, the server may not be reachable yet (switch STP port transitions can block traffic for 30-50 seconds after a reboot). The initrd probes the server with a 2-second timeout, retrying up to 30 times, distinguishing "TCP unreachable" from "HTTP error response" so a 404 still counts as reachable. A foreign DHCP server on a shared segment can still defeat this if it also wins the per-interface lease race, which is why the provisioning network must be isolated.
When Ze starts with a zefs database but no config file and no template (the state after a freshly-provisioned device boots), it auto-inits into bootstrap mode on first boot:
- Interface discovery enumerates all OS network interfaces.
- A minimal config is generated: a DHCP client on every ethernet interface, SSH server enabled.
- DHCP clients acquire addresses and SSH becomes reachable.
Non-ethernet interfaces (bridge, veth, dummy, loopback, wireguard, xfrm) are skipped. The SSH credentials come from zefs (written by the installer initrd), not from the generated config. Once you SSH in, configure Ze with ze config edit and commit; the committed config replaces the bootstrap config on the next restart, and Ze then starts in normal mode.
Bootstrap mode is intended only for trusted provisioning networks (SSH is enabled on all interfaces). If no ethernet interface is found, or the netlink backend is unavailable, bootstrap mode does not activate.
ze install remote generates a standard Ze config in brace format and pipes it to a child ze process. The config enables three plugins: dhcpserver (PXE options, shared-network, computed pool), tftpserver, and imageserver (with the SSH credentials). The same setup can be written by hand and run with ze <config-file>.
SIGTERM or SIGINT sent to ze install remote is forwarded to the child, which shuts down cleanly. Closing the parent sends EOF on the stdin pipe, which Ze treats as a shutdown signal.
- An isolated provisioning network: no second DHCP server on the L2 segment.
- Root privileges (DHCP, TFTP, and HTTP bind to privileged ports; interface auto-configuration uses netlink).
- Disk image at the path given to
--image. - Installer kernel and initrd: pass
--kernel/--initrdon first run, or pre-stage them in/var/lib/ze/install/boot/. - iPXE binaries: bundled in
tools/ipxe-binaries/, auto-staged if not present.
make ze-install-qemu-test exercises the whole PXE chain in QEMU with no hardware: it builds the initrd, builds a real appliance image, boots the installer kernel + initrd against a blank virtio disk, has the initrd download and write the image and zefs over HTTP, then boots the written disk and logs in over SSH as the provisioned power user.
ZE_INSTALL_KERNEL=$PWD/tools/installer-kernel/build/Image make ze-install-qemu-testmake ze-install-iso-qemu-test does the same for the ISO transport. Both self-skip (do not fail) when ZE_INSTALL_KERNEL is unset or QEMU is unavailable, because there is no safe default installer kernel.
- Appliance for building gokrazy images, the installer kernel, and ISO media.
-
Install for installing Ze on an existing Linux host (
ze install local,ze install systemd).
Adapted from main/docs/guide/ze-install.md.
Unreviewed draft. This wiki was authored in bulk and has not been reviewed. File corrections on the issue tracker.
- Overview
- YANG Model
- Editor Workflow
- Archive and Rollback
- System
- Interfaces
- VRRP
- BFD
- FIB
- OSPF
- IS-IS
- MPLS / LDP / RSVP-TE
- RSVP-TE
- SRv6
- Static Routes
- Policy Routing
- Firewall
- Traffic Control
- Class of Service
- L2TP/PPP
- PPPoE
- VPP Data Plane
- RPKI
- IPsec VPN
- TACACS+ AAA
- RADIUS AAA
- AS112 DNS
- Authorization
- Fleet
- BGP
- Starting and Stopping
- Show Commands
- Monitoring
- Flow Export
- DDoS Mitigation
- Anomaly Detection
- Health Checks
- Audit Trail
- Production Diagnostics
- Logging
- Operational Reports
- Healthcheck
- Self-Update
- Zero-Touch Provisioning
- MRT Analysis
- Upgrade and Restart
- Storage
- Policy
- Core
- Resilience
- Validation
- Capabilities
- Address Families
- Protocol
- Subsystems
- Infrastructure
- Route Server at an IXP
- Transit Edge with RPKI
- Public Looking Glass
- ExaBGP Migration Walkthrough
- FlowSpec Injection
- Chaos-Tested Peering
- AS Path Topology