Is it possible to have nix install base system and desktop, reboot and then have it install everything else in the background?

Warning: I’m new and might be looking at it all wrong. :sweat_smile:

I’m in the process of making my NixOS installation process as reproducible and automated as possible:

  1. Boot from USB
  2. Fetch and run custom bash script
  3. Come back to a login prompt on a working system

The isuue: If connectivity is not great, installation process can take several hours. (I’m based in Russia)

The question: Is it possible to have nix install base system and desktop, reboot and then have it install everything else in the background? The idea is to start using it sooner.
Can I, maybe, set it to (after reboot) trigger a script that will modify configuration.nix and run nixos-rebuild switch? Or maybe you know of a better way to do this? Can it be done at all? :thinking:

Any info, tips are much appreciated. And do tell me if I’m just being an idiot too.:upside_down_face:
Thanks!

2 Likes

Let me try to understand your motivation.
You want to install a minimal system and then start using it right away. While you are using it, you want to install all the other configuration that you don’t immediately use. Is that correct?
Then I’d recommend to prepare your full config, but install it using the minimal one. Once it’s installed and booted, you can replace /etc/configuration.nix with your full config and trigger a rebuild while continuing to use the system.
So there’s no need to automatically trigger it, because you’re going to use the system anyways.

If you don’t immediately start using it, then you can just have the first install process install everything - you don’t need to split the installation process because you’re not using it.
Or is there something I’m missing?

1 Like

Hi likivik,

I’ve done exactly this myself by following:

For a more detailed working example, see my gist: NixOS ISO · GitHub

Build NixOS closure

What I do it is build a closure of the NixOS environment (see nixos.nix), which is what will eventually be installed to hard-drive automatically:

nix-build --attr system "./nixos.nix" -o result-closure

It is comprised of a pinned version of nixpkgs and imports a configuration.nix (which pulls in dependencies and configures the system).

Build ISO

Then I take this closure of my NixOS environment, and wrap it up into an NixOS installer ISO, which when you boot into it, automatically installs the closure to disk.

I create a NixOS environment for the NixOS installer ISO (see iso.nix), which imports the NixOS Live CD derivation, and pulls in the pre-build closure and install script by linking them into /etc/.

{ config, pkgs, ... }:

{
  imports = [
    # https://nixos.wiki/wiki/Creating_a_NixOS_live_CD
    <nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix>
    <nixpkgs/nixos/modules/installer/cd-dvd/channel.nix>
  ];

  # add the automated installation files
  environment.etc = {
    "install.sh" = {
      source = ./install.sh;
      mode = "0700";
    };
    "closure-nix-store-path.txt" = {
      source = ./closure-nix-store-path.txt;
    };
    "system" = {
      source = ./system;
    };
  };

I build the ISO, and take the result and dd it onto a USB stick, then boot into.

nix-build '<nixpkgs/nixos>' -A config.system.build.isoImage -I nixos-config=iso.nix -o result-iso

Once booted, I run the install script. The key part of the install script is how it adds the imported closure into the nix store (which will be in memory when you’re booted into the ISO), and then runs nix-install which writes it to disk.

echo "copy closure to nix store"
nix copy --from file:///etc/system $(cat /etc/closure-nix-store-path.txt) --option binary-caches "" --no-check-sigs

echo "install nix"
nixos-install --no-root-passwd --option binary-caches "" --system $(cat /etc/closure-nix-store-path.txt)

Note the /etc/closure-nix-store-path.txt - this is my hack remembering the location of the closure that I built outside of the ISO, and passing it to the ISO.

I hope this helps!

4 Likes

I like the way you build the binary closure and create an installation image out of it. I am curious though how do you manage the “partition the disk” part of the target machine?