-
-
Notifications
You must be signed in to change notification settings - Fork 256
Description
Problem
Disko is currently somewhat tricky to maintain. Part of this comes from the current architecture that puts nix itself at the center of the entire operation, and uses it as a crude templating engine for bash scripts.
This makes implementation of some features difficult. A few examples (I'll add more when I come across them):
- Read current disk and output to disk-config.nix #728
- Feature Request: Add confirmation option for each disk when running script #772
- ZFS Features Support: Dataset property inheritance #560
- Refuse to evaluate if zpool is set to mirror if only one device is given #645
- Random boot failues due to partition confusion because disko now relies on
by-partlabel
#551 - Ignore Partitions #533
- [Feature request] Changing disk without reevaluation #732
Proposed solution
Switch to a different architecture where the nix files only define configuration values, and a bigger program written in a proper language (not bash or perl) runs nix eval --json
and works with the JSON output to plan and execute all the required actions.
Considerations
Compatibility
The interface for users should not change at all. disko.devices
should have the exact same type and result in the same configuration values as before.
Some programs (most notable nixos-anywhere, AFAIK) use disko's diskoScript
output and call this script directly. Because this is a derivation, it should be possible to just swap them out no matter the language, as long as the resulting path has a binary with the same name. However, a simple shim with a single-line script that just calls the CLI with the required flags might be sufficient for this.
Language to use
The language should make it easy for others to contribute, have decent error-handling capabilities and be well-suited to write a CLI in.
I am therefore immediately discarding bash (or any other shell language), perl, JS, TS and Haskell.
I see three main contenders: python, rust, and go. They are all well-known and have good general support. Rust is additionally loved in the nix community for its ethos of correctness, python is super easy to write, and go is kind-of a middle-ground between the two.
One thing to consider with this choice might be closure size. As disko is often run in installers, we can expect most dependencies to not be present yet (this is the singular advantage of bash; it is guaranteed to already be present). The closure sizes of the main executable vary quite a bit:
$ nix path-info --closure-size -h nixpkgs#cargo^out
/nix/store/j6vpbh78ngj2x7jrg27pqjn2cd5mzywl-cargo-1.79.0 1.2G
$ nix path-info --closure-size -h nixpkgs#go^out
/nix/store/kqf4gwhq1yrchvmvqjh4adc4y9hxp9xk-go-1.22.5 248.0M
$ nix path-info --closure-size -h nixpkgs#python3^out
/nix/store/l014xp1qxdl6gim3zc0jv3mpxhbp346s-python3-3.12.4 166.1M
It seems somewhat unreasonable to me to require the user to download 1.2 gigabytes just to be able to run disko. A binary cache could alleviate this, though this has additional usability implications.
In the case of rust and go, there would also be compilation times added, though it's hard to say if this will matter much given the size of this project.
In general, I don't yet have a strong preference for which language to use.