use rsfdisk::core::partition::{Guid, Partition, PartitionKind}; use rsfdisk::core::partition_table::PartitionTableKind; use rsfdisk::fdisk::Fdisk; use std::fs::File; use std::io; use std::io::Write; use std::path::Path; use std::process::{Command, Stdio}; use sys_metrics::disks; use curl::easy::Easy; use nix::mount::{mount, MsFlags}; fn format_drive(drive_name: &str) -> rsfdisk::Result<()> { let mut disk = Fdisk::builder() .assign_device(drive_name) .enable_read_write() .wipe_device_metadata() .build()?; disk.partition_table_create(PartitionTableKind::GPT)?; let partition_type = PartitionKind::builder().guid(Guid::EfiSystem).build()?; let boot = Partition::builder() .partition_type(partition_type) .name("EFI") //Assuming 512 bytes per sector, 2_097_152 sectors <=> 1 GiB. .size_in_sectors(2_097_152) .build()?; let _ = disk.partition_add(boot)?; let partition_type = PartitionKind::builder() .guid(Guid::LinuxRootx86_64) .build()?; let root = Partition::builder() .partition_type(partition_type) .name("Root") .build()?; let _ = disk.partition_add(root)?; disk.partition_table_write_to_disk()?; Ok(()) } fn format_partitions(drive_name: &str) { let efi_path = format!("{}p1", drive_name); let root_path = format!("{}p2", drive_name); let _efi_partition = Command::new("mkfs.fat") .arg("-F32") .arg("-n") .arg("EFI") .arg(&efi_path) .output() .expect("Failed to format boot partition as FAT32"); let _root_partition = Command::new("mkfs.ext4") .arg(&root_path) .output() .expect("Failed to format root partition as ext4"); } fn mount_partitions(drive_name: &str) { let efi_path = format!("{}p1", drive_name); let root_path = format!("{}p2", drive_name); let root_source = Some(Path::new(&root_path)); let root_target = Path::new("/mnt"); mount( root_source, root_target, Some("ext4"), MsFlags::empty(), None::<&[u8]>, ) .expect("Failed to mount root partition"); // Creates the boot directory in /mnt/boot let _create_boot_directory = Command::new("mkdir") .arg("-p") .arg("/mnt/boot") .output() .expect("Failed to create boot directory"); //let boot_source = Some(Path::new(&efi_path)); //let boot_target = Path::new("/mnt/boot"); let _mount_boot = Command::new("mount") .args(["-t", "vfat"]) .args(["-o", "umask=0077"]) .arg(&efi_path) .arg("/mnt/boot") .output() .expect("Failed to mount boot partition"); // mount( // boot_source, // boot_target, // Some("vfat"), // MsFlags::empty(), // None::<&[u8]>, // ) // .expect("Failed to mount boot partition"); } fn grab_flake() { let mut easy = Easy::new(); easy.url("https://gitlab.com/ahoneybun/nix-configs/-/raw/main/flake.nix") .unwrap(); let mut file = File::create("flake.nix").unwrap(); { let mut transfer = easy.transfer(); transfer .write_function(|data| { file.write_all(data).unwrap(); Ok(data.len()) }) .unwrap(); transfer.perform().unwrap(); } } fn grab_config() { let mut easy = Easy::new(); easy.url("https://gitlab.com/ahoneybun/nix-configs/-/raw/main/configuration.nix") .unwrap(); let mut file = File::create("configuration.nix").unwrap(); { let mut transfer = easy.transfer(); transfer .write_function(|data| { file.write_all(data).unwrap(); Ok(data.len()) }) .unwrap(); transfer.perform().unwrap(); } } fn grab_home() { let mut easy = Easy::new(); easy.url("https://gitlab.com/ahoneybun/nix-configs/-/raw/main/home.nix") .unwrap(); let mut file = File::create("home.nix").unwrap(); { let mut transfer = easy.transfer(); transfer .write_function(|data| { file.write_all(data).unwrap(); Ok(data.len()) }) .unwrap(); transfer.perform().unwrap(); } } fn grab_gnome() { let mut gnome_config = Easy::new(); gnome_config .url("https://gitlab.com/ahoneybun/nix-configs/-/raw/main/desktops/gnome.nix") .unwrap(); let mut config_file = File::create("gnome.nix").unwrap(); { let mut transfer = gnome_config.transfer(); transfer .write_function(|data| { config_file.write_all(data).unwrap(); Ok(data.len()) }) .unwrap(); transfer.perform().unwrap(); } } fn main() { println!("--------------------------------------"); println!("| Welcome to the Nyxi Installer 2.0! |"); println!("--------------------------------------"); println!(""); println!("Availble disks for installation:"); println!("---------------------------------"); println!(""); match disks::get_physical_ioblocks() { Ok(disk_list) => { for disk in disk_list { println!("Disk: {}", disk.device_name); } } Err(_e) => println!("{}", _e), } let mut drive_name = String::new(); println!(""); println!("Use the full drive path such as /dev/nvme0n1 or /dev/sda"); println!(""); println!( "Which drive do we want to use for this installation?: {}", drive_name ); io::stdin() .read_line(&mut drive_name) .expect("Failed to read line"); let drive_name = drive_name.trim(); // Download nix files grab_flake(); grab_config(); grab_home(); grab_gnome(); // Partitioning the selected drive let _ = format_drive(drive_name); // Formatting the partitions format_partitions(drive_name); // Mounting the partitions mount_partitions(drive_name); // Creates the init nix config in /mnt/etc/nixos let _nixos_gen_config = Command::new("nixos-generate-config") .arg("--root") .arg("/mnt") .output() .expect("Failed to execute command"); // Copies the nix files to /mnt/etc/nixos/ let _nix_move = Command::new("mv") .args(["-f", "flake.nix", "configuration.nix", "home.nix"]) .arg("/mnt/etc/nixos") .output() .expect("Failed to move nix files over"); // Fixes a security issue with boot let _boot_fix = Command::new("sed") .arg("-i") .arg( r#"/fsType = "vfat"/ { n s/\(options = \[.*\)\]/\1"umask=0077 "]/ }"#, ) .arg("/mnt/etc/nixos/hardware-configuration.nix") .output() .expect("Failed to apply boot fix"); // Host selection loop { println!(""); println!("Host selection:"); println!("---------------"); println!(""); println!("1. Lemur Pro 13 (Garrus)"); println!("2. Virtual Machine"); println!("3. Generic"); println!(""); println!("Enter your host for installation:"); let mut choice = String::new(); io::stdin().read_line(&mut choice).unwrap(); match choice.trim() { "1" => { let mut garrus_config = Easy::new(); garrus_config.url("https://gitlab.com/ahoneybun/nix-configs/-/raw/main/hosts/x86_64/garrus/configuration.nix").unwrap(); let mut config_file = File::create("garrus.nix").unwrap(); { let mut transfer = garrus_config.transfer(); transfer .write_function(|data| { config_file.write_all(data).unwrap(); Ok(data.len()) }) .unwrap(); transfer.perform().unwrap(); } // Copies the system nix files to /mnt/etc/nixos/ let _garrus_nix_copy = Command::new("mv") .args(["garrus.nix", "gnome.nix", "/mnt/etc/nixos"]) .output() .expect("Failed to copy nix files over"); let mut nixos_install = Command::new("nixos-install") .arg("--flake") .arg("/mnt/etc/nixos#garrus") .arg("--no-root-passwd") .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) .spawn() .unwrap(); let install_status = nixos_install.wait(); println!("Exited with status {:?}", install_status); break; } "2" => { let mut vm_config = Easy::new(); vm_config.url("https://gitlab.com/ahoneybun/nix-configs/-/raw/main/hosts/x86_64/vm/configuration.nix").unwrap(); let mut config_file = File::create("vm.nix").unwrap(); { let mut transfer = vm_config.transfer(); transfer .write_function(|data| { config_file.write_all(data).unwrap(); Ok(data.len()) }) .unwrap(); transfer.perform().unwrap(); } // Copies the system nix files to /mnt/etc/nixos/ let _garrus_nix_copy = Command::new("mv") .args(["vm.nix", "/mnt/etc/nixos"]) .output() .expect("Failed to copy nix files over"); let mut nixos_install = Command::new("nixos-install") .arg("--flake") .arg("/mnt/etc/nixos#vm") .arg("--no-root-passwd") .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) .spawn() .unwrap(); let install_status = nixos_install.wait(); println!("Exited with status {:?}", install_status); break; } "3" => { let mut nixos_install = Command::new("nixos-install") .arg("--flake") .arg("/mnt/etc/nixos#nixos") .arg("--no-root-passwd") .stdout(Stdio::inherit()) .stderr(Stdio::inherit()) .spawn() .unwrap(); let install_status = nixos_install.wait(); println!("Exited with status {:?}", install_status); break; } _ => println!("Invalid choice, try again."), } } }