This commit is contained in:
JMARyA 2024-12-28 01:19:44 +01:00
parent eabd898ccf
commit f2b1a43f62
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
13 changed files with 453 additions and 390 deletions

11
src/install/boot.rs Normal file
View file

@ -0,0 +1,11 @@
use crate::run_command;
use super::str_vec;
pub fn setup_bootloader() {
run_command(
&str_vec(vec!["arch-chroot", "/mnt", "bootctl", "install"]),
None,
false,
);
}

60
src/install/drives.rs Normal file
View file

@ -0,0 +1,60 @@
use crate::{config::DriveConfig, run_command};
use super::str_vec;
pub fn format_drives(conf: &DriveConfig, encrypted: bool) {
// EFI (BOOT)
run_command(
&str_vec(vec!["mkfs.vfat", "-F", "32", conf.boot.as_str()]),
None,
false,
);
// ROOT
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, 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,
);
} else {
run_command(
&str_vec(vec!["mount", conf.root.as_str(), "/mnt"]),
None,
false,
);
}
run_command(
&str_vec(vec![
"mount",
"--mkdir",
conf.boot.as_str(),
"/mnt/boot",
"-o",
"rw,nosuid,nodev,noatime,fmask=0137,dmask=0027",
]),
None,
false,
);
}

53
src/install/first_boot.rs Normal file
View file

@ -0,0 +1,53 @@
// GENFSTAB
use crate::{config::GeneralConfig, run_command};
use super::{str_vec, uncomment_first_value_of};
pub fn genfstab() {
let (stdout, _) = run_command(&str_vec(vec!["genfstab", "-U", "/mnt"]), None, false);
std::fs::write("/mnt/etc/fstab", stdout).unwrap();
}
pub fn first_boot_values(conf: &GeneralConfig) {
// CHROOT
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
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,
);
}

24
src/install/kernel.rs Normal file
View file

@ -0,0 +1,24 @@
// MKINITCPIO + UKI
use crate::run_command;
use super::str_vec;
pub fn setup_mkinitcpio() {
std::fs::write(
"/mnt/etc/mkinitcpio.d/linux.preset",
include_str!("../root/mkinitcpio/linux.preset"),
)
.unwrap();
// 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,
);
}

97
src/install/mod.rs Normal file
View file

@ -0,0 +1,97 @@
// TODO : Setup ssh (config + authorized_keys)
// TODO : Setup virtualization
// TODO : Setup docker
// TODO : Autojoin docker swarm
// TODO : Autojoin teleport
// DRIVE SELECTION
use boot::setup_bootloader;
use drives::{format_drives, mount_drives};
use first_boot::{first_boot_values, genfstab};
use kernel::setup_mkinitcpio;
use security::{setup_secure_boot, setup_tpm_unlock};
use user::setup_users;
use yansi::{Color, Paint};
use zram::setup_zram;
pub mod boot;
pub mod drives;
pub mod first_boot;
pub mod kernel;
pub mod security;
pub mod user;
pub mod zram;
use crate::{
config::InstallConfig,
pkg::{self, install_pkgs, pacstrap},
};
pub fn str_vec(v: Vec<&str>) -> Vec<String> {
v.into_iter().map(|x| x.to_string()).collect()
}
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 install(conf: InstallConfig) {
// Drive Setup
format_drives(&conf.drive, conf.general.encryption);
mount_drives(&conf.drive, conf.general.encryption);
// Base Install
pacstrap(&conf.pkg);
genfstab();
// System Setup
first_boot_values(&conf.general);
setup_users(&conf.user);
setup_bootloader();
match conf.general.mode {
crate::config::InstallMode::Base => {}
crate::config::InstallMode::Desktop => {
install_pkgs(&pkg::DESKTOP_PKG);
}
crate::config::InstallMode::Server => {
install_pkgs(&pkg::SERVER_PKG);
}
crate::config::InstallMode::Kiosk => {
// TODO
}
}
if conf.pkg.virtualization {
// TODO : Enable virtualization
}
if conf.pkg.docker {
// TODO : Enable docker
}
setup_zram();
setup_secure_boot();
setup_mkinitcpio();
setup_tpm_unlock(&conf.drive);
println!("{}", "System install complete".paint(Color::Green));
}

103
src/install/security.rs Normal file
View file

@ -0,0 +1,103 @@
// TPM Unlock
use crate::{config::DriveConfig, pkg::install_pkgs, run_command};
use super::str_vec;
pub fn setup_tpm_unlock(conf: &DriveConfig) {
install_pkgs(&["tpm2-tools"]);
// 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,
);
}
// SECURE BOOT
pub fn setup_secure_boot() {
let (stdout, _) = run_command(&str_vec(vec!["sbctl", "status"]), None, false);
let binding = stdout.lines().collect::<Vec<&str>>();
let status = binding.get(1).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);
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);
}

27
src/install/user.rs Normal file
View file

@ -0,0 +1,27 @@
use crate::{config::UserConfig, run_command};
use super::str_vec;
pub fn setup_users(conf: &[UserConfig]) {
let mut doas_conf = String::new();
for user in conf {
run_command(
&str_vec(vec!["arch-chroot", "/mnt", "useradd", "-m", &user.name]),
None,
false,
);
run_command(
&str_vec(vec!["arch-chroot", "/mnt", "passwd", &user.name]),
Some(&format!("{}\n{}\n", user.password, user.password)),
false,
);
if user.doas_root {
doas_conf.push_str(&format!("permit {} as root\n", user.name));
}
}
std::fs::write("/mnt/etc/doas.conf", doas_conf).unwrap();
}

23
src/install/zram.rs Normal file
View file

@ -0,0 +1,23 @@
use crate::{pkg::install_pkgs, run_command};
use super::str_vec;
pub fn setup_zram() {
install_pkgs(&["zram-generator"]);
std::fs::write(
"/mnt/etc/systemd/zram-generator.conf",
include_str!("../root/zram-generator.conf"),
)
.unwrap();
run_command(
&str_vec(vec![
"arch-chroot",
"/mnt",
"systemctl",
"enable",
"systemd-zram-setup@zram0.service",
]),
None,
false,
);
}