This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

tools.build-installer-iso: add structured configuration support

+239 -81
+91 -15
tools/build-installer-iso/build-installer-iso.sh
··· 5 5 # Default values 6 6 OUTPUT="installer.iso" 7 7 ARCH="x86_64-linux" # Default to x86_64-linux for cross-compilation 8 - VARS_DIR="" 8 + CONFIG_DIR="" 9 + FLAKE_URL="" 9 10 10 11 usage() { 11 12 cat <<EOF 12 13 Usage: $0 [OPTIONS] 13 14 14 - Build a NixOS installer ISO with custom vars appended. 15 + Build a NixOS installer ISO with custom configuration. 15 16 16 17 OPTIONS: 17 18 -o, --output FILE Output ISO file (default: installer.iso) 18 19 -a, --arch ARCH Architecture: x86_64-linux or aarch64-linux (default: x86_64-linux) 19 - -v, --vars DIR Directory containing vars to append to ISO 20 + -c, --config DIR Configuration directory containing installer-config.json and files/ 21 + -f, --flake URL Flake URL to install automatically (creates minimal config) 20 22 -h, --help Show this help message 21 23 22 - EXAMPLE: 23 - $0 -o my-installer.iso -v ./my-vars -a x86_64-linux 24 + EXAMPLES: 25 + $0 -o my-installer.iso -f github:user/nixos-config 26 + $0 -o my-installer.iso -c ./installer-config 27 + 28 + Configuration Directory Structure: 29 + installer-config/ 30 + ├── installer-config.json # Configuration file 31 + └── files/ # Files to copy to target system 32 + ├── etc/ 33 + │ └── resolv.conf # Gets copied to /etc/resolv.conf 34 + └── root/ 35 + └── .ssh/ 36 + └── authorized_keys # Gets copied to /root/.ssh/authorized_keys 37 + 38 + JSON Configuration Format: 39 + { 40 + "flakeUrl": "github:user/nixos-config", 41 + "fileMetadata": { 42 + "/etc/resolv.conf": { 43 + "owner": "root:root", 44 + "permissions": "644" 45 + }, 46 + "/root/.ssh/authorized_keys": { 47 + "owner": "root:root", 48 + "permissions": "600" 49 + } 50 + } 51 + } 52 + 53 + Default file metadata: owner=root:root, permissions=400 24 54 EOF 25 55 } 26 56 ··· 35 65 ARCH="$2" 36 66 shift 2 37 67 ;; 38 - -v|--vars) 39 - VARS_DIR="$2" 68 + -c|--config) 69 + CONFIG_DIR="$2" 70 + shift 2 71 + ;; 72 + -f|--flake) 73 + FLAKE_URL="$2" 40 74 shift 2 41 75 ;; 42 76 -h|--help) ··· 55 89 echo "Building base ISO for $ARCH..." 56 90 BASE_ISO=$(nix build -L --no-link --print-out-paths "$FLAKE_ROOT#nixosConfigurations.installer-$ARCH.config.system.build.images.iso-installer") 57 91 58 - if [ -z "$VARS_DIR" ]; then 59 - # No vars specified, just copy the base ISO 60 - echo "No vars directory specified, copying base ISO..." 61 - cp "$BASE_ISO"/iso/*.iso "$OUTPUT" 62 - else 63 - # Append vars using xorriso - preserve boot structure 64 - echo "Appending vars from $VARS_DIR to ISO..." 92 + # Determine what to append to the ISO 93 + if [ -n "$FLAKE_URL" ]; then 94 + # Create minimal config for flake URL 95 + echo "Creating minimal configuration for flake URL: $FLAKE_URL" 96 + TEMP_CONFIG_DIR=$(mktemp -d) 97 + trap 'rm -rf "$TEMP_CONFIG_DIR"' EXIT 98 + 99 + cat > "$TEMP_CONFIG_DIR/installer-config.json" <<EOF 100 + { 101 + "flakeUrl": "$FLAKE_URL" 102 + } 103 + EOF 104 + 105 + echo "Appending flake configuration to ISO..." 65 106 xorriso \ 66 107 -indev "$BASE_ISO"/iso/*.iso \ 67 108 -outdev "$OUTPUT" \ 68 109 -boot_image any replay \ 69 - -map "$VARS_DIR" /vars \ 110 + -map "$TEMP_CONFIG_DIR/installer-config.json" /installer-config.json \ 70 111 -commit_eject all 112 + 113 + elif [ -n "$CONFIG_DIR" ]; then 114 + # Use provided configuration directory 115 + echo "Appending configuration from $CONFIG_DIR to ISO..." 116 + 117 + if [ ! -d "$CONFIG_DIR" ]; then 118 + echo "Error: Configuration directory '$CONFIG_DIR' not found" 119 + exit 1 120 + fi 121 + 122 + # Build xorriso command with all necessary mappings 123 + XORRISO_ARGS=( 124 + -indev "$BASE_ISO"/iso/*.iso 125 + -outdev "$OUTPUT" 126 + -boot_image any replay 127 + ) 128 + 129 + # Add installer-config.json if it exists 130 + if [ -f "$CONFIG_DIR/installer-config.json" ]; then 131 + XORRISO_ARGS+=(-map "$CONFIG_DIR/installer-config.json" /installer-config.json) 132 + fi 133 + 134 + # Add files directory if it exists 135 + if [ -d "$CONFIG_DIR/files" ]; then 136 + XORRISO_ARGS+=(-map "$CONFIG_DIR/files" /files) 137 + fi 138 + 139 + XORRISO_ARGS+=(-commit_eject all) 140 + 141 + xorriso "${XORRISO_ARGS[@]}" 142 + 143 + else 144 + # No configuration specified, just copy the base ISO 145 + echo "No configuration specified, copying base ISO..." 146 + cp "$BASE_ISO"/iso/*.iso "$OUTPUT" 71 147 fi 72 148 73 149 echo "ISO created: $OUTPUT"
+147 -65
tools/build-installer-iso/flake-module.nix
··· 1 - { self, nixpkgs, clan-core, ... }: 1 + { self, inputs, ... }: 2 2 let 3 3 # Shared installer configuration module 4 - installerModule = { modulesPath, pkgs, ... }: { 5 - imports = [ 6 - (modulesPath + "/image/images.nix") 7 - ]; 4 + installerModule = 5 + { modulesPath, pkgs, ... }: 6 + { 7 + imports = [ 8 + (modulesPath + "/image/images.nix") 9 + ]; 8 10 9 - # Basic installer configuration 10 - networking.hostName = "installer"; 11 + # Basic installer configuration 12 + networking.hostName = "installer"; 11 13 12 - # Enable emergency access in initrd for debugging 13 - boot.initrd.systemd.emergencyAccess = true; 14 + # Enable emergency access in initrd for debugging 15 + boot.initrd.systemd.emergencyAccess = true; 14 16 15 - # Enable serial console for VM usage 16 - boot.kernelParams = [ "console=ttyS0,115200n8" "console=tty0" ]; 17 - 18 - # Configure systemd for serial console 19 - systemd.services."serial-getty@ttyS0" = { 20 - enable = true; 21 - wantedBy = [ "getty.target" ]; 22 - serviceConfig.Restart = "always"; 23 - }; 17 + # Enable serial console for VM usage 18 + boot.kernelParams = [ 19 + "console=ttyS0,115200n8" 20 + "console=tty0" 21 + ]; 24 22 25 - # Auto-mount ISO and extract vars 26 - systemd.services.extract-vars = { 27 - description = "Extract vars from ISO"; 28 - wantedBy = [ "multi-user.target" ]; 29 - after = [ "local-fs.target" ]; 30 - path = with pkgs; [ util-linux coreutils ]; 31 - serviceConfig = { 32 - Type = "oneshot"; 33 - RemainAfterExit = true; 23 + # Configure systemd for serial console 24 + systemd.services."serial-getty@ttyS0" = { 25 + enable = true; 26 + wantedBy = [ "getty.target" ]; 27 + serviceConfig.Restart = "always"; 34 28 }; 35 - script = '' 36 - set -euxo pipefail 37 29 38 - # Find the ISO device (usually sr0, but could be others) 39 - ISO_DEVICE="" 40 - for dev in /dev/sr*; do 41 - if [ -b "$dev" ]; then 42 - ISO_DEVICE="$dev" 43 - break 44 - fi 45 - done 30 + # Process installer configuration from ISO during system activation 31 + system.activationScripts.installer-config = { 32 + text = '' 33 + echo "Processing installer configuration from ISO..." 46 34 47 - if [ -z "$ISO_DEVICE" ]; then 48 - echo "No ISO device found, checking loop devices..." 49 - for dev in /dev/loop*; do 50 - if [ -b "$dev" ] && lsblk -no FSTYPE "$dev" 2>/dev/null | grep -q iso9660; then 35 + # Find the ISO device (usually sr0, but could be others) 36 + ISO_DEVICE="" 37 + for dev in /dev/sr*; do 38 + if [ -b "$dev" ]; then 51 39 ISO_DEVICE="$dev" 52 40 break 53 41 fi 54 42 done 55 - fi 56 43 57 - if [ -n "$ISO_DEVICE" ]; then 58 - echo "Found ISO device: $ISO_DEVICE" 59 - mkdir -p /mnt/iso 60 - if mount -t iso9660 -o ro "$ISO_DEVICE" /mnt/iso; then 61 - echo "Successfully mounted ISO" 62 - if [ -d /mnt/iso/vars ]; then 63 - echo "Extracting vars to /vars" 64 - cp -r /mnt/iso/vars /vars 65 - chmod -R u+w /vars 66 - echo "Vars extracted successfully" 44 + if [ -z "$ISO_DEVICE" ]; then 45 + echo "No ISO device found, checking loop devices..." 46 + for dev in /dev/loop*; do 47 + if [ -b "$dev" ] && ${pkgs.util-linux}/bin/lsblk -no FSTYPE "$dev" 2>/dev/null | ${pkgs.gnugrep}/bin/grep -q iso9660; then 48 + ISO_DEVICE="$dev" 49 + break 50 + fi 51 + done 52 + fi 53 + 54 + if [ -n "$ISO_DEVICE" ]; then 55 + echo "Found ISO device: $ISO_DEVICE" 56 + mkdir -p /mnt/iso 57 + if ${pkgs.util-linux}/bin/mount -t iso9660 -o ro "$ISO_DEVICE" /mnt/iso; then 58 + echo "Successfully mounted ISO" 59 + 60 + # Check for installer configuration 61 + if [ -f /mnt/iso/installer-config.json ]; then 62 + echo "Found installer configuration" 63 + CONFIG_FILE="/mnt/iso/installer-config.json" 64 + 65 + # Process flake URL if present 66 + FLAKE_URL=$(${pkgs.jq}/bin/jq -r '.flakeUrl // empty' "$CONFIG_FILE" || true) 67 + if [ -n "$FLAKE_URL" ]; then 68 + echo "Flake URL configured: $FLAKE_URL" 69 + # Store for later installation 70 + mkdir -p /var/lib 71 + echo "$FLAKE_URL" > /var/lib/installer-flake-url 72 + fi 73 + 74 + # Process files from file structure 75 + if [ -d /mnt/iso/files ]; then 76 + echo "Processing files from file structure..." 77 + 78 + # Copy all files from the files directory, preserving structure 79 + ${pkgs.findutils}/bin/find /mnt/iso/files -type f | while read -r source_file; do 80 + # Remove /mnt/iso/files prefix to get target path 81 + target_path="''${source_file#/mnt/iso/files}" 82 + echo "Copying file: $source_file -> $target_path" 83 + 84 + # Create target directory 85 + mkdir -p "$(dirname "$target_path")" 86 + 87 + # Copy the file 88 + ${pkgs.coreutils}/bin/cp "$source_file" "$target_path" 89 + 90 + # Apply metadata from JSON if present 91 + if ${pkgs.jq}/bin/jq -e ".fileMetadata[\"$target_path\"]" "$CONFIG_FILE" >/dev/null 2>&1; then 92 + # Extract metadata for this file 93 + OWNER=$(${pkgs.jq}/bin/jq -r ".fileMetadata[\"$target_path\"].owner // \"root:root\"" "$CONFIG_FILE") 94 + PERMS=$(${pkgs.jq}/bin/jq -r ".fileMetadata[\"$target_path\"].permissions // \"400\"" "$CONFIG_FILE") 95 + 96 + echo "Setting owner: $OWNER, permissions: $PERMS for $target_path" 97 + ${pkgs.coreutils}/bin/chown "$OWNER" "$target_path" || echo "Warning: failed to set owner $OWNER" 98 + ${pkgs.coreutils}/bin/chmod "$PERMS" "$target_path" || echo "Warning: failed to set permissions $PERMS" 99 + else 100 + # Apply defaults: root:root, 400 101 + echo "Applying default metadata for $target_path" 102 + ${pkgs.coreutils}/bin/chown root:root "$target_path" || echo "Warning: failed to set default owner" 103 + ${pkgs.coreutils}/bin/chmod 400 "$target_path" || echo "Warning: failed to set default permissions" 104 + fi 105 + done 106 + fi 107 + 108 + else 109 + echo "No installer configuration found in ISO" 110 + fi 111 + 112 + ${pkgs.util-linux}/bin/umount /mnt/iso 67 113 else 68 - echo "No vars directory found in ISO" 114 + echo "Failed to mount ISO device $ISO_DEVICE" 69 115 fi 70 116 else 71 - echo "Failed to mount ISO device $ISO_DEVICE" 117 + echo "No ISO device found" 72 118 fi 73 - else 74 - echo "No ISO device found" 75 - fi 76 - ''; 119 + ''; 120 + deps = [ ]; 121 + }; 122 + 123 + # Service to install from flake URL if configured 124 + systemd.services.installer-flake-install = { 125 + description = "Install NixOS from configured flake URL"; 126 + wantedBy = [ "multi-user.target" ]; 127 + after = [ 128 + "installer-config.service" 129 + "network-online.target" 130 + ]; 131 + wants = [ "network-online.target" ]; 132 + path = with pkgs; [ 133 + git 134 + nix 135 + coreutils 136 + ]; 137 + serviceConfig = { 138 + Type = "oneshot"; 139 + RemainAfterExit = true; 140 + }; 141 + script = '' 142 + set -euo pipefail 143 + 144 + if [ -f /var/lib/installer-flake-url ]; then 145 + FLAKE_URL=$(cat /var/lib/installer-flake-url) 146 + echo "Installing from flake: $FLAKE_URL" 147 + 148 + # TODO: Add actual installation logic here 149 + # This would typically involve: 150 + # 1. Partitioning disks 151 + # 2. Mounting filesystems 152 + # 3. Running nixos-install with the flake 153 + echo "Installation from flake not yet implemented" 154 + echo "Flake URL: $FLAKE_URL" 155 + else 156 + echo "No flake URL configured for automatic installation" 157 + fi 158 + ''; 159 + }; 77 160 }; 78 - }; 79 161 in 80 162 { 81 163 flake = { 82 164 # Export the installer module for reuse 83 165 nixosModules.installer = installerModule; 84 - 166 + 85 167 # Define installer configurations for each architecture 86 168 nixosConfigurations = { 87 - installer-x86_64-linux = nixpkgs.lib.nixosSystem { 169 + installer-x86_64-linux = inputs.nixpkgs.lib.nixosSystem { 88 170 system = "x86_64-linux"; 89 171 modules = [ installerModule ]; 90 172 }; 91 - 92 - installer-aarch64-linux = nixpkgs.lib.nixosSystem { 173 + 174 + installer-aarch64-linux = inputs.nixpkgs.lib.nixosSystem { 93 175 system = "aarch64-linux"; 94 176 modules = [ installerModule ]; 95 177 }; 96 178 }; 97 179 }; 98 - 180 + 99 181 perSystem = 100 182 { pkgs, ... }: 101 183 { ··· 113 195 ''; 114 196 }; 115 197 }; 116 - } 198 + }
+1 -1
tools/vm-boot/flake-module.nix
··· 14 14 text = builtins.readFile ./vm-boot.sh; 15 15 }; 16 16 }; 17 - } 17 + }