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

nordisk/Skidbladnir

.nornir/install-for-idiots.md

install — for idiots (install a real service, step by step)

Class: idiot. Every step, nothing assumed. Goal: watch Skidbladnir install a service two different ways (systemd and OpenRC) from the SAME description, and prove it — without touching a real machine. If you already know Rust, read install-guide.md.

What you need first

cd /run/media/rickard/T9/git/Skidbladnir
cargo --version

Step 1 — the big idea, in one sentence

You write one description of your service (what to run, as which user, which ports). Skidbladnir turns it into the right files and commands for whatever init system the target uses — systemd on Ubuntu, OpenRC on Alpine — and it does this as data you can inspect before anything runs.

Step 2 — run the install tests and watch them pass

The install lifecycle has tests that install a service into a temporary folder (so no root, no real machine) and check every file and command. Run them — type and press Enter:

cargo test --release install_product

Look for the green test result: ok. Two tests just ran:

Step 3 — see the "one spec, two backends" proof

Type and press Enter:

cargo test --release one_spec_renders_to_systemd_and_openrc

That single test takes ONE ServiceSpec and renders it to BOTH systemd and OpenRC, each in its own native shape. That is the whole point of the install tree: describe once, install anywhere. The SAME description now also renders to SysV (/etc/init.d/<name> LSB script), runit (a /etc/sv/<name>/ service directory), dinit (a /etc/dinit.d/<name> textual service description), s6-rc (a /etc/s6-rc/source/<name>/ compiled-source definition dir), OCI (a podman run container invocation), Quadlet (a systemd .container unit podman-systemd turns into a <name>.service) and Windows SCM (a WiX .wxs service fragment driven by sc.exe) — all eleven backends from one spec, full coverage. Watch the runit, dinit, s6-rc, OCI, Quadlet and Windows ones:

cargo test --release runit_renders_a_service_dir_with_run_finish_conf_and_log
cargo test --release dinit_renders_a_service_description_and_env_file
cargo test --release s6rc_renders_a_source_definition_dir_with_run_finish_deps_and_env
cargo test --release oci_renders_a_podman_run_invocation_and_env_file
cargo test --release quadlet_renders_a_container_unit_and_verbs
cargo test --release windows_service_renders_a_wix_fragment_and_sc_verbs

Step 4 — understand the three verbs

Skidbladnir treats these as three different jobs (run each test to watch it):

cargo test --release install_product_on_systemd_system
cargo test --release update_product_preserves_data_and_log_and_swaps_version
cargo test --release uninstall_product_purge_flag_controls_data_retention

Each green line is Skidbladnir proving that job works, into a throwaway folder.

Step 5 — why "verbs as data" means you can trust it

Notice none of those tests needed root or a real service manager. That is because Skidbladnir does not do the install directly — it produces the list of files to write and the list of commands to run (enable, start, …) as plain data. The test reads that data and checks it. Only the real apply step actually runs the commands. So you can always see exactly what would happen first.

Step 6 — where secrets go (and where they must NOT)

A service's password or token is a secret. The systemd unit file lives at /etc/systemd/system/<name>.service, which anyone on the machine can read (mode 0644). So a secret must never be written into it. Skidbladnir gives you two knobs: with_env(key, value) for ordinary settings (these end up in the unit, in the clear) and with_secret_env(key, value) for secrets (these go only into a locked-down env file that is chmod 600 — readable by nobody but the owner). If you set a secret but forget to say where the env file lives, Skidbladnir refuses to install rather than leak it. Watch the guard prove it:

cargo test --release secret_env_never_leaks_into_world_readable_unit
cargo test --release write_private_file_is_0600_even_over_a_loose_preexisting_file

The first line checks the token is nowhere in the unit but is in the private file; the second checks the private file is chmod 600 the instant it is created — never briefly world-readable.

Step 6 — see the identity a real install would mint

Type and press Enter:

cargo test --release fresh_dirs_mint_different_install_ids

This proves that installing onto the same machine twice keeps the same machine fingerprint but gets a fresh install id each time — that is how Skidbladnir tells "same machine, reinstalled" apart from "a different machine".

Where to go next