nh (Yet Another Nix Helper)

repository·master·Indexed 25 days ago

https://github.com/nix-community/nh

A modern, unified CLI utility designed to consolidate and improve the ergonomics of Nix, NixOS, Home Manager, and Nix-Darwin workflows. It provides a cohesive interface with features such as build-tree visualization, fast diffing, improved garbage collection via `nh clean`, and a powerful search tool for packages and options. It includes a Rust-based `NixCommand` builder API for constructing and executing Nix subcommands with streaming or captured output.

Tokens
16.1K
Snippets
19
Records
118
Agent score
83%

What's inside nh

  1. Perform remote deployments with nh

    master

    NH supports remote deployments using two primary flags to control where work happens:

    • --build-host X: The host where the configuration is built (via nix copy + nix build).
    • --target-host Y: The host where the result is deployed and activated.

    Note: Derivation evaluation always happens locally. If --target-host is provided without --hostname or -H, the hostname defaults to the value in --target-host.

    Flags usedBuild locationActivation location
    nonelocalhostlocalhost
    --build-host XXlocalhost
    --target-host YlocalhostY
    --build-host X --target-host YXY
    --build-host Y --target-host YYY
  2. Install NH

    master

    You can install or try NH using nix shell. Use the stable version from nixpkgs for most use cases, or the development version from the GitHub flake for the latest features.

    nix shell nixpkgs#nh # stable
    nix shell github:nix-community/nh # dev
  3. Construct and run Nix commands with the `nix-command` builder API

    master

    Use the NixCommand builder API to construct Nix subcommands (like build, shell, etc.) with predefined defaults. You can chain methods to configure arguments, environment variables, impurity, interactivity, build log printing, and timeouts.

    Supported CommandKind variants include:

    • build: Includes --print-build-logs, no interactive mode.
    • develop: Includes --print-build-logs, supports interactive mode.
    • eval: No default flags, no interactive mode.
    • flake: No default flags, no interactive mode.
    • run: Includes --print-build-logs, supports interactive mode.
    • shell: Includes --print-build-logs, supports interactive mode.
    use nix_command::{CommandKind, NixCommand};
    
    // Build a command
    let cmd = NixCommand::new(CommandKind::Build)
        .arg("nixpkgs#hello")
        .impure(true);
    
    // Inspect the argv
    assert_eq!(cmd.argv(), [
        "nix", "build", "--print-build-logs", "--impure", "nixpkgs#hello"
    ]);
    
    // Run with streaming output
    let status = cmd.run_with_logs()?;
    assert!(status.success());
    
    // Or capture output
    let output = cmd.output()?;
    let stdout = String::from_utf8_lossy(&output.stdout);
  4. Enable Specialisation support for NixOS

    master

    To allow NH to detect and run the proper activation script for a NixOS specialisation, you must write the name of the specialisation to /etc/specialisation.

    Example configuration:

    {config, pkgs, ...}: {
      specialisation."foo".configuration = {
        environment.etc."specialisation".text = "foo";
        # ..rest of config
      };
    
      specialisation."bar".configuration = {
        environment.etc."specialisation".text = "bar";
        # ..rest of config
      };
    }
  5. Switch NixOS configurations with NH

    master

    NH supports both Nix flakes and classical NixOS configurations (channels/manual pinning).

    • For Flakes: Use nh os switch /path/to/flake.
    • For Classical Configurations:
      • Use nh os switch -f '<nixpkgs/nixos>'.
      • If your configuration is in a non-default location, use: nh os switch -f '<nixpkgs/nixos>' -- -I nixos-config=/path/to/configuration.nix.

    Refer to nh os --help or man 1 nh for more details and environment variable defaults.

  6. Manage NixOS, Home Manager, and Darwin configurations with platform subcommands

    master

    NH provides specialized subcommands to replace standard rebuild scripts, adding features like build-tree displays (via nom), pretty diffs (via dix), and user confirmations.

    Subcommands

    • nh os: Replaces nixos-rebuild. Use for NixOS systems.
    • nh home: Replaces home-manager. Use for Home Manager configurations.
    • nh darwin: Replaces darwin-rebuild. Use for macOS/nix-darwin systems.

    Usage Patterns

    Flake-based switching:

    • NixOS: nh os switch . -H <hostname>
    • Darwin: nh darwin switch . -H <hostname>
    • Home Manager: nh home switch . -c <configuration-name>

    Automation & Environment Variables:

    • Omitting Flake Path: If NH_FLAKE is set, you can omit the path (e.g., nh os switch). This is automatically handled if programs.nh.flake is set in your NixOS/Home Manager modules.
    • Omitting Hostname/Config: NH can autodiscover the hostname (-H) or configuration (-c) if NH_FLAKE or NH_OS_FLAKE is set.
    • Non-Flake Configs: Use NH_FILE (path to Nix file) and NH_ATTRP (Nix attribute path) to specify non-flake configurations. nh os switch will evaluate $NH_FILE#$NH_ATTRP.
  7. Enable Specialisation support for Home Manager

    master

    To enable specialisation detection for Home Manager, write the specialisation name to ~/.local/share/home-manager/specialisation.

    Example configuration:

    {config, pkgs, ...}: {
      specialisation."foo".configuration = {
        xdg.dataFile."home-manager/specialisation".text = "foo";
        # ..rest of config
      };
    
      specialisation."bar".configuration = {
        xdg.dataFile."home-manager/specialisation".text = "bar";
        # ..rest of config
      };
    }
  8. Configure NH as a NixOS service

    master

    NH provides a NixOS module that allows you to integrate nh clean as a service. This is useful for automated garbage collection. You can specify retention policies via clean.extraArgs and point to your configuration flake via flake (which sets the NH_OS_FLAKE environment variable).

    {
      programs.nh = {
        enable = true;
        clean.enable = true;
        clean.extraArgs = "--keep-since 4d --keep 3";
        flake = "/home/user/my-nixos-config"; # sets NH_OS_FLAKE variable for you
      };
    }
  9. Configure remote deployment environment variables

    master

    Use the following environment variables to control remote deployment behavior:

    • NH_REMOTE_CLEANUP: When set to 1, true, or yes, nh attempts to terminate remote Nix processes using pkill if you press Ctrl+C. This is opt-in and depends on pkill being available on the remote host.
    • NH_NO_VALIDATE: When set to 1, skips pre-activation system validation checks. This is useful when the target host's store path is not accessible from the local machine (e.g., when building remotely and deploying to a different target).
    • NH_SSHOPTS: Passes additional SSH options to the connection. Takes precedence over NIX_SSHOPTS.
    # Enable remote cleanup
    export NH_REMOTE_CLEANUP=1
    nh os switch --build-host user@buildserver
    
    # Skip validation for remote-to-remote deployments
    export NH_NO_VALIDATE=1
    nh os switch --build-host user@buildserver --target-host user@production
  10. Use `nh search` to find packages, options, and more

    master

    The nh search command allows you to search for Nix packages, NixOS/home-manager options, GitHub pull requests, and issues. You can use explicit subcommands or shorthand syntax.

    Search Modes

    • Packages: Search for Nix packages via search.nixos.org.
    • Options: Search for NixOS or home-manager options via search.nixos.org.
    • Offline: Search local SPAM database files without network access.
    • Prs: Search Nixpkgs pull requests.
    • Issues: Search Nixpkgs issues.

    Shorthand Usage

    You can omit the subcommand if you provide a query. The mode is determined by the --default-search flag (defaults to packages).

    # Search for packages (default)
    nh search hello
    
    # Search for options using shorthand
    nh search --default-search options hello
  11. Use NH_FLAKE instead of FLAKE

    master

    To avoid deprecation warnings, use the NH_FLAKE environment variable to specify your flake path. You can also use more specific variables to avoid global overrides:

    • NH_OS_FLAKE (for OS-specific commands)
    • NH_HOME_FLAKE (for Home Manager commands)
    • NH_DARWIN_FLAKE (for Darwin commands)