Creating a NixOS live CD: Difference between revisions

From NixOS Wiki
imported>Sh4r3m4n
Fix SSH configuration typo (it produced a syntax error)
m →‎Static IP Address: Changed networking.interfaces.eth0.ip4 to networking.interfaces.eth0.ipv4.addresses to be consistent with the current proper usage ( as of 24.05 )
 
(26 intermediate revisions by 13 users not shown)
Line 1: Line 1:
==Motivation==
<translate>
== Motivation == <!--T:19-->
 
<!--T:33-->
Creating a modified NixOS LiveCD out of an existing working NixOS installation has a number of benefits:
Creating a modified NixOS LiveCD out of an existing working NixOS installation has a number of benefits:
<!--T:34-->
* Ensures authenticity.
* Ensures authenticity.
<!--T:35-->
* No need for internet access.
* No need for internet access.
<!--T:36-->
* It is easy to add your own packages and configuration changes to the image.
* It is easy to add your own packages and configuration changes to the image.


==Building==
== Building == <!--T:20-->
 
<!--T:37-->
Building minimal NixOS installation CD with the <code>nix-build</code> command by creating this <code>iso.nix</code>-file. In this example with [[Neovim]] preinstalled.


Create a file <tt>iso.nix</tt>:
</translate>
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
# This module defines a small NixOS installation CD.  It does not
{ config, pkgs, ... }:
# contain any graphical stuff.
{config, pkgs, ...}:
{
{
   imports = [
   imports = [
Line 20: Line 30:
     <nixpkgs/nixos/modules/installer/cd-dvd/channel.nix>
     <nixpkgs/nixos/modules/installer/cd-dvd/channel.nix>
   ];
   ];
  environment.systemPackages = [ pkgs.neovim ];
}
}
</syntaxhighlight>
</syntaxhighlight>
<translate>


<!--T:21-->
Build the image via:
Build the image via:


</translate>
<syntaxhighlight lang="bash">
<syntaxhighlight lang="bash">
nix-build '<nixpkgs/nixos>' -A config.system.build.isoImage -I nixos-config=iso.nix
nix-build '<nixpkgs/nixos>' -A config.system.build.isoImage -I nixos-config=iso.nix
</syntaxhighlight>
</syntaxhighlight>
<translate>
<!--T:22-->
Alternatively, use Nix [[Flakes]] to generate a ISO installation image, using the <code>nixos-24.05</code> branch as nixpkgs source:


</translate>
{{file|flake.nix|nix|<nowiki>
{
  description = "Minimal NixOS installation media";
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
  outputs = { self, nixpkgs }: {
    nixosConfigurations = {
      exampleIso = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [
          ({ pkgs, modulesPath, ... }: {
            imports = [ (modulesPath + "/installer/cd-dvd/installation-cd-minimal.nix") ];
            environment.systemPackages = [ pkgs.neovim ];
          })
        ];
      };
    };
  };
}
</nowiki>}}
<translate>
<!--T:23-->
The following commands will generate the iso-image:
</translate>
<syntaxhighlight lang="console">
# git init
# git add flake.nix
# nix build .#nixosConfigurations.exampleIso.config.system.build.isoImage
</syntaxhighlight>
<translate>
<!--T:24-->
The resulting image can be found in <code>result</code>:
The resulting image can be found in <code>result</code>:


</translate>
<syntaxhighlight lang="console">
<syntaxhighlight lang="console">
$ ls result/iso/
$ ls result/iso/
nixos-17.09.git.158ec57-x86_64-linux.iso
nixos-24.05.20240721.63d37cc-x86_64-linux.iso
</syntaxhighlight>
<translate>
 
=== Testing the image === <!--T:7-->
 
<!--T:38-->
To inspect the contents of the ISO image:
 
</translate>
<syntaxhighlight lang="console">
$ mkdir mnt
$ sudo mount -o loop result/iso/nixos-*.iso mnt
$ ls mnt
boot  EFI  isolinux  nix-store.squashfs  version.txt
$ umount mnt
</syntaxhighlight>
<translate>
 
<!--T:25-->
To boot the ISO image in an emulator:
 
</translate>
<syntaxhighlight lang="console">
$ nix-shell -p qemu
$ qemu-system-x86_64 -enable-kvm -m 256 -cdrom result/iso/nixos-*.iso
</syntaxhighlight>
</syntaxhighlight>
<translate>


===SSH=== <!--T:26-->


===SSH===
<!--T:39-->
In your <tt>iso.nix</tt>:
In your <tt>iso.nix</tt>:


</translate>
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
{
{
   ...
   ...
   # Enable SSH in the boot process.
   # Enable SSH in the boot process.
   systemd.services.sshd.wantedBy = lib.mkForce [ "multi-user.target" ];
   systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ];
   users.users.root.openssh.authorizedKeys.keys = [
   users.users.root.openssh.authorizedKeys.keys = [
     "ssh-ed25519 AaAeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee username@host"
     "ssh-ed25519 AaAeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee username@host"
Line 51: Line 132:
}
}
</syntaxhighlight>
</syntaxhighlight>
<translate>


===Static IP Address===
===Static IP Address=== <!--T:11-->


<!--T:40-->
Static IP addresses can be set in the image itself. This can be useful for VPS installation.
Static IP addresses can be set in the image itself. This can be useful for VPS installation.


<syntaxhighlight lang="nix">
</translate>
<syntaxhighlight lang="nix" line="1">
{
{
   ...
   ...
   networking = {
   networking = {
     usePredictableInterfaceNames = false;
     usePredictableInterfaceNames = false;
     interfaces.eth0.ip4 = [{
     interfaces.eth0.ipv4.addresses = [{
       address = "64.137.201.46";
       address = "64.137.201.46";
       prefixLength = 24;
       prefixLength = 24;
     }];
     }];
     defaultGateway = "64.137.201.1";
     defaultGateway = "64.137.201.1";
     nameServers = [ "8.8.8.8" ];
     nameservers = [ "8.8.8.8" ];
   };
   };
   ...
   ...
}
}
</syntaxhighlight>
</syntaxhighlight>
<translate>
=== Building faster === <!--T:27-->
<!--T:41-->
The build process is slow because of compression.


<!--T:28-->
Here are some timings for <code>nix-build</code>:


===ZFS Support===
<!--T:29-->
{| class="wikitable" style="margin:auto"
|+ Compression results
|-
! squashfsCompression !! Time !! Size
|-
| <code>lz4</code> || 100s || 59%
|-
| <code>gzip -Xcompression-level 1</code> || 105s || 52%
|-
| <code>gzip</code> || 210s || 49%
|-
| <code>xz -Xdict-size 100%</code> (default) || 450s || 43%
|}


NixOS ISOs do not contain ZFS tools and kernel modules by default. They can be added via:
<!--T:30-->
See also: [https://gist.github.com/baryluk/70a99b5f26df4671378dd05afef97fce mksquashfs benchmarks]


<!--T:31-->
If you don't care about file size, you can use a faster compression
by adding this to your <code>iso.nix</code>:
</translate>
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
{
{
   ...
   isoImage.squashfsCompression = "gzip -Xcompression-level 1";
  boot.supportedFilesystems = [ "zfs" ];
  ...
}
}
</syntaxhighlight>
</syntaxhighlight>
<translate>
==See also== <!--T:32-->


==See also==
<!--T:42-->
* [https://nixos.org/nixos/manual/index.html#sec-building-cd NixOS Manual: Building your own CD].
* [https://nixos.org/manual/nixos/stable/index.html#sec-building-image NixOS Manual: Building a NixOS (Live) ISO].
</translate>


[[Category:NixOS]]
[[Category:NixOS]]
[[Category:Installation]]
[[Category:Deployment]]
[[Category:Deployment]]
[[Category:Guide]]
[[Category:Cookbook]]

Latest revision as of 21:33, 1 August 2024

Motivation

Creating a modified NixOS LiveCD out of an existing working NixOS installation has a number of benefits:

  • Ensures authenticity.
  • No need for internet access.
  • It is easy to add your own packages and configuration changes to the image.

Building

Building minimal NixOS installation CD with the nix-build command by creating this iso.nix-file. In this example with Neovim preinstalled.

{ config, pkgs, ... }:
{
  imports = [
    <nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix>

    # Provide an initial copy of the NixOS channel so that the user
    # doesn't need to run "nix-channel --update" first.
    <nixpkgs/nixos/modules/installer/cd-dvd/channel.nix>
  ];
  environment.systemPackages = [ pkgs.neovim ];
}

Build the image via:

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

Alternatively, use Nix Flakes to generate a ISO installation image, using the nixos-24.05 branch as nixpkgs source:

flake.nix
{
  description = "Minimal NixOS installation media";
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
  outputs = { self, nixpkgs }: {
    nixosConfigurations = {
      exampleIso = nixpkgs.lib.nixosSystem {
        system = "x86_64-linux";
        modules = [
          ({ pkgs, modulesPath, ... }: {
            imports = [ (modulesPath + "/installer/cd-dvd/installation-cd-minimal.nix") ];
            environment.systemPackages = [ pkgs.neovim ];
          })
        ];
      };
    };
  };
}

The following commands will generate the iso-image:

# git init
# git add flake.nix
# nix build .#nixosConfigurations.exampleIso.config.system.build.isoImage

The resulting image can be found in result:

$ ls result/iso/
nixos-24.05.20240721.63d37cc-x86_64-linux.iso

Testing the image

To inspect the contents of the ISO image:

$ mkdir mnt
$ sudo mount -o loop result/iso/nixos-*.iso mnt
$ ls mnt
boot  EFI  isolinux  nix-store.squashfs  version.txt
$ umount mnt

To boot the ISO image in an emulator:

$ nix-shell -p qemu
$ qemu-system-x86_64 -enable-kvm -m 256 -cdrom result/iso/nixos-*.iso

SSH

In your iso.nix:

{
  ...
  # Enable SSH in the boot process.
  systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ];
  users.users.root.openssh.authorizedKeys.keys = [
    "ssh-ed25519 AaAeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee username@host"
  ];
  ...
}

Static IP Address

Static IP addresses can be set in the image itself. This can be useful for VPS installation.

{
  ...
  networking = {
    usePredictableInterfaceNames = false;
    interfaces.eth0.ipv4.addresses = [{
      address = "64.137.201.46";
      prefixLength = 24;
    }];
    defaultGateway = "64.137.201.1";
    nameservers = [ "8.8.8.8" ];
  };
  ...
}

Building faster

The build process is slow because of compression.

Here are some timings for nix-build:

Compression results
squashfsCompression Time Size
lz4 100s 59%
gzip -Xcompression-level 1 105s 52%
gzip 210s 49%
xz -Xdict-size 100% (default) 450s 43%

See also: mksquashfs benchmarks

If you don't care about file size, you can use a faster compression by adding this to your iso.nix:

{
  isoImage.squashfsCompression = "gzip -Xcompression-level 1";
}

See also