nix-installer
is an opinionated alternative to the official Nix install scripts.
bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
The nix-installer
tool is ready to use in a number of environments:
| Platform | Multi User | root
only | Maturity |
|------------------------------|:------------------:|:-----------:|:-----------------:|
| Linux (x8664 & aarch64) | ✓ (via [systemd]) | ✓ | Stable |
| MacOS (x8664 & aarch64) | ✓ | | Stable (See note) |
| Valve Steam Deck (SteamOS) | ✓ | | Stable |
| WSL2 (x86_64 & aarch64) | ✓ (via [systemd]) | ✓ | Stable |
| Podman Linux Containers | ✓ (via [systemd]) | ✓ | Stable |
| Docker Containers | | ✓ | Stable |
| Linux (i686) | ✓ (via [systemd]) | ✓ | Unstable |
Note On MacOS only, removing users and/or groups may fail if there are no users who are logged in graphically.
Differing from the current official Nix installer scripts:
nix.conf
:
nix-command
and flakes
features are enabledbash-prompt-prefix
is setauto-optimise-store
is set to true
extra-nix-path
is set to nixpkgs=flake:nixpkgs
/nix/receipt.json
as well as a copy of the install binary at /nix/nix-installer
nix-channel --update
is not run, ~/.nix-channels
is not provisionedNIX_SSL_CERT_FILE
is set in the various shell profiles if the ssl-cert-file
argument is used.The current Nix install scripts do an excellent job, however they are difficult to maintain. Subtle differences in the shell implementations and certain characteristics of bash scripts make it difficult to make meaningful changes to the installer.
Our team wishes to experiment with the idea of an installer in a more structured language and see if this is a worthwhile alternative. Along the way, we are also exploring a few other ideas, such as:
So far, our explorations have been quite fruitful, so we wanted to share and keep exploring.
Install Nix with the default planner and options:
bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
Or, to download a platform specific Installer binary yourself:
bash
$ curl -sL -o nix-installer https://install.determinate.systems/nix/nix-installer-x86_64-linux
$ chmod +x nix-installer
Note
nix-installer
will elevate itself if needed usingsudo
. If you usedoas
orplease
you may need to elevatenix-installer
yourself.
nix-installer
installs Nix by following a plan made by a planner. Review the available planners:
```bash $ ./nix-installer install --help Execute an install (possibly using an existing plan)
To pass custom options, select a planner, for example nix-installer install linux-multi --help
Usage: nix-installer install [OPTIONS] [PLAN]
nix-installer install
Commands: linux A planner for Linux installs steam-deck A planner suitable for the Valve Steam Deck running SteamOS help Print this message or the help of the given subcommand(s)
```
Planners have their own options and defaults, sharing most of them in common:
```bash $ ./nix-installer install linux --help A planner for Linux installs
Usage: nix-installer install linux [OPTIONS]
Options:
--nix-build-group-name <NIX_BUILD_GROUP_NAME>
The Nix build group name
[env: NIX_INSTALLER_NIX_BUILD_GROUP_NAME=]
[default: nixbld]
--nix-build-group-id <NIX_BUILD_GROUP_ID>
The Nix build group GID
[env: NIX_INSTALLER_NIX_BUILD_GROUP_ID=]
[default: 3000]
```
Planners can be configured via environment variable or command arguments:
```bash $ curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | NIXBUILDGROUP_NAME=nixbuilder sh -s -- install linux-multi --nix-build-group-id 4000
$ NIXBUILDGROUP_NAME=nixbuilder ./nix-installer install linux-multi --nix-build-group-id 4000 ```
You can remove a nix-installer
-installed Nix by running
bash
/nix/nix-installer uninstall
You can use the nix-installer-action
Github Action like so:
```yaml on: pull_request: push: branches: [main]
jobs:
lints:
name: Build
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
- name: Run nix build
run: nix build .
```
Warning When
--init none
is used, onlyroot
or users who can elevate toroot
privileges can run Nix:
bash sudo -i nix run nixpkgs#hello
If you don't use [systemd], you can still install Nix by explicitly specifying the linux
plan and --init none
:
bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux --init none
In Docker/Podman containers or WSL2 instances where an init (like systemd
) is not present, pass --init none
.
Warning When
--init none
is used, onlyroot
or users who can elevate toroot
privileges can run Nix:
bash sudo -i nix run nixpkgs#hello
For Docker containers (without an init):
```dockerfile
FROM ubuntu:latest RUN apt update -y RUN apt install curl -y COPY nix-installer /nix-installer RUN /nix-installer install linux --init none --no-confirm ENV PATH="${PATH}:/nix/var/nix/profiles/default/bin" RUN nix run nixpkgs#hello ```
Podman containers require sandbox = false
in your Nix.conf
.
For podman containers without an init:
```dockerfile
FROM ubuntu:latest RUN apt update -y RUN apt install curl -y COPY nix-installer /nix-installer RUN /nix-installer install linux --extra-conf "sandbox = false" --init none --no-confirm ENV PATH="${PATH}:/nix/var/nix/profiles/default/bin" RUN nix run nixpkgs#hello ```
For Podman containers with a systemd init:
```dockerfile
FROM ubuntu:latest RUN apt update -y RUN apt install curl systemd -y COPY nix-installer /nix-installer RUN /nix-installer install linux --extra-conf "sandbox = false" --no-start-daemon --no-confirm ENV PATH="${PATH}:/nix/var/nix/profiles/default/bin" RUN nix run nixpkgs#hello CMD [ "/usr/sbin/init" ] ```
If systemd is enabled it's possible to install Nix as normal using the command at the top of this document:
bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
If systemd is not enabled, pass --init none
at the end of the command:
Warning When
--init none
is used, onlyroot
or users who can elevate toroot
privileges can run Nix:
bash sudo -i nix run nixpkgs#hello
bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux --init none
If you'd like to bypass the confirmation step, you can apply the --no-confirm
flag:
bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install --no-confirm
This is especially useful when using the installer in non-interactive scripts.
Since you'll be using nix-installer
to install Nix on systems without Nix, the default build is a static binary.
Build a portable Linux binary on a system with Nix:
```bash
nix build -L ".#nix-installer-static"
nix build -L "github:determinatesystems/nix-installer#nix-installer-static"
export NIXINSTALLERTAG="v0.6.0" nix build -L "github:determinatesystems/nix-installer/$NIXINSTALLERTAG#nix-installer-static" ```
On Mac:
```bash
nix build -L ".#nix-installer"
nix build -L "github:determinatesystems/nix-installer#nix-installer"
export NIXINSTALLERTAG="v0.6.0" nix build -L "github:determinatesystems/nix-installer/$NIXINSTALLERTAG#nix-installer" ```
Then copy the result/bin/nix-installer
to the machine you wish to run it on.
You can also add nix-installer
to a system without Nix via cargo
:
```bash
RUSTFLAGS="--cfg tokio_unstable" cargo run -- --help
RUSTFLAGS="--cfg tokio_unstable" cargo install --git https://github.com/DeterminateSystems/nix-installer nix-installer --help
export NIXINSTALLERTAG="v0.6.0" RUSTFLAGS="--cfg tokiounstable" cargo install --git https://github.com/DeterminateSystems/nix-installer --tag $NIXINSTALLER_TAG nix-installer --help ```
To make this build portable, pass --target x86_64-unknown-linux-musl
.
Note We currently require
--cfg tokio_unstable
as we utilize Tokio's process groups, which wrap stablestd
APIs, but are unstable due to it requiring an MSRV bump.
Warning Use as a library is still experimental, if you're using this, please let us know and we can make a path to stablization.
Add nix-installer
to your dependencies:
bash
cargo add nix-installer
If you are building a CLI, check out the cli
feature flag for clap
integration.
You'll also need to edit your .cargo/config.toml
to use tokio_unstable
as we utilize Tokio's process groups, which wrap stable std
APIs, but are unstable due to it requiring an MSRV bump:
```toml
[build] rustflags=["--cfg", "tokio_unstable"] ```
Then it's possible to review the documentation:
bash
cargo doc --open -p nix-installer
Documentation is also available via nix
build:
bash
nix build github:DeterminateSystems/nix-installer#nix-installer.doc
firefox result-doc/nix-installer/index.html
While nix-installer
tries to provide a comprehensive and unquirky experience, there are unfortunately some issues which may require manual intervention or operator choices.
$PATH
When connecting to a Mac remote SSH builder users may sometimes see this error:
bash
$ nix store ping --store "ssh://$USER@$HOST"
Store URL: ssh://$USER@$HOST
zsh:1: command not found: nix-store
error: cannot connect to '$USER@$HOST'
The way MacOS populates the PATH
environment differs from other environments. (Some background)
There are two possible workarounds for this:
remote-program
parameter pointing to nix-store
. For example:
bash
nix store ping --store "ssh://$USER@$HOST?remote-program=/nix/var/nix/profiles/default/bin/nix-store"
If you are unsure where the nix-store
binary is located, run which nix-store
on the remote.Update /etc/zshenv
on the remote so that zsh
populates the Nix path for every shell, even those that are neither interactive or login:
```bash
if [ -e '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' ]; then . '/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh' fi
```
This strategy has some behavioral caveats, namely,
$PATH
may have unexpected contents
For example, if $PATH
gets unset then a script invoked, $PATH
may not be as empty as expected:
```bash
$ cat example.sh
echo $PATH
$ PATH= ./example.sh
/Users/ephemeraladmin/.nix-profile/bin:/nix/var/nix/profiles/default/bin:
``
This strategy results in Nix's paths being present on
$PATH` twice and may have a minor impact on performance.
The goal of the Determinate Nix Installer is to successfully and correctly install Nix.
The curl | sh
pipeline and the installer collects a little bit of diagnostic information to help us make that true.
Here is a table of the diagnostic data we collect:
| Field | Use |
| --------------------- | ----------------------------------------------------------------------------------------------------- |
| version
| The version of the Determinate Nix Installer. |
| planner
| The method of installing Nix (linux
, macos
, steam-deck
) |
| configured_settings
| The names of planner settings which were changed from their default. Does not include the values. |
| os_name
| The running operating system. |
| os_version
| The version of the operating system. |
| triple
| The architecture/operating system/binary format of your system. |
| is_ci
| Whether the installer is being used in CI (e.g. GitHub Actions). |
| action
| Either Install
or Uninstall
. |
| status
| One of Success
, Failure
, Pending
, or Cancelled
. |
| failure_chain
| A high level description of what the failure was, if any. For example: Command("diskutil")
if the command diskutil list
failed. |
To disable diagnostic reporting, set the diagnostics URL to an empty string by passing --diagnostic-endpoint=""
or setting NIX_INSTALLER_DIAGNOSTIC_ENDPOINT=""
.
You can read the full privacy policy for Determinate Systems, the creators of the Determinate Nix Installer, here.