diff --git a/src/config.rs b/src/config.rs index 85a633f..39e01e1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -25,6 +25,12 @@ pub struct GeneralConfig { pub mode: InstallMode, /// System locale pub locale: String, + /// Keymap + pub keymap: String, + /// Timezone + pub timezone: String, + /// Hostname + pub hostname: String, /// Packages to install pub pkg: Vec, /// Enable libvirt diff --git a/src/install.rs b/src/install.rs index ab71b3e..bc75d78 100644 --- a/src/install.rs +++ b/src/install.rs @@ -14,7 +14,7 @@ pub fn str_vec(v: Vec<&str>) -> Vec { v.into_iter().map(|x| x.to_string()).collect() } -pub fn format_drives(conf: &DriveConfig) { +pub fn format_drives(conf: &DriveConfig, encrypted: bool) { // EFI (BOOT) run_command( &str_vec(vec!["mkfs.vfat", "-F", "32", conf.boot.as_str()]), @@ -23,27 +23,39 @@ pub fn format_drives(conf: &DriveConfig) { ); // ROOT - run_command( - &str_vec(vec!["cryptsetup", "luksFormat", conf.root.as_str()]), - None, - true, - ); + if encrypted { + run_command( + &str_vec(vec!["cryptsetup", "luksFormat", conf.root.as_str()]), + None, + true, + ); + } else { + run_command(&str_vec(vec!["mkfs.ext4", conf.root.as_str()]), None, false); + } } // MOUNT -pub fn mount_drives(conf: &DriveConfig) { - run_command( - &str_vec(vec!["cryptsetup", "open", conf.root.as_str(), "root"]), - None, - true, - ); +pub fn mount_drives(conf: &DriveConfig, encrypted: bool) { + if encrypted { + run_command( + &str_vec(vec!["cryptsetup", "open", conf.root.as_str(), "root"]), + None, + true, + ); - run_command( - &str_vec(vec!["mount", "/dev/mapper/root", "/mnt"]), - None, - false, - ); + run_command( + &str_vec(vec!["mount", "/dev/mapper/root", "/mnt"]), + None, + false, + ); + } else { + run_command( + &str_vec(vec!["mount", conf.root.as_str(), "/mnt"]), + None, + false, + ); + } // TODO : Secure mount options run_command( @@ -56,9 +68,18 @@ pub fn mount_drives(conf: &DriveConfig) { // PACSTRAP pub fn pacstrap(conf: &GeneralConfig) { - // TODO : Modes install + pkgs - - let mut cmd: Vec = vec!["pacstrap".into(), "-K".into(), "/mnt".into(), "base".into()]; + let mut cmd: Vec = vec![ + "pacstrap".into(), + "-K".into(), + "/mnt".into(), + "base".into(), + "linux".into(), + "linux-firmware".into(), + "linux-headers".into(), + "git".into(), + "networkmanager".into(), + "nano".into(), + ]; cmd.extend(conf.pkg.clone()); @@ -74,23 +95,96 @@ pub fn genfstab() { pub fn first_boot_values(conf: &GeneralConfig) { // CHROOT - - // SYSTEMD-FIRSTBOOT + run_command( + &vec![ + "arch-chroot".into(), + "/mnt".into(), + "systemd-firstboot".into(), + format!("--locale={}", conf.locale), + format!("--keymap={}", conf.keymap), + format!("--timezone={}", conf.timezone), + format!("--hostname={}", conf.hostname), + ], + None, + false, + ); // LOCALE - // TODO : Logic for uncommenting a value - std::fs::write("/etc/locale.gen", &conf.locale).unwrap(); - run_command(&str_vec(vec!["locale-gen"]), None, false); + uncomment_first_value_of(&conf.locale, "/mnt/etc/locale.gen"); + run_command( + &str_vec(vec!["arch-chroot", "/mnt", "locale-gen"]), + None, + false, + ); + + run_command( + &str_vec(vec!["arch-chroot", "/mnt", "hwclock", "--systohc"]), + None, + false, + ); + + run_command( + &str_vec(vec![ + "arch-chroot", + "/mnt", + "systemctl", + "enable", + "NetworkManager.service", + ]), + None, + false, + ); +} + +pub fn uncomment_first_value_of(value: &str, file: &str) { + // read in the file + let content = std::fs::read_to_string(file).unwrap(); + let mut new = String::new(); + let mut found = false; + + // search for the first instance of `value` in the file + // uncomment the '#' symbol if there is one + for line in content.lines() { + if line.contains(value) && !found { + new.push_str(&format!("{}\n", line.replace("#", ""))); + found = true; + } else { + new.push_str(&format!("{line}\n")); + } + } + // write back + std::fs::write(file, new).unwrap(); } pub fn setup_zram() { - // arch-chroot /mnt pacman -S zram-generator + run_command( + &str_vec(vec![ + "arch-chroot", + "/mnt", + "pacman", + "-Syu", + "--noconfirm", + "zram-generator", + ]), + None, + false, + ); std::fs::write( "/mnt/etc/systemd/zram-generator.conf", include_str!("root/zram-generator.conf"), ) .unwrap(); - // arch-chroot /mnt systemctl enable --now systemd-zram-setup@zram0.service + run_command( + &str_vec(vec![ + "arch-chroot", + "/mnt", + "systemctl", + "enable", + "systemd-zram-setup@zram0.service", + ]), + None, + false, + ); } // MKINITCPIO + UKI @@ -101,17 +195,84 @@ pub fn setup_mkinitcpio() { include_str!("root/mkinitcpio/linux.preset"), ) .unwrap(); - run_command(&str_vec(vec!["mkinitcpio", "--allpresets"]), None, true); + // TODO : more configs + std::fs::write( + "/mnt/etc/mkinitcpio.conf", + include_str!("root/mkinitcpio.conf"), + ) + .unwrap(); + run_command( + &str_vec(vec!["arch-chroot", "/mnt", "mkinitcpio", "--allpresets"]), + None, + true, + ); } // SECURE BOOT pub fn setup_secure_boot() { // TODO : Assert sb setup mode + let (stdout, _) = run_command(&str_vec(vec!["sbctl", "status"]), None, false); + let binding = stdout.lines().collect::>(); + let status = binding.get(2).unwrap(); + + if !status.contains("Setup Mode") { + println!("[!] Secure Boot is not in Setup Mode"); + std::process::exit(1); + } else { + if !status.contains("Enabled") { + println!("[!] Secure Boot is not in Setup Mode"); + std::process::exit(1); + } + } run_command(&vec!["sbctl".into(), "create-keys".into()], None, false); - // TODO : Sign + Enroll + run_command( + &str_vec(vec!["sbctl", "enroll-keys", "--microsoft"]), + None, + false, + ); + run_command( + &str_vec(vec![ + "sbctl", + "sign", + "-s", + "/boot/EFI/Linux/arch-linux.efi", + ]), + None, + false, + ); + + run_command( + &str_vec(vec![ + "sbctl", + "sign", + "-s", + "/boot/EFI/Linux/arch-linux-fallback.efi", + ]), + None, + false, + ); + + run_command( + &str_vec(vec![ + "sbctl", + "sign", + "-s", + "/boot/EFI/systemd/systemd-bootx64.efi", + ]), + None, + false, + ); + + run_command( + &str_vec(vec!["sbctl", "sign", "-s", "/boot/EFI/Boot/bootx64.efi"]), + None, + false, + ); + + run_command(&str_vec(vec!["sbctl", "verify"]), None, false); } // MODS @@ -120,14 +281,70 @@ pub fn setup_secure_boot() { // TPM Unlock +pub fn setup_tpm_unlock(conf: &DriveConfig) { + run_command( + &str_vec(vec![ + "arch-chroot", + "/mnt", + "pacman", + "-Syu", + "--noconfirm", + "tpm2-tools", + ]), + None, + false, + ); + + // systemd-cryptenroll --tpm2-device=list + + // Recovery Key + run_command( + &str_vec(vec![ + "arch-chroot", + "/mnt", + "systemd-cryptenroll", + "--recovery-key", + &conf.root, + ]), + None, + false, + ); + + run_command( + &str_vec(vec![ + "arch-chroot", + "/mnt", + "systemd-cryptenroll", + "--tpm2-device=auto", + &conf.root, + "--tpm2-pcrs=7", + ]), + None, + false, + ); +} + pub fn install_pkgs(pkg: &[&str]) { - // TODO : implement + let mut cmd = vec!["arch-chroot", "/mnt", "pacman", "-Syu"]; + + cmd.extend_from_slice(pkg); + cmd.push("--noconfirm"); + + run_command(&str_vec(cmd), None, true); +} + +pub fn setup_bootloader() { + run_command( + &str_vec(vec!["arch-chroot", "/mnt", "bootctl", "install"]), + None, + false, + ); } pub fn install(conf: InstallConfig) { // Drive Setup - format_drives(&conf.drive); - mount_drives(&conf.drive); + format_drives(&conf.drive, conf.general.encryption); + mount_drives(&conf.drive, conf.general.encryption); // Base Install pacstrap(&conf.general); @@ -135,7 +352,7 @@ pub fn install(conf: InstallConfig) { // System Setup first_boot_values(&conf.general); - // TODO : install bootloader + setup_bootloader(); match conf.general.mode { crate::config::InstallMode::Base => {} @@ -161,4 +378,7 @@ pub fn install(conf: InstallConfig) { setup_zram(); setup_secure_boot(); setup_mkinitcpio(); + setup_tpm_unlock(&conf.drive); + + println!("System install complete"); } diff --git a/src/root/mkinitcpio.conf b/src/root/mkinitcpio.conf new file mode 100644 index 0000000..cce4662 --- /dev/null +++ b/src/root/mkinitcpio.conf @@ -0,0 +1,5 @@ +MODULES=(tpm_tis) +BINARIES=() +FILES=() +HOOKS=(systemd plymouth autodetect microcode modconf kms keyboard sd-vconsole block sd-encrypt filesystems fsck) +COMPRESSION="zstd"