Skip to content

jro/jodi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JODI — jro's Own Debian Installer

A scriptable, debootstrap-based Debian installer. Installs Debian Trixie onto a ZFS root pool (single, mirror, or raidz) with optional ZFS-native encryption. Supports BIOS and UEFI. Use it interactively with a text UI, or automate with env vars.

JODI focuses on the initial system install. If you're building a NAS, add your bulk storage pools after the first boot.

Status: works on my machine(s). x86_64/amd64 only for now.


Quick start

1. Build the live ISO from a git checkout (the build stages tracked files via git ls-files, so an unpacked source archive won't work):

sudo apt-get install -y live-build dpkg-dev rsync
git clone https://github.com/jro/jodi.git
cd jodi
scripts/build-live-iso.sh
# output: dist/jodi-live.iso

2. Flash to USB:

sudo dd if=dist/jodi-live.iso of=/dev/sdX bs=4M status=progress conv=fsync

3. Boot from the USB drive, then run jodi:

Interactive:

jodi

Walks you through disk selection, encryption choice, hostname, users, and shows an install summary before touching any disk.

Non-interactive (setting env vars):

JODI_TARGET_DISKS="sda sdb" \
JODI_WIPE=yes \
JODI_HOSTNAME=myhost \
JODI_ROOT_PASSWORD=changeme \
jodi

JODI is idempotent at the bootstrap stage — safe to re-run if it fails partway through, as long as JODI_WIPE=yes is set (which re-wipes and re-partitions the target disks).


Environment variables

Variable Default Description
JODI_TARGET_DISKS (required) Space-separated disk names, e.g. "vda vdb" or "sda"
JODI_WIPE no Must be yes to allow destructive disk wipe
JODI_FORCE_REUSE_POOL_NAMES no Set yes to skip the vdev-membership safety check and destroy an existing rpool/bpool regardless of which disks its vdevs are on. Only needed when reinstalling on a machine that already has a pool with the default names on the target disks. Dangerous if set incorrectly — will destroy the named pool without verifying it lives on the target disks.
JODI_FIRMWARE auto auto (detect via /sys/firmware/efi) | bios | uefi
JODI_SERIAL_CONSOLE no yes adds console=tty0 console=ttyS0,115200n8 to the installed kernel
JODI_ROOT_PASSWORD (required unless JODI_USER is set) Root password; also sets PermitRootLogin yes in sshd
JODI_USER (optional) Username for a non-root sudo user to create
JODI_USER_PASSWORD (required if JODI_USER is set) Password for the non-root user
JODI_ENCRYPTION none none | native (ZFS native encryption)
JODI_ZFS_PASSPHRASE (prompted when needed) Passphrase for JODI_ENCRYPTION=native; required for non-interactive native encryption
JODI_HOSTNAME debian Hostname for the installed system
JODI_TIMEZONE live timezone or UTC Timezone for the installed system, e.g. America/New_York
JODI_BOOT_OPTIONS (empty) Extra installed-kernel boot options, e.g. nomodeset pci=noaer
JODI_SYNC_CLOCK yes Best-effort live clock sync before apt/debootstrap work; set no to skip
JODI_SYNC_CLOCK_TIMEOUT 20 Seconds to wait for best-effort live clock sync
JODI_ASSUME_DEFAULTS no Use defaults for optional prompts; useful for serial/automated installs
JODI_TOPOLOGY auto Pool topology: auto | single | mirror | raidz1 | raidz2 | raidz3. auto resolves to single (1 disk) or mirror (2 disks); 3+ disks require an explicit value or TUI selection.
JODI_BPOOL_SIZE 2G Size of the boot pool partition
JODI_MIRROR http://deb.debian.org/debian Debian mirror for debootstrap and apt
JODI_LOCALE en_US.UTF-8 Locale for the installed system
JODI_LOG_FILE /tmp/jodi-install.log Path to write the install log

Disks are resolved to /dev/disk/by-id/ paths automatically — passing bare names like vda or sda is fine.

Pool topology

auto selects single for 1 disk and mirror for 2. For 3+ disks, topology must be chosen explicitly via JODI_TOPOLOGY (non-interactive) or via the TUI prompt (interactive). Options: mirror, raidz1, raidz2, raidz3.


What JODI does

Each disk gets four GPT partitions: 1 MB BIOS boot (EF02), 512 MB ESP (EF00), JODI_BPOOL_SIZE bpool (BF01), remainder rpool (BF00).

Two ZFS pools: bpool (compatibility=grub2, holds /boot) and rpool (full features, optional native encryption, holds everything else).

Dataset tree

rpool/ROOT/debian  /              rpool/var/log    /var/log
rpool/home         /home          rpool/var/spool  /var/spool
rpool/home/root    /root          rpool/var/cache  /var/cache
rpool/srv          /srv           rpool/var/www    /var/www
rpool/usr/local    /usr/local     rpool/tmp        /tmp
bpool/BOOT/debian  /boot

Development

Prerequisites: make deps installs QEMU/KVM, OVMF, expect, sshpass, shellcheck, and live-build.

Lint:

make check       # bash -n syntax check + shellcheck (errors only)

Tests (each spins up a QEMU VM, installs, boots, and asserts):

tests/vm.sh fetch-iso                    # download Debian Live 13.6 Xfce ISO once
tests/run-cases.sh                       # run all cases
tests/run-cases.sh bios-mirror           # run one case
Case What it covers
bios-mirror Two-disk virtio mirror, BIOS/SeaBIOS. Baseline.
uefi-single One-disk UEFI/OVMF. Common single-drive hardware path.
uefi-mirror Two-disk mirror, UEFI/OVMF.
uefi-single-zfs-native-encryption One-disk UEFI with ZFS native encryption and local-console unlock.
_live-tui Interactive TUI walkthrough — excluded from the default run. Invoke explicitly: tests/run-cases.sh _live-tui. Boots a live VM with no env vars set and attaches to a serial console.

See TESTING.md for the full test matrix, individual VM commands, and serial console tips.


Known limitations

  • amd64 only for now — GRUB target, ESP fallback path, and live-build config are all x86_64-hardcoded.
  • UEFI mirror ESP. Only the first disk's ESP is populated; losing it leaves the machine unbootable despite a healthy-degraded rpool. Workaround: rsync -a /boot/efi/ /path/to/second/esp/ after install.
  • Offline install. Network is required at install time (for now).

Inspiration

JODI stands on the shoulders of two prior efforts:

  • The OpenZFS project's Debian Trixie Root on ZFS HOWTO. The bpool/rpool split, the dataset layout, the GPT partition scheme, and the zfs-list.cache priming step all come from this guide.
  • Dan Fossi's Debian-ZFS-Root-Installation-Script, which showed a working shape for turning the HOWTO into an actual installer script.

Contributing

PRs and issues welcome.

About

jro's own debian installer

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages