parent
bc69d74ac2
commit
30e2db26ca
18 changed files with 257 additions and 337 deletions
|
@ -3,10 +3,10 @@
|
|||
boot = "/dev/null"
|
||||
root = "/dev/null"
|
||||
|
||||
[general]
|
||||
# Use LUKS encryption on root drive
|
||||
encryption = true
|
||||
encryption = "password"
|
||||
|
||||
[general]
|
||||
# Preset
|
||||
mode = "Desktop"
|
||||
|
||||
|
|
|
@ -58,12 +58,12 @@ pub struct DriveConfig {
|
|||
pub boot: String,
|
||||
/// Root Drive Path
|
||||
pub root: String,
|
||||
/// Enable encryption on root
|
||||
pub encryption: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct GeneralConfig {
|
||||
/// Enable encryption on root
|
||||
pub encryption: bool,
|
||||
/// Presets
|
||||
pub mode: InstallMode,
|
||||
/// System locale
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use crate::{
|
||||
install::{str_vec, uncomment_tag},
|
||||
is_root, print_status, run_command,
|
||||
};
|
||||
use crate::{install::uncomment_tag, is_root, linux::run_command, print_status};
|
||||
|
||||
/// Build the `kxkbrc` file for the given `layout` and `variant
|
||||
pub fn build_kxkbrc(layout: &str, variant: Option<&str>) -> String {
|
||||
let mut res = String::from("[Layout]\nUse=true\n");
|
||||
res.push_str(&format!("LayoutList={layout}\n"));
|
||||
|
@ -20,7 +18,7 @@ pub fn create_iso(without_gui: bool, kb_layout: &str, kb_variant: Option<&str>)
|
|||
}
|
||||
|
||||
if !std::fs::exists("./iso").unwrap() {
|
||||
let cmd = str_vec(vec!["git", "clone", "https://git.hydrar.de/navos/iso"]);
|
||||
let cmd = vec!["git", "clone", "https://git.hydrar.de/navos/iso"];
|
||||
run_command(&cmd, None, false);
|
||||
}
|
||||
|
||||
|
@ -41,25 +39,15 @@ pub fn create_iso(without_gui: bool, kb_layout: &str, kb_variant: Option<&str>)
|
|||
|
||||
std::fs::create_dir_all("./work").unwrap();
|
||||
|
||||
let mount_cmd = str_vec(vec![
|
||||
"mount", "-t", "tmpfs", "-o", "size=10G", "tmpfs", "./work",
|
||||
]);
|
||||
let mount_cmd = vec!["mount", "-t", "tmpfs", "-o", "size=10G", "tmpfs", "./work"];
|
||||
|
||||
run_command(&mount_cmd, None, false);
|
||||
|
||||
let mkarchiso_cmd = vec![
|
||||
"mkarchiso".to_string(),
|
||||
"-v".to_string(),
|
||||
"-w".to_string(),
|
||||
"./work".to_string(),
|
||||
"-o".to_string(),
|
||||
"./".to_string(),
|
||||
"./iso".to_string(),
|
||||
];
|
||||
let mkarchiso_cmd = vec!["mkarchiso", "-v", "-w", "./work", "-o", "./", "./iso"];
|
||||
|
||||
run_command(&mkarchiso_cmd, None, true);
|
||||
|
||||
let umount_cmd = str_vec(vec!["umount", "-r", "./work"]);
|
||||
let umount_cmd = vec!["umount", "-r", "./work"];
|
||||
|
||||
run_command(&umount_cmd, None, false);
|
||||
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
use crate::run_command;
|
||||
|
||||
use super::str_vec;
|
||||
use crate::linux::arch_chroot;
|
||||
|
||||
/// Install the bootloader (`systemd-boot`)
|
||||
pub fn setup_bootloader() {
|
||||
run_command(
|
||||
&str_vec(vec!["arch-chroot", "/mnt", "bootctl", "install"]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
arch_chroot(&["bootctl", "install"], None, false);
|
||||
}
|
||||
|
|
|
@ -1,61 +1,51 @@
|
|||
use crate::{config::DriveConfig, run_command};
|
||||
|
||||
use super::str_vec;
|
||||
use crate::{config::DriveConfig, linux::run_command};
|
||||
|
||||
// TODO : Add support for using entire block device
|
||||
|
||||
pub fn format_drives(conf: &DriveConfig, encrypted: bool) {
|
||||
/// Format the drives with the given config
|
||||
pub fn format_drives(conf: &DriveConfig) {
|
||||
// TODO : Safety checks !!!
|
||||
|
||||
// EFI (BOOT)
|
||||
run_command(
|
||||
&str_vec(vec!["mkfs.vfat", "-F", "32", conf.boot.as_str()]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
run_command(&["mkfs.vfat", "-F", "32", conf.boot.as_str()], None, false);
|
||||
|
||||
// ROOT
|
||||
if encrypted {
|
||||
if let Some(pass) = &conf.encryption {
|
||||
run_command(
|
||||
&str_vec(vec!["cryptsetup", "luksFormat", conf.root.as_str()]),
|
||||
None,
|
||||
&["cryptsetup", "luksFormat", conf.root.as_str()],
|
||||
Some(&format!("YES\n{pass}\n{pass}\n")),
|
||||
true,
|
||||
);
|
||||
} else {
|
||||
run_command(&str_vec(vec!["mkfs.ext4", conf.root.as_str()]), None, false);
|
||||
run_command(&["mkfs.ext4", conf.root.as_str()], None, false);
|
||||
}
|
||||
}
|
||||
|
||||
// MOUNT
|
||||
|
||||
pub fn mount_drives(conf: &DriveConfig, encrypted: bool) {
|
||||
if encrypted {
|
||||
/// Mount the drives at `/mnt`
|
||||
pub fn mount_drives(conf: &DriveConfig) {
|
||||
if let Some(pass) = &conf.encryption {
|
||||
run_command(
|
||||
&str_vec(vec!["cryptsetup", "open", conf.root.as_str(), "root"]),
|
||||
None,
|
||||
&["cryptsetup", "open", conf.root.as_str(), "root"],
|
||||
Some(&format!("{pass}\n")),
|
||||
true,
|
||||
);
|
||||
|
||||
run_command(
|
||||
&str_vec(vec!["mount", "/dev/mapper/root", "/mnt"]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
run_command(&["mount", "/dev/mapper/root", "/mnt"], None, false);
|
||||
} else {
|
||||
run_command(
|
||||
&str_vec(vec!["mount", conf.root.as_str(), "/mnt"]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
run_command(&["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,
|
||||
);
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
// GENFSTAB
|
||||
|
||||
use crate::{config::GeneralConfig, print_status, run_command};
|
||||
use crate::{
|
||||
config::GeneralConfig,
|
||||
linux::{arch_chroot, run_command, systemd_service_enable},
|
||||
print_status,
|
||||
};
|
||||
|
||||
use super::{str_vec, uncomment_first_value_of};
|
||||
use super::uncomment_first_value_of;
|
||||
|
||||
/// Generate the `/etc/fstab` file
|
||||
pub fn genfstab() {
|
||||
print_status("Generating fstab");
|
||||
let (stdout, _) = run_command(&str_vec(vec!["genfstab", "-U", "/mnt"]), None, false);
|
||||
let (stdout, _) = run_command(&["genfstab", "-U", "/mnt"], None, false);
|
||||
std::fs::write("/mnt/etc/fstab", stdout).unwrap();
|
||||
}
|
||||
|
||||
/// Set common config values for the system
|
||||
pub fn first_boot_values(conf: &GeneralConfig) {
|
||||
// Locale
|
||||
print_status(&format!("Setting locale {}", conf.locale));
|
||||
|
@ -45,27 +51,9 @@ pub fn first_boot_values(conf: &GeneralConfig) {
|
|||
// LOCALE
|
||||
print_status("Setting locale");
|
||||
uncomment_first_value_of(&conf.locale, "/mnt/etc/locale.gen");
|
||||
run_command(
|
||||
&str_vec(vec!["arch-chroot", "/mnt", "locale-gen"]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
arch_chroot(&["locale-gen"], None, false);
|
||||
|
||||
run_command(
|
||||
&str_vec(vec!["arch-chroot", "/mnt", "hwclock", "--systohc"]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
arch_chroot(&["hwclock", "--systohc"], None, false);
|
||||
|
||||
run_command(
|
||||
&str_vec(vec![
|
||||
"arch-chroot",
|
||||
"/mnt",
|
||||
"systemctl",
|
||||
"enable",
|
||||
"NetworkManager.service",
|
||||
]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
systemd_service_enable("NetworkManager.service");
|
||||
}
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
// MKINITCPIO + UKI
|
||||
|
||||
use crate::{config::DriveConfig, print_status, run_command};
|
||||
|
||||
use super::str_vec;
|
||||
use crate::{
|
||||
config::DriveConfig,
|
||||
linux::{arch_chroot, install_file},
|
||||
print_status,
|
||||
};
|
||||
|
||||
pub fn setup_mkinitcpio(conf: &DriveConfig) {
|
||||
print_status("Writing /etc/mkinitcpio.d/linux.preset");
|
||||
std::fs::write(
|
||||
install_file(
|
||||
"/mnt/etc/mkinitcpio.d/linux.preset",
|
||||
include_str!("../root/mkinitcpio/linux.preset"),
|
||||
)
|
||||
.unwrap();
|
||||
0o644,
|
||||
);
|
||||
|
||||
// Set kernel cmdline
|
||||
// TODO : Encryption support
|
||||
|
@ -19,14 +21,11 @@ pub fn setup_mkinitcpio(conf: &DriveConfig) {
|
|||
|
||||
// TODO : more configs
|
||||
print_status("Writing /etc/mkinitcpio.conf");
|
||||
std::fs::write(
|
||||
install_file(
|
||||
"/mnt/etc/mkinitcpio.conf",
|
||||
include_str!("../root/mkinitcpio.conf"),
|
||||
)
|
||||
.unwrap();
|
||||
run_command(
|
||||
&str_vec(vec!["arch-chroot", "/mnt", "mkinitcpio", "--allpresets"]),
|
||||
None,
|
||||
true,
|
||||
0o644,
|
||||
);
|
||||
|
||||
arch_chroot(&["mkinitcpio", "--allpresets"], None, true);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use kernel::setup_mkinitcpio;
|
|||
use navos::setup_navos;
|
||||
use ollama::setup_ollama;
|
||||
use security::{setup_secure_boot, setup_tpm_unlock};
|
||||
use skel::setup_skel;
|
||||
use ssh::setup_ssh;
|
||||
use user::setup_users;
|
||||
use yansi::{Color, Paint};
|
||||
|
@ -25,6 +26,7 @@ pub mod kernel;
|
|||
pub mod navos;
|
||||
pub mod ollama;
|
||||
pub mod security;
|
||||
pub mod skel;
|
||||
pub mod ssh;
|
||||
pub mod user;
|
||||
pub mod zram;
|
||||
|
@ -35,10 +37,6 @@ use crate::{
|
|||
print_status,
|
||||
};
|
||||
|
||||
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();
|
||||
|
@ -49,7 +47,7 @@ pub fn uncomment_first_value_of(value: &str, file: &str) {
|
|||
// uncomment the '#' symbol if there is one
|
||||
for line in content.lines() {
|
||||
if line.contains(value) && !found {
|
||||
new.push_str(&format!("{}\n", line.replace("#", "")));
|
||||
new.push_str(&format!("{}\n", line.replace('#', "")));
|
||||
found = true;
|
||||
} else {
|
||||
new.push_str(&format!("{line}\n"));
|
||||
|
@ -80,8 +78,8 @@ pub fn uncomment_tag(tag: &str, file: &str) {
|
|||
|
||||
pub fn install(conf: InstallConfig) {
|
||||
// Drive Setup
|
||||
format_drives(&conf.drive, conf.general.encryption);
|
||||
mount_drives(&conf.drive, conf.general.encryption);
|
||||
format_drives(&conf.drive);
|
||||
mount_drives(&conf.drive);
|
||||
|
||||
// Base Install
|
||||
pacstrap(&conf.pkg);
|
||||
|
@ -89,9 +87,10 @@ pub fn install(conf: InstallConfig) {
|
|||
|
||||
// System Setup
|
||||
first_boot_values(&conf.general);
|
||||
setup_skel(&conf.general);
|
||||
setup_users(&conf.user);
|
||||
|
||||
setup_ssh(&conf.ssh);
|
||||
setup_ssh(conf.ssh);
|
||||
|
||||
setup_bootloader();
|
||||
|
||||
|
@ -135,7 +134,7 @@ pub fn install(conf: InstallConfig) {
|
|||
setup_mkinitcpio(&conf.drive);
|
||||
setup_secure_boot();
|
||||
|
||||
if conf.general.encryption {
|
||||
if conf.drive.encryption.is_some() {
|
||||
setup_tpm_unlock(&conf.drive);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
use crate::{print_status, run_command};
|
||||
|
||||
use super::str_vec;
|
||||
use crate::{linux::arch_chroot, print_status};
|
||||
|
||||
pub fn setup_navos() {
|
||||
// pacman.conf
|
||||
|
@ -15,31 +13,27 @@ pub fn setup_navos() {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
run_command(
|
||||
&str_vec(vec![
|
||||
"arch-chroot",
|
||||
"/mnt",
|
||||
arch_chroot(
|
||||
&[
|
||||
"pacman-key",
|
||||
"--add",
|
||||
"/usr/share/pacman/keyrings/navos.gpg",
|
||||
]),
|
||||
],
|
||||
None,
|
||||
false,
|
||||
);
|
||||
|
||||
run_command(
|
||||
&str_vec(vec![
|
||||
"arch-chroot",
|
||||
"/mnt",
|
||||
arch_chroot(
|
||||
&[
|
||||
"pacman-key",
|
||||
"--lsign-key",
|
||||
"778D9D7E5B6AC3762BB5541FEE446EC749C4AE00",
|
||||
]),
|
||||
],
|
||||
None,
|
||||
false,
|
||||
);
|
||||
|
||||
// remote os-release
|
||||
// remove os-release
|
||||
print_status("Removing os-release");
|
||||
std::fs::remove_file("/mnt/etc/os-release").unwrap();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::{config::OllamaConfig, pkg::install_pkgs, run_command};
|
||||
|
||||
use super::str_vec;
|
||||
use crate::{config::OllamaConfig, linux::systemd_service_enable, pkg::install_pkgs};
|
||||
|
||||
/// Setup Ollama AI Service
|
||||
pub fn setup_ollama(conf: &OllamaConfig) {
|
||||
if conf.gpu {
|
||||
install_pkgs(&["ollama-cuda"]);
|
||||
|
@ -9,17 +8,7 @@ pub fn setup_ollama(conf: &OllamaConfig) {
|
|||
install_pkgs(&["ollama"]);
|
||||
}
|
||||
|
||||
run_command(
|
||||
&str_vec(vec![
|
||||
"arch-chroot",
|
||||
"/mnt",
|
||||
"systemctl",
|
||||
"enable",
|
||||
"ollama.service",
|
||||
]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
systemd_service_enable("ollama.service");
|
||||
|
||||
for model in conf.models.clone().unwrap_or_default() {
|
||||
// TODO : Pull models
|
||||
|
|
|
@ -1,137 +1,70 @@
|
|||
// TPM Unlock
|
||||
|
||||
use crate::{config::DriveConfig, pkg::install_pkgs, run_command};
|
||||
use yansi::{Color, Paint};
|
||||
|
||||
use super::str_vec;
|
||||
use crate::{
|
||||
config::DriveConfig,
|
||||
linux::{arch_chroot, install_file, run_command},
|
||||
pkg::install_pkgs,
|
||||
};
|
||||
|
||||
/// Setup TPM Unlock and a recovery key for the root drive
|
||||
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,
|
||||
let recovery_key = arch_chroot(
|
||||
&["systemd-cryptenroll", "--recovery-key", &conf.root],
|
||||
Some(&format!("{}\n", conf.encryption.as_ref().unwrap())),
|
||||
false,
|
||||
);
|
||||
)
|
||||
.0;
|
||||
install_file("/mnt/root/recovery.key", &recovery_key, 0o400);
|
||||
|
||||
run_command(
|
||||
&str_vec(vec![
|
||||
"arch-chroot",
|
||||
"/mnt",
|
||||
arch_chroot(
|
||||
&[
|
||||
"systemd-cryptenroll",
|
||||
"--tpm2-device=auto",
|
||||
&conf.root,
|
||||
"--tpm2-pcrs=7",
|
||||
]),
|
||||
None,
|
||||
],
|
||||
Some(&format!("{}\n", conf.encryption.as_ref().unwrap())),
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
// SECURE BOOT
|
||||
|
||||
/// Setup Secure Boot on the system
|
||||
pub fn setup_secure_boot() {
|
||||
let (stdout, _) = run_command(&str_vec(vec!["sbctl", "status"]), None, false);
|
||||
let (stdout, _) = run_command(&["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");
|
||||
if !status.contains("Setup Mode") || !status.contains("Enabled") {
|
||||
println!(
|
||||
"{}",
|
||||
"[!] Secure Boot is not in Setup Mode".paint(Color::Red)
|
||||
);
|
||||
std::process::exit(1);
|
||||
} else {
|
||||
if !status.contains("Enabled") {
|
||||
println!("[!] Secure Boot is not in Setup Mode");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
install_pkgs(&["sbctl", "sbsigntools"]);
|
||||
|
||||
run_command(
|
||||
&vec![
|
||||
"arch-chroot".into(),
|
||||
"/mnt".into(),
|
||||
"sbctl".into(),
|
||||
"create-keys".into(),
|
||||
],
|
||||
None,
|
||||
false,
|
||||
);
|
||||
arch_chroot(&["sbctl", "create-keys"], None, false);
|
||||
|
||||
run_command(
|
||||
&str_vec(vec![
|
||||
"arch-chroot",
|
||||
"/mnt",
|
||||
"sbctl",
|
||||
"enroll-keys",
|
||||
"--microsoft",
|
||||
]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
run_command(
|
||||
&str_vec(vec![
|
||||
"arch-chroot",
|
||||
"/mnt",
|
||||
"sbctl",
|
||||
"sign",
|
||||
"-s",
|
||||
"/boot/EFI/Linux/arch-linux.efi",
|
||||
]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
arch_chroot(&["sbctl", "enroll-keys", "--microsoft"], None, false);
|
||||
|
||||
run_command(
|
||||
&str_vec(vec![
|
||||
"arch-chroot",
|
||||
"/mnt",
|
||||
"sbctl",
|
||||
"sign",
|
||||
"-s",
|
||||
"/boot/EFI/Linux/arch-linux-fallback.efi",
|
||||
]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
sb_sign("/boot/EFI/Linux/arch-linux.efi");
|
||||
sb_sign("/boot/EFI/Linux/arch-linux-fallback.efi");
|
||||
sb_sign("/boot/EFI/systemd/systemd-bootx64.efi");
|
||||
sb_sign("/boot/EFI/Boot/bootx64.efi");
|
||||
|
||||
run_command(
|
||||
&str_vec(vec![
|
||||
"arch-chroot",
|
||||
"/mnt",
|
||||
"sbctl",
|
||||
"sign",
|
||||
"-s",
|
||||
"/boot/EFI/systemd/systemd-bootx64.efi",
|
||||
]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
|
||||
run_command(
|
||||
&str_vec(vec![
|
||||
"arch-chroot",
|
||||
"/mnt",
|
||||
"sbctl",
|
||||
"sign",
|
||||
"-s",
|
||||
"/boot/EFI/Boot/bootx64.efi",
|
||||
]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
|
||||
run_command(
|
||||
&str_vec(vec!["arch-chroot", "/mnt", "sbctl", "verify"]),
|
||||
None,
|
||||
false,
|
||||
);
|
||||
arch_chroot(&["sbctl", "verify"], None, false);
|
||||
}
|
||||
|
||||
pub fn sb_sign(file: &str) {
|
||||
arch_chroot(&["sbctl", "sign", "-s", file], None, false);
|
||||
}
|
||||
|
|
6
src/install/skel.rs
Normal file
6
src/install/skel.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
use crate::config::GeneralConfig;
|
||||
|
||||
pub fn setup_skel(conf: &GeneralConfig) {
|
||||
// TODO : Implement
|
||||
unimplemented!()
|
||||
}
|
|
@ -1,14 +1,17 @@
|
|||
use crate::{config::SSHConfig, pkg::install_pkgs, print_status};
|
||||
use crate::{config::SSHConfig, linux::install_file, pkg::install_pkgs, print_status};
|
||||
use std::io::Write;
|
||||
|
||||
pub fn setup_ssh(conf: &Option<SSHConfig>) {
|
||||
/// Setup SSH on the system
|
||||
///
|
||||
/// This should be done after `setup_users()` to ensure that the users directories exist.
|
||||
pub fn setup_ssh(conf: Option<SSHConfig>) {
|
||||
if let Some(conf) = conf {
|
||||
install_pkgs(&["openssh"]);
|
||||
|
||||
if let Some(sshd_config) = &conf.sshd_config {
|
||||
print_status("Writing /etc/ssh/sshd_config");
|
||||
let content = std::fs::read_to_string(sshd_config).unwrap();
|
||||
std::fs::write("/mnt/etc/ssh/sshd_config", content).unwrap();
|
||||
install_file("/mnt/etc/ssh/sshd_config", &content, 0o644);
|
||||
}
|
||||
|
||||
for key in &conf.key {
|
||||
|
@ -17,7 +20,7 @@ pub fn setup_ssh(conf: &Option<SSHConfig>) {
|
|||
std::fs::create_dir_all("/root/.ssh").unwrap();
|
||||
"/root/.ssh/authorized_keys".to_string()
|
||||
} else {
|
||||
std::fs::create_dir_all(&format!("/home/{user}/.ssh")).unwrap();
|
||||
std::fs::create_dir_all(format!("/home/{user}/.ssh")).unwrap();
|
||||
format!("/home/{user}/.ssh/authorized_keys")
|
||||
};
|
||||
|
||||
|
@ -27,8 +30,8 @@ pub fn setup_ssh(conf: &Option<SSHConfig>) {
|
|||
.open(path)
|
||||
.unwrap();
|
||||
|
||||
print_status(&format!("Adding key to authorized_keys for {}", user));
|
||||
writeln!(authorized_keys, "{}", format!("{}\n", key.key)).unwrap();
|
||||
print_status(&format!("Adding key to authorized_keys for {user}"));
|
||||
writeln!(authorized_keys, "{}\n", key.key).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
use crate::{config::UserConfig, print_status, run_command};
|
||||
|
||||
use super::str_vec;
|
||||
use crate::{
|
||||
config::UserConfig,
|
||||
linux::{arch_chroot, install_file},
|
||||
print_status,
|
||||
};
|
||||
|
||||
/// Setup the users of the system
|
||||
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,
|
||||
);
|
||||
arch_chroot(&["useradd", "-m", &user.name], None, false);
|
||||
|
||||
run_command(
|
||||
&str_vec(vec!["arch-chroot", "/mnt", "passwd", &user.name]),
|
||||
arch_chroot(
|
||||
&["passwd", &user.name],
|
||||
Some(&format!("{}\n{}\n", user.password, user.password)),
|
||||
false,
|
||||
);
|
||||
|
@ -24,5 +23,5 @@ pub fn setup_users(conf: &[UserConfig]) {
|
|||
}
|
||||
}
|
||||
|
||||
std::fs::write("/mnt/etc/doas.conf", doas_conf).unwrap();
|
||||
install_file("/mnt/etc/doas.conf", &doas_conf, 0o644);
|
||||
}
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
use crate::{pkg::install_pkgs, print_status, run_command};
|
||||
|
||||
use super::str_vec;
|
||||
use crate::{
|
||||
linux::{install_file, systemd_service_enable},
|
||||
pkg::install_pkgs,
|
||||
print_status,
|
||||
};
|
||||
|
||||
/// Setup the ZRAM feature
|
||||
pub fn setup_zram() {
|
||||
install_pkgs(&["zram-generator"]);
|
||||
|
||||
print_status("Writing /etc/systemd/zram-generator.conf");
|
||||
std::fs::write(
|
||||
install_file(
|
||||
"/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,
|
||||
0o644,
|
||||
);
|
||||
|
||||
systemd_service_enable("systemd-zram-setup@zram0.service");
|
||||
}
|
||||
|
|
80
src/linux.rs
Normal file
80
src/linux.rs
Normal file
|
@ -0,0 +1,80 @@
|
|||
use nix::{unistd::Uid, unistd::getuid};
|
||||
use std::{io::Write, os::unix::fs::PermissionsExt};
|
||||
|
||||
use crate::print_status;
|
||||
|
||||
pub fn is_root() -> bool {
|
||||
getuid() == Uid::from_raw(0)
|
||||
}
|
||||
|
||||
pub fn run_command(cmd: &[&str], input: Option<&str>, inherit: bool) -> (String, String) {
|
||||
print_status(&cmd.join(" "));
|
||||
|
||||
let mut cmd_setup = std::process::Command::new(cmd[0]);
|
||||
let mut cmd_setup = cmd_setup.args(cmd.iter().skip(1).collect::<Vec<_>>());
|
||||
|
||||
if inherit {
|
||||
assert!(input.is_none());
|
||||
cmd_setup = cmd_setup
|
||||
.stdout(std::process::Stdio::inherit())
|
||||
.stdin(std::process::Stdio::inherit());
|
||||
} else {
|
||||
cmd_setup = cmd_setup.stdout(std::process::Stdio::piped());
|
||||
}
|
||||
|
||||
if input.is_some() {
|
||||
cmd_setup = cmd_setup.stdin(std::process::Stdio::piped());
|
||||
}
|
||||
|
||||
let mut child = cmd_setup.spawn().unwrap();
|
||||
|
||||
if let Some(input) = input {
|
||||
let stdin = child.stdin.as_mut().unwrap();
|
||||
stdin.write_all(input.as_bytes()).unwrap();
|
||||
stdin.flush().unwrap();
|
||||
}
|
||||
|
||||
let status = child.wait_with_output().unwrap();
|
||||
assert!(status.status.success());
|
||||
|
||||
let output = String::from_utf8(status.stdout).unwrap();
|
||||
let stderr = String::from_utf8(status.stderr).unwrap();
|
||||
|
||||
if !stderr.trim().is_empty() && !inherit {
|
||||
eprintln!("{stderr}");
|
||||
}
|
||||
|
||||
if !inherit {
|
||||
println!("{output}");
|
||||
}
|
||||
|
||||
(output, stderr)
|
||||
}
|
||||
|
||||
/// Runs a command in the chroot environment at `/mnt`
|
||||
pub fn arch_chroot(cmd: &[&str], input: Option<&str>, inherit: bool) -> (String, String) {
|
||||
let mut chroot_cmd = vec!["arch-chroot", "/mnt"];
|
||||
chroot_cmd.extend_from_slice(cmd);
|
||||
run_command(&chroot_cmd, input, inherit)
|
||||
}
|
||||
|
||||
/// Enable a systemd `.service` in the chroot environment at `/mnt`
|
||||
pub fn systemd_service_enable(unit: &str) {
|
||||
arch_chroot(&["systemctl", "enable", unit], None, false);
|
||||
}
|
||||
|
||||
/// Installs a file at `path` with `content` and `permissions`
|
||||
pub fn install_file(path: &str, content: &str, permissions: u32) {
|
||||
let mut file = std::fs::OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(path)
|
||||
.unwrap();
|
||||
|
||||
file.write_all(content.as_bytes()).unwrap();
|
||||
|
||||
let permissions = std::fs::Permissions::from_mode(permissions);
|
||||
print_status(&format!("Wrote file {path} [{permissions:#?}]"));
|
||||
std::fs::set_permissions(path, permissions).unwrap();
|
||||
}
|
57
src/main.rs
57
src/main.rs
|
@ -1,21 +1,18 @@
|
|||
use std::io::Write;
|
||||
|
||||
use config::InstallConfig;
|
||||
use nix::unistd::{Uid, getuid};
|
||||
|
||||
mod args;
|
||||
mod config;
|
||||
mod create_iso;
|
||||
mod install;
|
||||
mod linux;
|
||||
mod pkg;
|
||||
use create_iso::create_iso;
|
||||
use install::install;
|
||||
use linux::is_root;
|
||||
use yansi::{Color, Paint};
|
||||
|
||||
fn is_root() -> bool {
|
||||
getuid() == Uid::from_raw(0)
|
||||
}
|
||||
|
||||
fn print_status(msg: &str) {
|
||||
println!(
|
||||
"{} {}",
|
||||
|
@ -24,52 +21,6 @@ fn print_status(msg: &str) {
|
|||
);
|
||||
}
|
||||
|
||||
fn run_command(cmd: &[String], input: Option<&str>, inherit: bool) -> (String, String) {
|
||||
print_status(&cmd.join(" "));
|
||||
|
||||
let mut cmd_setup = std::process::Command::new(cmd[0].clone());
|
||||
let mut cmd_setup = cmd_setup.args(cmd.into_iter().skip(1).collect::<Vec<_>>());
|
||||
|
||||
if inherit {
|
||||
assert!(input.is_none());
|
||||
cmd_setup = cmd_setup
|
||||
.stdout(std::process::Stdio::inherit())
|
||||
.stdin(std::process::Stdio::inherit());
|
||||
} else {
|
||||
cmd_setup = cmd_setup.stdout(std::process::Stdio::piped());
|
||||
}
|
||||
|
||||
if input.is_some() {
|
||||
cmd_setup = cmd_setup.stdin(std::process::Stdio::piped());
|
||||
}
|
||||
|
||||
let mut child = cmd_setup.spawn().unwrap();
|
||||
|
||||
if let Some(input) = input {
|
||||
let stdin = child.stdin.as_mut().unwrap();
|
||||
stdin.write_all(input.as_bytes()).unwrap();
|
||||
stdin.flush().unwrap();
|
||||
}
|
||||
|
||||
let status = child.wait_with_output().unwrap();
|
||||
assert!(status.status.success());
|
||||
|
||||
let output = String::from_utf8(status.stdout).unwrap();
|
||||
let stderr = String::from_utf8(status.stderr).unwrap();
|
||||
|
||||
if !stderr.trim().is_empty() {
|
||||
if !inherit {
|
||||
eprintln!("{}", stderr);
|
||||
}
|
||||
}
|
||||
|
||||
if !inherit {
|
||||
println!("{}", output);
|
||||
}
|
||||
|
||||
(output, stderr)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!(
|
||||
"{}",
|
||||
|
@ -87,7 +38,7 @@ fn main() {
|
|||
let kb_variant: Option<&str> =
|
||||
iso_args.get_one("kb_variant").map(|x: &String| x.as_str());
|
||||
|
||||
create_iso(without_gui, &kb_layout, kb_variant);
|
||||
create_iso(without_gui, kb_layout, kb_variant);
|
||||
std::process::exit(0);
|
||||
}
|
||||
Some(("create-tar", _)) => {
|
||||
|
@ -163,7 +114,7 @@ fn main() {
|
|||
}
|
||||
|
||||
// Run the
|
||||
install(conf)
|
||||
install(conf);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
43
src/pkg.rs
43
src/pkg.rs
|
@ -1,36 +1,47 @@
|
|||
use crate::{config::PackageConfig, install::str_vec, run_command};
|
||||
use crate::{
|
||||
config::PackageConfig,
|
||||
linux::{arch_chroot, run_command},
|
||||
};
|
||||
|
||||
pub const DESKTOP_PKG: [&str; 3] = ["plasma", "sddm", "navos/navos"];
|
||||
|
||||
pub const SERVER_PKG: [&str; 2] = ["tmux", "navos/navos"];
|
||||
|
||||
/// Install packages to the chroot environment at `/mnt`
|
||||
pub fn install_pkgs(pkg: &[&str]) {
|
||||
let mut cmd = vec!["arch-chroot", "/mnt", "pacman", "-Syu"];
|
||||
let mut cmd = vec!["pacman", "-Syu"];
|
||||
|
||||
cmd.push("--noconfirm");
|
||||
cmd.extend_from_slice(pkg);
|
||||
|
||||
run_command(&str_vec(cmd), None, true);
|
||||
arch_chroot(&cmd, None, true);
|
||||
}
|
||||
|
||||
// PACSTRAP
|
||||
|
||||
/// Initial system pacstrap
|
||||
pub fn pacstrap(conf: &PackageConfig) {
|
||||
let mut cmd: Vec<String> = vec![
|
||||
"pacstrap".into(),
|
||||
"-K".into(),
|
||||
"/mnt".into(),
|
||||
"base".into(),
|
||||
"linux".into(),
|
||||
"linux-firmware".into(),
|
||||
"linux-headers".into(),
|
||||
"git".into(),
|
||||
"networkmanager".into(),
|
||||
"nano".into(),
|
||||
"doas".into(),
|
||||
let mut cmd: Vec<&str> = vec![
|
||||
"pacstrap",
|
||||
"-K",
|
||||
"/mnt",
|
||||
"base",
|
||||
"linux",
|
||||
"linux-firmware",
|
||||
"linux-headers",
|
||||
"git",
|
||||
"networkmanager",
|
||||
"nano",
|
||||
"doas",
|
||||
];
|
||||
|
||||
cmd.extend(conf.pkg.clone());
|
||||
cmd.extend(
|
||||
&conf
|
||||
.pkg
|
||||
.iter()
|
||||
.map(std::string::String::as_str)
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
run_command(&cmd, None, true);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue