Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/Skidbladnir

.nornir/install-guide.md

install — guide

Class: guide · audience: a techie installing a product on a target. The what is in install-design.md; the why in install-reasoning.md.

f6 — one spec, any init, three lifecycle verbs (the whole flow)

use skidbladnir::{archive::TarZstd, layout::Layout, product::ComponentSpec,
                  service::Backend, install};

let eng    = TarZstd::new();
let layout = Layout::dated("/var/lib/nordisk", "/var/log/nordisk", "/opt/nordisk");
let spec   = ComponentSpec::holger();

// INSTALL: provision dirs, unfold the product, mint identity, render + write unit files
let outcome = install::install_product(&spec, &layout, &bundle_path, &eng,
                                       Backend::SystemdSystem, "/")?;   // install.rs:88
// nothing privileged has run yet — inspect the plan as data:
assert_eq!(outcome.verbs, vec![vec!["systemctl","enable","holger.service"],
                               vec!["systemctl","start","holger.service"]]);
install::apply(&outcome)?;   // the only step that runs the verbs (systemd → D-Bus)

Swap Backend::SystemdSystem for Backend::OpenRc and the same ComponentSpec installs on Alpine — different files (/etc/init.d/holger + /etc/conf.d/holger), different verbs (rc-update add …), same call.

Update (preserve data + log)

let next = Layout::dated("/var/lib/nordisk", "/var/log/nordisk", "/opt/nordisk");   // new version
let outcome = install::update_product(&spec, &next, &new_bundle, &eng, Backend::SystemdSystem, "/")?;
// data/ and log/ are preserved; the install id is loaded (not re-minted); verbs = [stop, start]
install::apply(&outcome)?;

Uninstall (optionally purge)

let outcome = install::uninstall_product(&spec, &layout, Backend::SystemdSystem, "/", /* purge */ false)?;
// unit files removed; data/log kept (purge=false) or removed (purge=true); verbs = [stop, disable]
install::apply(&outcome)?;

Build a spec by hand

use skidbladnir::{product::{ComponentSpec, HealthCheck}, systemd::RestartPolicy};

let spec = ComponentSpec::new("holger", "linux-x86_64/holger", "_holger")
    .with_arg("serve").with_arg("--config").with_arg("/var/lib/nordisk/holger/config.toml")
    .with_port(7070)
    .after("nornir-server")
    .with_health(HealthCheck::Tcp(7070));

bundle_binary is the full relative path inside the bundle — the lifecycle unfolds the whole product tree (extract_all), so keep the real path (linux-x86_64/holger), not a flattened name.

Test a render with zero privilege

Because verbs are data, you can assert an install without installing anything:

let neutral = spec.to_service_spec(&layout, Backend::OpenRc);          // product.rs:174
let rendered = skidbladnir::service::renderer_for(Backend::OpenRc).unwrap().render(&neutral);
assert!(rendered.enable == vec!["rc-update","add","holger","default"]);
assert!(rendered.file_ending("/etc/init.d/holger").unwrap().contains("supervise-daemon"));

Identity

Each install mints (or, on update, loads) an identity under the data dir:

let id = skidbladnir::identity::ensure(&data_dir, "holger", scope, "_holger")?;   // identity.rs:135
println!("{}", id.wire());   // nid1:<machine_fp>:<install_id>

Gotchas