From 41c3a425afd4cc5369ec734d222236b083ae04dc Mon Sep 17 00:00:00 2001
From: Jens Nolte <jens@nightmarestudio.de>
Date: Wed, 22 Jan 2020 02:24:25 +0100
Subject: [PATCH] Implement 'deploy <machine> iso'

---
 bin/deploy                | 18 ++++++++++++++++--
 nixos/configuration.nix   | 16 ++++++++--------
 nixos/machine-manager.nix | 32 ++++++++++++++++++++++++++++++--
 3 files changed, 54 insertions(+), 12 deletions(-)

diff --git a/bin/deploy b/bin/deploy
index 4c8c0ec..0928d8b 100755
--- a/bin/deploy
+++ b/bin/deploy
@@ -9,6 +9,7 @@ readonly cmdname=$(basename $0)
 
 
 nixos_system_file=$MACHINES_PATH/nixos.nix
+nixos_iso_file=$MACHINES_PATH/nixos_iso.nix
 
 # This script cannot run without the nixos configuration entry point
 if [[ ! -f "$nixos_system_file" ]]
@@ -21,7 +22,7 @@ fi
 source $DOTFILES_PATH/bin/lib/util.zsh
 
 usage() {
-  print "Usage: $cmdname [--via via_hostname] <hostname> [switch|boot|reboot|test|dry-activate|build]" >&2
+  print "Usage: $cmdname [--via via_hostname] <hostname> [switch|boot|reboot|test|dry-activate|build|iso]" >&2
 }
 
 positional=()
@@ -77,7 +78,7 @@ then
   operation="boot"
   set_profile=1
   reboot=1
-elif [[ "$operation" = "test" || "$operation" = "dry-activate" || "$operation" = "build" ]]
+elif [[ "$operation" = "test" || "$operation" = "dry-activate" || "$operation" = "build" || "$operation" = "iso" ]]
 then
   # pass
 else
@@ -97,6 +98,19 @@ fi
 readonly local_temp_dir=$(mktemp --tmpdir --directory phoenix-deploy.XXXXXXXXXX)
 trap "rm -rf $local_temp_dir" EXIT INT HUP TERM
 
+
+if [[ "$operation" = "iso" ]]
+then
+  print_info "Building iso image"
+  nix build --file "$MACHINES_PATH" --out-link "$local_temp_dir/nixos-iso-$hostname" "nixosIsoDerivations.$hostname"
+  readonly nixos_iso_path=$(realpath "$local_temp_dir/nixos-iso-$hostname")
+
+  print_info "Iso generated"
+  print $nixos_iso_path
+  exit 0
+fi
+
+
 print_info "Building target system configuration"
 nix build --file "$nixos_system_file" --argstr hostname "$hostname" --out-link "$local_temp_dir/nixos-config-$hostname"
 readonly nixos_config_path=$(realpath "$local_temp_dir/nixos-config-$hostname")
diff --git a/nixos/configuration.nix b/nixos/configuration.nix
index 5527f1f..1326590 100644
--- a/nixos/configuration.nix
+++ b/nixos/configuration.nix
@@ -1,5 +1,5 @@
 # This is the entry point for my NixOS configuration.
-{ name, path, channel }:
+{ name, path, channel, isIso }:
 { lib, config, pkgs, ... }:
 
 let
@@ -7,12 +7,11 @@ let
   dotfilesConfig = import (path + "/dotfiles.nix");
   layerImports = map (l: ./layers + "/${l}.nix") dotfilesConfig.layers;
 in
-{
+({
   imports = [
     ./modules
     (path + "/configuration.nix")
-    (path + "/hardware-configuration.nix")
-  ] ++ layerImports;
+  ] ++ layerImports ++ (lib.lists.optional (!isIso) (path + "/hardware-configuration.nix"));
 
   nixpkgs.config = {
     packageOverrides = ( import ./pkgs ) { inherit lib config; } ;
@@ -21,19 +20,20 @@ in
   # Pin channel in nix path
   nix.nixPath = [ "nixpkgs=${channel}" ];
 
+  # Default hostname ist machine directory name
+  networking.hostName = lib.mkDefault name;
+
+} // (lib.attrsets.optionalAttrs (!isIso) {
   # Bootloader
   boot.loader.systemd-boot.enable = (installResult.bootloader == "efi");
   boot.loader.efi.canTouchEfiVariables = (installResult.bootloader == "efi");
   boot.loader.grub.enable = (installResult.bootloader == "bios");
   boot.loader.grub.device = installResult.installedBlockDevice;
 
-  # Default hostname ist machine directory name
-  networking.hostName = lib.mkDefault name;
-
   boot.initrd.luks.devices = if installResult.luks then {
     cryptvol = {
       device = "/dev/disk/by-uuid/" + installResult.luksPartitionUuid;
       allowDiscards = true;
     };
   } else {};
-}
+}))
diff --git a/nixos/machine-manager.nix b/nixos/machine-manager.nix
index 6b21845..5445314 100644
--- a/nixos/machine-manager.nix
+++ b/nixos/machine-manager.nix
@@ -31,9 +31,9 @@ let
   machinesDirContents = readDir machinesDir;
   machineNames = filter (p: machinesDirContents.${p} == "directory") (attrNames machinesDirContents);
   withMachines = lambda: listToAttrs (map (m: {name = m; value = lambda { name = m; path = (machinesDir + "/${m}"); }; }) machineNames);
-  mkMachineConfig = { name, path }: (
+  mkMachineConfig = { name, path, isIso ? false }: (
     import ./configuration.nix {
-      inherit name path;
+      inherit name path isIso;
       channel = machineChannels.${name};
     }
   );
@@ -48,10 +48,38 @@ let
       };
     in
       nixos.system;
+  mkNixosIsoDerivation = { name, path }:
+    let
+      channel = machineChannels.${name};
+      configuration = { config, ... }:
+      {
+        imports = [
+          (mkMachineConfig { inherit name path; isIso = true; })
+          <nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix>
+          <nixpkgs/nixos/modules/profiles/all-hardware.nix>
+          <nixpkgs/nixos/modules/profiles/base.nix>
+        ];
+        isoImage.isoName = "${config.isoImage.isoBaseName}-${config.system.nixos.label}-isohost-${name}.iso";
+        isoImage.volumeID = substring 0 11 "NIXOS_ISO";
+
+        isoImage.makeEfiBootable = true;
+        isoImage.makeUsbBootable = true;
+        boot.loader.grub.memtest86.enable = true;
+
+      };
+      # Importing <nixpkgs/nixos> results in a nixos system closure
+      nixos = import "${channel}/nixos" {
+        system = "x86_64-linux";
+        inherit configuration;
+      };
+    in
+      nixos.config.system.build.isoImage;
+
 in
 {
   configurations = withMachines mkMachineConfig;
   nixosSystemDerivations = withMachines mkNixosSystemDerivation;
+  nixosIsoDerivations = withMachines mkNixosIsoDerivation;
   machineTemplates = withMachines ({name, path}: import (path + /template.nix));
   channels = machineChannels;
 }
\ No newline at end of file
-- 
GitLab