Skidbladnir — complete overview
The real README: the full pitch, quickstart, capabilities and design. The repo-root
README.mdis the slim face (title · mashup · pointers); this chapter is the heavy detail, and it is also folded into the manualdocs/manual.pdfbynornir docs book.
100% Rust — airgap a whole system (the infrastructure and the software on it) across a gap with no network, no shell, no manual steps: pack everything into one sealed, content-addressed bundle, carry it across, and on the far side it provisions the machine, sets up PKI + systemd, and starts every component in dependency order.
Why Skíðblaðnir — it carries the whole deployment (infra and software) over an airgap in one bundle and brings it up with no agent on the target — the rows marked NA are categories the rivals have no concept for:
| capability | Skidbladnir | Ansible | Packer | cloud-init |
| One sealed, content-addressed bundle — infra + software + images + config + data, verify-on-receipt | ✅ | ✗ | ◐ (image only) | ✗ |
| Zero network, zero shell on the target — drives systemd over D-Bus, no SSH/agent | ✅ | ✗ (SSH + Python) | ✗ | ◐ (first-boot shell) |
| Provision the machine (Redfish BMC · Terraform · KVM) and install the software, one tool | ✅ | ◐ | ✗ | ✗ |
Typed ServiceSpec → renderer tree — PKI + user + systemd unit + ports + dated layout from one declaration |
✅ | NA | NA | NA |
| Dependency-ordered bring-up with atomic version-swap + rollback | ✅ | ◐ | ✗ | ✗ |
| 100% Rust, builds & runs fully offline (lean core pulls no network client) | ✅ | ✗ (Python) | ◐ (Go) | ✗ |
| Mature module ecosystem / huge community / multi-distro coverage | ◐ | ✅ | ✅ | ✅ |
Rows marked NA: the rival has no such category — not a missing feature, a missing concept.
Think of it as a moving company for a deployment. The flyttbil (moving van) packs all your belongings — every binary, config, container image and data file — into one sealed crate. But unlike a normal mover, it also brings the cement mixer: on the far side it pours the foundation first (provisions the machine, the OS, the network) and then unpacks the furniture (installs, configures and starts each component) — in the right order. You roll the crate across the airgap; the far side comes up running.
What it does — pack, move, unfold
- pack — gather everything the target needs: artifacts, target-identical dependencies (it can build a component in a container so it is byte-alike with the destination), images, config, data.
- archive — seal it into one movable bundle with a content-addressed manifest (SHA-256 per entry), so the far side can verify-on-receipt that nothing changed in transit.
- move — carry the single bundle across the gap by any means (it is just bytes — a disk, a one-way diode, a courier).
- unfold — on arrival: lay the foundation (provision hardware/VMs), unpack into a versioned software dir, set up the PKI, create the service user and systemd unit, open the firewall, and start every component in dependency order. No shell scripts — it talks to systemd over D-Bus directly.
It packs and unpacks: the same crate goes both ways.
Named for Skíðblaðnir, the ship in Norse myth that always has a fair wind and folds up small enough to fit in a pouch. The bundle folds an entire deployment into one thing you can carry.
Quickstart
# internet side — pack a staging tree into a signed tar.zst bundle + per-entry SHA-256 manifest:
nornir airgap pack ./staging --out lake.tar.zst
# …carry lake.tar.zst across the gap (a disk, a one-way diode, a courier)…
# secure side — ZERO network on the target:
nornir airgap fetch lake.tar.zst # verify-on-receipt against the manifest
nornir airgap unfold kvm my-vm # show the provisioning plan (kvm | terraform | redfish; --run to drive)
nornir airgap start lake.spec.toml # dependency-ordered start waves → systemd over D-Bus
The packet format — tar + zstd default, znippy behind a feature
The default archive is tar + zstd: pure Rust, always works offline, the dependable fallback. znippy — the REAL znippy archive format (../znippy: selective read without full decompress, blake3 chunk integrity, ship-only-changes delta), the one canonical archive — is fully implemented behind the znippy cargo feature (--features znippy), not the default. Turn it on to use it; the tar+zstd path keeps working regardless.
Capabilities
- platform — per-OS prep, verify-on-receipt, unpack into the software dir.
- pki —
SelfGenerateded25519 certs (pure Rust, offline) or a Vault source. - layout — version-dated
software/<date>/<product>dirs with an atomic symlink swap on upgrade (and rollback). - product — service user + systemd unit + configure + open ports.
- unfold backends — Redfish (bare-metal BMC) · Terraform (cloud/VM) · KVM (local test).
- orchestrate — dependency-ordered bring-up, emitting
airgap_events.
Design
Lean by default: the offline core (pack · archive · layout · orchestrate · events) needs only a small always-offline dep set (anyhow/serde/tar/zstd/sha2/chrono/tempfile/zbus), so it always builds offline. PKI, the znippy engine, and the Redfish/Terraform/KVM backends sit behind cargo features — the lean core never pulls a network client it doesn't use.
Part of the nornir ecosystem. See nornir/.nornir/airgap-install.md for the full design + guide.
License
MIT OR Apache-2.0