Before nuts, there was cows

Today, let’s examine some history. The Nitrux Update Tool System was introduced almost a year ago, but there’s more to the announcement at the Nitrux Blog, so I want to expand on the unfinished predecessor to nuts called cbl.

Without further ado, let’s start.

So, it was 2023, and during the months before finally deciding to make Nitrux, once again, an immutable distribution, I was left with one major issue to work on. Remembering all the hate we received for creating and using ZNX, I just couldn’t stop thinking of all the absolute simplicity it provided us. Wanting and needing, however, are two different things. I needed something that worked with the structure we now had to use, like Calamares. In this context, we had to create software that didn’t deal with system installation, and that would also allow us to continue to push the concept of separation between the “system” and the “applications.”

Just as we did two years prior, the presence of a package manager in the traditional Linux distribution context is incompatible with that idea; thus, without it, how would a user update the “system”? So, I came up with a solution: introduce the workflow of Service Packs.

Service Pack can be defined as follows:

«A service pack is a collection of updates and fixes, called patches, for an operating system or a software program. […] the service pack allows for an easy, single installation.»

On mainstream Linux distributions, the software is typically built as a package, distributed through repositories, and managed on the end-user system through package managers. Each Linux system typically contains thousands of packages, many of which are required dependencies for other packages.

Therefore, the concept of Service Packs is very uncommon. On the other hand, Enterprises use purpose-built Linux distributions managed by Service Packs, as this allows vendors to provide OTA-style direct upgrades that are easily manageable.

And this is where Cowbell, or cbl, a tool for using Service Packs in Nitrux, came to exist, at least on paper.

Cowbell was to be used exclusively with Service Packs to provide users with problem-free upgrades from their system vendors. I mean, great! But how were these archives supposed to look like? What would they contain? Ah, let’s check the specification I drafted.


1. Service Pack Structure — Cowbell Service Pack Specification version 0.1

Service Packs for Cowbell are digitally signed TAR archives compressed using Zstandard, with a metadata file packaged inside. Cowbell will then process the archive and read the metadata file to apply the update.

In the interest of safety, cbl will refuse to process the files unless these are signed. Also, cbl will verify the structure of the Service Pack and will refuse to process files if they do not follow the structure below.

1.1 Archive

A valid Service Pack should have the file name ${service-pack-name}.csp (i.e., any combination of numbers and letters except special characters and spaces) and the following structure.

  ├─ ${service-pack-name}.mtd
  └─ content
      ├─ package-1_0.0.1.deb
      ├─ package-2_0.0.1.deb

As Cowbell would be working with Debian packages, the archive contains debs; Cowbell uses dpkg with the option(s)—i or—-force-all—i to perform the installation.

DISCLAIMER: It’s essential to note (and understand) that cbl is NOT a package manager, an alternative to APT, will NOT resolve dependencies, and does NOT manage repositories. Vendors are entirely responsible for the content of a Service Pack. They should test the Debian packages in a Service Pack to know if they work on the target Linux distribution.

1.2 Metadata File

Service Packs should include a file called ${service-pack-name}.mtd. A valid .mtd file must have the following structure.

Below are the required fields in a valid .mtd file.

SPK_NAME: The name of the Service Pack.
     * The name must match the file name ${service-pack-name}.csp.
SPK_ARCH: The intended CPU architecture of a Service Pack.
SPK_DATE: The date when a vendor created the Service Pack.
SPK_SREQ: The intended Linux distribution of a Service Pack.
     * Cowbell will check for this value; if it doesn't match, Cowbell will stop.
SPK_DESC: A short description of the Service Pack.
     * Text is displayed as a single line; keep that in mind.
SPK_SIZE: The total size of the Service Pack in metric units.
SPK_CURL: A URL pointing to the changes in a Service Pack.
SPK_HASH: A URL pointing to the SHA2 checksum file of a Service Pack.
SPK_PGPG: A URL pointing to the public key used to sign a Service Pack.

Below are the optional fields in a valid .mtd file.

SPK_EUPD: Enable automatic updates for a Service Pack.
     * Accepted values are YES and NO.
     * Useful for Linux distributions with short release cycles.
SPK_UURL: A URL pointing to the new Service Pack.
     * It only works if automatic updates are enabled; otherwise, Cowbell will ignore it even if it is present.
     * The URL pointing to the Service Pack should be static.

Below is an example with dummy data:

SPK_NAME 20223108AUG
SPK_ARCH amd64
SPK_DATE jue 01 sep 2022 23:31:23 CDT
SPK_DESC Update for Nitrux (NX Desktop) 2.2.1 to 2.4.0
SPK_HASH https://updates.nxos/${service-pack-name}.sha
SPK_PGPG https://updates.nxos/${service-pack-name}.gpg
SPK_UURL https://updates.nxos/${service-pack-name}.csp

And that was as far as I got. The next thing was visualizing how it would work; for example, what would the command be to update? What other functionality would it have, such as backups? Would it be interactive?

sudo cbl -u service-pack.csp
sudo cbl -u --reboot service-pack.csp
sudo cbl -u service-pack.csp --root-backup-path /other/device
sudo cbl -B /XFS/backup/path

I also thought, ok, and should it also create its archives? Or would it be better if a separate tool did that?

cbl -c /directory/with/debs --sign-key key.gpg

If the archives contain metadata, how would that be displayed?

cbl -i service-pack.csp

Additional changes were necessary for the whole idea to be deployed, like partition layout in Calamares, a feature that did not work then. Ultimately, I started seeing Cowbell as increasingly complex to create and maintain, which I did not want to have to deal with.

As time passed, other ideas were discussed: what if we used Git? If Git is not viable, what are other binary diff tools? Etcetera.

Until one day, I started over and landed on rsync; the rest, as they say, is history.

That’s it, folks. Here is some history of one of Nitrux’s defining features today. I still want to add some things from Cowbell to the Nitrux Update Tool System, namely the signed archives, but that’s for another time.