Bare-metal netboot appliance in one container. Catalog + fetch + NBD
serving + PXE plan renderer + TFTP + operator UI: one FastAPI process
(plus a supervised in.tftpd subprocess for the PXE first hop), one
state.db, and one admin password.
Pixie folds into a single service what bty (operator UI + machine
registry + PXE plan renderer + Rich TUI), nbdmux (NBD-export
multiplexer + netboot artifact serve), and a hard-fork of withcache
(catalog + fetch + blob store) implement as three separate FastAPI
services. bty, nbdmux, and withcache continue as their own projects;
pixie is a sibling appliance that starts from a merged design. See
PLAN.md for the design rationale, locked decisions, and roadmap.
The reference deploy is a single podman-compose stack under
--network=host. The pixie-lab CLI (installed with the package)
generates the compose file, the envvars template, and a per-deploy
README:
pixie-lab init /opt/pixie
"$EDITOR" /opt/pixie/envvars.example # set PIXIE_HOST_ADDR + PIXIE_ADMIN_PASSWORD
mv /opt/pixie/envvars.example /opt/pixie/envvars
cd /opt/pixie
COMPOSE_ENV_FILES=envvars podman compose up -d
pixie-lab deploy fills in an admin password + host address + waits
for /healthz in one shot, useful for a fresh lab machine.
Log in at http://:8080/. First landing after login is a dashboard summarising machines, catalog, and NBD-serving state; the top nav has Machines, Catalog, Images, Overlays, Live env, Events, and Settings.
- Point catalog import at a
catalog.tomlURL on/ui/catalog. Entries land staged (rows only, no bytes yet). - Click Fetch on a row to download it. The status pill ticks
through downloading -> decompressing -> unpacking with a
bytes / totalcounter so you see progress live. - For the live-env boot modes (
pixie-inventory/pixie-tui/pixie-flash-*), Fetch thepixie-live-envimage + its netboot bundle, then set the image'scontent_sha256on the Live env page (/ui/live-env) or viaPIXIE_LIVE_ENV_IMAGE_SHA. Those modes nbdboot that image; until it's selected they renderunavailable. - Power-cycle a target with pixie in its DHCP next-server chain.
A first contact shows up on
/ui/machineswith the defaultpixie-inventoryboot mode (non-destructive, one-shot; it posts inventory then self-exits toipxe-exit). Open the row to bind a mode + image. pixie-inventoryprompts the live env to POST an inventory blob; the target's disks + NICs + memory show up on the machine detail page.- Flash modes (
pixie-flash-once,pixie-flash-always) require a target disk serial that came in on the inventory. The binding form disables Save until that prerequisite is met.
Everything writable lives under PIXIE_DATA_DIR (default
/var/lib/pixie). state.db holds catalog rows, machine rows,
event log, settings, NBD-export records, and persistent-overlay
records. blobs/<sha>/blob holds fetched disk images.
artifacts/<sha>/{vmlinuz,initrd,manifest.json} holds unpacked
netboot bundles. overlays/<alias>.qcow2 holds globally-named
single-writer overlay volumes for the nbdboot boot mode. The live env
(pixie-inventory / pixie-tui / pixie-flash-*) is the fetched
pixie-live-env disk image, selected by PIXIE_LIVE_ENV_IMAGE_SHA /
the Live env page and nbdbooted like any other image, so it lives in
blobs/ + artifacts/ too - there is no separate live-env directory.
Both admin password and display timezone / strftime pattern have
env-var overrides plus DB overrides via /ui/settings; env wins
so a compose deploy pins behaviour deterministically.
uv sync
uv run pytest
uv run ruff check src tests
uv run mypy src
The integration tests spin real QEMU VMs behind a real pixie
container to exercise the PXE bootstrap + ramboot chains. They are
gated behind a marker so plain pytest skips them.
pixie is licensed under GPL-3.0-only. See LICENSE.
