Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Package in Nixpkgs for latest release tracking? #1235

Open
commiterate opened this issue Oct 15, 2024 · 0 comments
Open

Package in Nixpkgs for latest release tracking? #1235

commiterate opened this issue Oct 15, 2024 · 0 comments

Comments

@commiterate
Copy link

commiterate commented Oct 15, 2024

To make latest release tracking easier for Nix consumers, would it make sense to package the Determinate Nix Installer in Nixpkgs?

This probably sounds a bit weird, but doing so helps a use case for creating non-NixOS VM images with Nix installed.

For example, suppose we're trying to create a macOS Amazon Machine Image (AMI) for AWS EC2 where we want to use Nix as the package manager with Nix profiles to source gitlab-runner or github-runner (for use as CI/CD build hosts).

In this situation, we'd need to use EC2 Image Builder or HashiCorp Packer to build the macOS AMI. Both of these essentially launch an EC2 instance, run on-instance setup commands (either with SSM Agent + ssm:SendCommand or SSH), create an AMI from the instance, and terminate it.

We can alternatively use an EC2 user data script that's run on instance launch. May be required for macOS to work around Nix being installed to the instance store instead of the root volume.

To make these images reproducible, we'd want to lock the specific Determinate Nix Installer and Nixpkgs (for the flake registry) versions in the on-instance setup commands. For example:

# Install Nix with the Determinate Nix Installer.
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix/tag/v0.27.0 | sh -s -- install --no-confirm
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh

# Pin Nixpkgs in the flake registry.
nix registry add nixpkgs github:NixOS/nixpkgs/ef7226d68ba45b2de3e428e5d4bb4532caffec7b

# Install packages.
nix profile install nixpkgs#gitlab-runner nixpkgs#tart nixpkgs#openssh

# ...

If we're using infrastructure-as-code (IaC) with Nix in the IaC repository for development shells, we might have a flake like this:

flake.nix

{
  inputs = {
    nixpkgs = {
      type = "github";
      owner = "NixOS";
      repo = "nixpkgs";
      ref = "nixos-unstable";
    };
  };

  outputs =
    {
      self,
      nixpkgs,
    }:
    let
      # Systems to provide outputs for.
      systems = [
        "x86_64-linux"
        "aarch64-linux"
        "x86_64-darwin"
        "aarch64-darwin"
      ];

      # A function that creates an attribute set and provides a system-specific nixpkgs for each system.
      forEachSystem =
        f:
        nixpkgs.lib.genAttrs systems (
          system:
          f {
            pkgs = import nixpkgs {
              inherit system;
            };
          }
        );
    in
    {
      devShells = forEachSystem (
        { pkgs }:
        {
          default = pkgs.mkShell {
            packages = with pkgs; [
              # ...
            ];

            shellHook = ''
              # Nix.
              #
              # For pinning Nix in AMIs.
              export DETERMINATE_NIX_INSTALLER_VERSION=v0.27.0
              export NIXPKGS_FLAKE_REFERENCE=github:NixOS/nixpkgs/${nixpkgs.rev}
            '';
          };
        }
      );
    };
}

We'd then make our infrastructure code substitute the DETERMINATE_NIX_INSTALLER_VERSION and NIXPKGS_FLAKE_REFERENCE environment variables into the on-instance setup commands script our IaC setup deploys (i.e. bakes them in at build time).

For example:

# Install Nix with the Determinate Nix Installer.
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix/tag/${DETERMINATE_NIX_INSTALLER_VERSION} | sh -s -- install --no-confirm
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh

# Pin Nixpkgs in the flake registry.
nix registry add nixpkgs ${NIXPKGS_FLAKE_REFERENCE}

# Same as before.
# ...

The above flake, however, hardcodes the latest Determinate Nix Installer release. We'd instead like to make it a flake input like Nixpkgs so that a nix flake update will automatically update the version.

One option is to directly make this repository's flake an input. For example:

flake.nix

{
  inputs = {
    # ...

    nix-installer = {
      type = "github";
      owner = "DeterminateSystems";
      repo = "nix-installer";
      # We don't want to track a specific Git tag ref since we won't get updates automatically.
      ref = "main";
    };
  };

  outputs =
    {
      self,
      nixpkgs,
      nix-installer,
    }:
    let
      # ...

      forEachSystem =
        f:
        nixpkgs.lib.genAttrs systems (
          system:
          f {
            # ...

            installer = nix-installer.packages.${system}.default;
          }
        );
    in
    {
      devShells = forEachSystem (
        { pkgs, installer }:
        {
          default = pkgs.mkShell {
            packages = with pkgs; [
              # ...
            ];

            shellHook = ''
              # Nix.
              #
              # For pinning Nix in AMIs.
              export DETERMINATE_NIX_INSTALLER_VERSION=v${installer.version}
              export NIXPKGS_FLAKE_REFERENCE=github:NixOS/nixpkgs/${nixpkgs.rev}
            '';
          };
        }
      );
    };
}

This, however, can create problems when the Determinate Nix Installer team is in the middle of bumping the version. For example:

  • Determinate Nix Installer's main branch version is bumped (e.g. v0.27.0 to v1.0.0).
  • ⛔️ Consumer does a nix flake update.
    • Their builds now incorrectly think the v1.0.0 release exists.
    • AMI builds fail.
  • Determinate Nix Installer's v1.0.0 tag is created.
  • ⛔️ Consumer does a nix flake update.
    • Their builds now incorrectly think the v1.0.0 release exists.
    • AMI builds fail.
  • Determinate Nix Installer's v1.0.0 release is created.
  • ✅ Consumer does a nix flake update.
    • AMI builds succeed.

If the Determinate Nix Installer is in Nixpkgs, however, its package version determined from Nixpkgs would always point to a release that exists (ignoring release revocations and bypassing failed Nixpkgs PR checks). Consumers can just do a nix flake update as usual and automatically get the latest version.

For example, the flake would look like this:

flake.nix

{
  inputs = {
    # Pretend the Determinate Nix Installer's package name is `determinate-nix-installer`.
    nixpkgs = {
      type = "github";
      owner = "NixOS";
      repo = "nixpkgs";
      ref = "nixos-unstable";
    };
  };

  outputs =
    {
      self,
      nixpkgs,
    }:
    let
      # Systems to provide outputs for.
      systems = [
        "x86_64-linux"
        "aarch64-linux"
        "x86_64-darwin"
        "aarch64-darwin"
      ];

      # A function that creates an attribute set and provides a system-specific nixpkgs for each system.
      forEachSystem =
        f:
        nixpkgs.lib.genAttrs systems (
          system:
          f {
            pkgs = import nixpkgs {
              inherit system;
            };
          }
        );
    in
    {
      devShells = forEachSystem (
        { pkgs }:
        {
          default = pkgs.mkShell {
            packages = with pkgs; [
              # ...
            ];

            shellHook = ''
              # Nix.
              #
              # For pinning Nix in AMIs.
              export DETERMINATE_NIX_INSTALLER_VERSION=v${pkgs.determinate-nix-installer.version}
              export NIXPKGS_FLAKE_REFERENCE=github:NixOS/nixpkgs/${nixpkgs.rev}
            '';
          };
        }
      );
    };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant