Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Binary release archives

The v1-compatible mkBinaryRelease packages one or more already-built binaries into a deterministic, static MUSL archive. The archive contains bin/ and a manifest.json describing the package name, version, Nix system, Rust target, and exact binary list. mkReleaseBinaryPackage consumes an unpacked archive from a locked flake = false input and validates that contract before installing the binaries. Keep this schema when existing consumers already consume v1 archives; new multi-format release wiring should use the generic v2 constructors below.

The producer and consumer are deliberately separate. A project keeps its source-built package for development and exposes the prebuilt package as an explicit opt-in output:

let
  release = harbor-rs.lib.mkBinaryRelease {
    inherit pkgs;
    pname = "my-tool";
    version = "1.2.3";
    artifacts = {
      x86_64-linux-musl = {
        package = packages.my-tool-x86_64-linux-musl;
        system = "x86_64-linux";
        rustTarget = "x86_64-unknown-linux-musl";
        binaries = ["my-tool"];
      };
      aarch64-linux-musl = {
        package = packages.my-tool-aarch64-linux-musl;
        system = "aarch64-linux";
        rustTarget = "aarch64-unknown-linux-musl";
        binaries = ["my-tool"];
      };
    };
  };
in
{
  packages.release-bundle = release.releaseBundle;
}

A consumer pins each supported release asset as a non-flake input, verifies the published Simit checksum signature before changing its lock file, then selects the matching input:

inputs.my-tool-bin-x86_64.url =
  "https://codeberg.org/example/my-tool/releases/download/1.2.3/my-tool-1.2.3-x86_64-linux-musl.tar.gz";
inputs.my-tool-bin-x86_64.flake = false;

packages.my-tool-prebuilt = harbor-rs.lib.mkReleaseBinaryPackage {
  inherit pkgs;
  pname = "my-tool";
  version = "1.2.3";
  sources.x86_64-linux = inputs.my-tool-bin-x86_64;
  binaries = ["my-tool"];
};

The helper fails closed when the current system has no matching input or the archive manifest is inconsistent. The release workflow is generated by simit init release; it builds the bundle on atlas-nix-trusted, publishes the archives to Codeberg, and signs the checksum manifest with the committed keys/minisign.pub trust root.

Before the first tag, provision the generated workflow’s required secrets: CODEBERG_TOKEN at user scope, and a dedicated harbor-rs MINISIGN_SECRET_KEY/MINISIGN_PASSWORD pair at repository scope. The public key in keys/minisign.pub must be the matching key; do not reuse another project’s signing key. Check the contract with simit release secrets contract --json and the Canix declaration with canix release secrets check --project /path/to/harbor-rs.

Portable native applications

Applications that cannot satisfy the static ELF contract can use the pinned nix-bundle backend:

let
  release = harbor-rs.lib.mkPortableBinaryRelease {
    inherit pkgs;
    pname = "my-app";
    version = "1.2.3";
    artifacts.x86_64-linux.entries.my-app.package = packages.my-app;
  };
in {
  packages.release-bundle = release.releaseBundle;
}

The resulting archive contains a self-extracting executable and a v2 manifest.json with format = "nix-bundle". Consumers use mkPortableReleaseBinaryPackage with a locked flake = false archive. The bundle remains dependent on the host kernel and hardware interfaces (for example GPU drivers or PipeWire), which must be smoke-tested before switching the production module.

Generic release bundles

Projects with more than one release format can use the format-neutral constructors. mkReleaseArtifact exposes one flat file, mkReleaseArchive stages named files into a deterministic tar.gz or zip, and mkReleaseBundle combines those outputs and writes one versioned *-release-manifest.json. The configured bundle set is the explicit input consumed by Simit’s [release.artifacts].nix_bundle_attrs list and must produce exactly one versioned manifest; project-specific build_commands remain additive for formats that need extra signing or installer work.

let
  archive = harbor-rs.lib.mkReleaseArchive {
    inherit pkgs;
    pname = "my-tool";
    version = "1.2.3";
    name = "my-tool-1.2.3-x86_64-linux.tar.gz";
    package = packages.my-tool;
    entries = {"bin/my-tool" = "bin/my-tool";};
    system = "x86_64-linux";
    rustTarget = "x86_64-unknown-linux-gnu";
  };
in
{
  packages.release-bundle = harbor-rs.lib.mkReleaseBundle {
    inherit pkgs;
    pname = "my-tool";
    version = "1.2.3";
    artifacts = {inherit archive;};
  };
}