diff --git a/installs/full.toml b/installs/full.toml deleted file mode 100644 index 42e8a1f..0000000 --- a/installs/full.toml +++ /dev/null @@ -1,87 +0,0 @@ -# Full Install Template - -# Drive Selection for Install -[drive] -# Device node for the EFI boot filesystem -boot = "/dev/null" - -# Device node for the root filesystem -root = "/dev/null" - -# Root filesystem encryption passphrase -# If this option is set the root filesystem will be encrypted with LUKS -encryption = "password" - -# General configuration -[general] -# Preset -mode = "Desktop" - -# System Locale -locale = "de_DE.UTF-8" - -# Keymap -keyboard_layout = "de" -keyboard_variant = "mac" - -# Timezone -timezone = "Europe/Berlin" - -# Hostname -hostname = "navos" - -# Root password -root_password = "root" - -[pkg] -# Additional packages -pkg = [ - "nano", - "micro" -] - -# Enable virtualization -virtualization = true - -# Enable docker -docker = true - -# User configuration -# The `[[user]]` directive can be repeated to create multiple users. -[[user]] -# Username -name = "testuser" - -# User password -password = "testpass" - -# Allow user to use `doas` as root -doas_root= true - -# SSH Configuration -# If `[ssh]` is set, openssh will be installed and enabled. -[ssh] -# Config file for sshd -# This file will be copied to the new system -sshd_config = "/etc/ssh/sshd_config" - -# Install a SSH keys -# To set multiple keys, repeat the `[[ssh.key]]` directive. -# Every key will be installed in the users respective `authorized_keys` file. -[[ssh.key]] -# The SSH Key -key = "ssh-rsa ... user@host" - -# The users allowed to login with this key -users = ["testuser", "root"] - -# Ollama Configuration -# If `[ai]` is set, ollama will be installed and enabled. -[ai] -# Install with CUDA supports -gpu = true - -# Pull LLMs -models = [ - "llama3.1:8b" -] diff --git a/installs/min.toml b/installs/min.toml deleted file mode 100644 index e2185ab..0000000 --- a/installs/min.toml +++ /dev/null @@ -1,38 +0,0 @@ -# Minimal Install Template - -# Drive Selection for Install -[drive] -# Device node for the EFI boot filesystem -boot = "/dev/null" - -# Device node for the root filesystem -root = "/dev/null" - -# Root filesystem encryption passphrase -# If this option is set the root filesystem will be encrypted with LUKS -encryption = "password" - -# General configuration -[general] -# Preset -mode = "Base" - -# System Locale -locale = "de_DE.UTF-8" - -# Keymap -keyboard_layout = "de" -keyboard_variant = "mac" - -# Timezone -timezone = "Europe/Berlin" - -# Hostname -hostname = "navos_min" - -# Root password -root_password = "root" - -[pkg] -# Additional packages -pkg = [] diff --git a/installs/testinstall.toml b/installs/testinstall.toml new file mode 100644 index 0000000..ca5b5dd --- /dev/null +++ b/installs/testinstall.toml @@ -0,0 +1,56 @@ +# Drive Selection for Install +[drive] +boot = "/dev/null" +root = "/dev/null" + +# Use LUKS encryption on root drive +encryption = "password" + +[general] +# Preset +mode = "Desktop" + +# System Locale +locale = "de_DE.UTF-8" + +# Keymap +keymap = "de-latin1" + +# Timezone +timezone = "Europe/Berlin" + +# Hostname +hostname = "navos" + +[pkg] +# Additional packages +pkg = [ + "nano", + "micro" +] + +# Enable virtualization +virtualization = true + +# Enable docker +docker = true + +[[user]] +# Username +name = "testuser" + +# User password +password = "testpass" + +# Allow user to use doas as root +doas_root= true + +# SSH Configuration +[ssh] +# Config file for sshd +sshd_config = "/etc/ssh/sshd_config" + +# Install a SSH key for the user as `authorized_keys` +[[ssh.key]] +key = "ssh-rsa ... user@host" +users = ["testuser", "root"] diff --git a/src/config.rs b/src/config.rs index 710fffd..d31b3b5 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,5 +1,3 @@ -use std::fmt::Display; - use serde::Deserialize; /// Declarative install configuration @@ -12,7 +10,7 @@ pub struct InstallConfig { /// Package Configuration pub pkg: PackageConfig, /// User Configuration - pub user: Option>, + pub user: Vec, /// SSH Configuration pub ssh: Option, /// Ollama AI Config @@ -28,7 +26,7 @@ pub struct OllamaConfig { #[derive(Debug, Deserialize)] pub struct SSHConfig { pub sshd_config: Option, - pub key: Option>, + pub key: Vec, } #[derive(Debug, Deserialize)] @@ -49,9 +47,9 @@ pub struct PackageConfig { /// Packages to install pub pkg: Vec, /// Enable libvirt - pub virtualization: Option, + pub virtualization: bool, /// Enable docker - pub docker: Option, + pub docker: bool, } #[derive(Debug, Deserialize)] @@ -70,16 +68,12 @@ pub struct GeneralConfig { pub mode: InstallMode, /// System locale pub locale: String, - /// Keyboard Layout - pub keyboard_layout: String, - /// Keyboard Variant - pub keyboard_variant: Option, + /// Keymap + pub keymap: String, /// Timezone pub timezone: String, /// Hostname pub hostname: String, - // Root password - pub root_password: Option, } #[derive(Debug, Deserialize)] @@ -94,16 +88,3 @@ pub enum InstallMode { // TODO : Evaluate Kiosk, } - -impl Display for InstallMode { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - InstallMode::Base => f.write_str("Base")?, - InstallMode::Desktop => f.write_str("Desktop")?, - InstallMode::Server => f.write_str("Server")?, - InstallMode::Kiosk => f.write_str("Kiosk")?, - } - - Ok(()) - } -} diff --git a/src/install/first_boot.rs b/src/install/first_boot.rs index 93dcf4f..f2e30e2 100644 --- a/src/install/first_boot.rs +++ b/src/install/first_boot.rs @@ -6,7 +6,7 @@ use crate::{ print_status, }; -use super::{uncomment_first_value_of, user::change_passwd}; +use super::uncomment_first_value_of; /// Generate the `/etc/fstab` file pub fn genfstab() { @@ -38,7 +38,11 @@ pub fn first_boot_values(conf: &GeneralConfig) { // Keymap print_status("Writing /etc/vconsole.conf"); - std::fs::write("/mnt/etc/vconsole.conf", build_vconsole_conf(conf)).unwrap(); + std::fs::write( + "/mnt/etc/vconsole.conf", + format!("KEYMAP=\"{}\"", conf.keymap), + ) + .unwrap(); // Hostname print_status("Writing /etc/hostname"); @@ -51,20 +55,5 @@ pub fn first_boot_values(conf: &GeneralConfig) { arch_chroot(&["hwclock", "--systohc"], None, false); - if let Some(root_pw) = &conf.root_password { - change_passwd("root", root_pw); - } - systemd_service_enable("NetworkManager.service"); } - -pub fn build_vconsole_conf(conf: &GeneralConfig) -> String { - let mut ret = format!("KEYMAP={}\n", conf.keyboard_layout); - ret.push_str(&format!("XBKLAYOUT={}\n", conf.keyboard_layout)); - - if let Some(variant) = &conf.keyboard_variant { - ret.push_str(&format!("XKBMODEL={variant}\n")); - } - - ret -} diff --git a/src/install/mod.rs b/src/install/mod.rs index a197d79..e9f0fc6 100644 --- a/src/install/mod.rs +++ b/src/install/mod.rs @@ -88,7 +88,7 @@ pub fn install(conf: InstallConfig) { // System Setup first_boot_values(&conf.general); setup_skel(&conf.general); - setup_users(&conf.user.unwrap_or_default()); + setup_users(&conf.user); setup_ssh(conf.ssh); @@ -118,11 +118,11 @@ pub fn install(conf: InstallConfig) { } } - if conf.pkg.virtualization.unwrap_or_default() { + if conf.pkg.virtualization { // TODO : Enable virtualization } - if conf.pkg.docker.unwrap_or_default() { + if conf.pkg.docker { // TODO : Enable docker } diff --git a/src/install/skel.rs b/src/install/skel.rs index e4231da..6cb3214 100644 --- a/src/install/skel.rs +++ b/src/install/skel.rs @@ -1,14 +1,6 @@ -use crate::{config::GeneralConfig, create_iso::build_kxkbrc, linux::install_file, print_status}; +use crate::config::GeneralConfig; pub fn setup_skel(conf: &GeneralConfig) { - print_status("Setting user config"); - std::fs::create_dir_all("/mnt/etc/skel/.config").unwrap(); - install_file( - "/mnt/etc/skel/.config/kxkbrc", - &build_kxkbrc( - conf.keyboard_layout.as_str(), - conf.keyboard_variant.as_ref().map(|x| x.as_str()), - ), - 0o644, - ); + // TODO : Implement + unimplemented!() } diff --git a/src/install/ssh.rs b/src/install/ssh.rs index f1685de..01f3b89 100644 --- a/src/install/ssh.rs +++ b/src/install/ssh.rs @@ -14,7 +14,7 @@ pub fn setup_ssh(conf: Option) { install_file("/mnt/etc/ssh/sshd_config", &content, 0o644); } - for key in &conf.key.unwrap_or_default() { + for key in &conf.key { for user in &key.users { let path = if user == "root" { std::fs::create_dir_all("/root/.ssh").unwrap(); diff --git a/src/install/user.rs b/src/install/user.rs index de8c82c..0152dd9 100644 --- a/src/install/user.rs +++ b/src/install/user.rs @@ -4,10 +4,6 @@ use crate::{ print_status, }; -pub fn change_passwd(user: &str, pw: &str) { - arch_chroot(&["passwd", user], Some(&format!("{}\n{}\n", pw, pw)), false); -} - /// Setup the users of the system pub fn setup_users(conf: &[UserConfig]) { let mut doas_conf = String::new(); @@ -15,7 +11,11 @@ pub fn setup_users(conf: &[UserConfig]) { for user in conf { arch_chroot(&["useradd", "-m", &user.name], None, false); - change_passwd(&user.name, &user.password); + arch_chroot( + &["passwd", &user.name], + Some(&format!("{}\n{}\n", user.password, user.password)), + false, + ); if user.doas_root { print_status(&format!("Allowing root doas for {}", user.name)); diff --git a/src/main.rs b/src/main.rs index da97f49..4f85aed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,11 +8,9 @@ mod create_iso; mod install; mod linux; mod pkg; -mod print; use create_iso::create_iso; use install::install; use linux::is_root; -use print::print_config; use yansi::{Color, Paint}; fn print_status(msg: &str) { @@ -99,8 +97,9 @@ fn main() { } }; - print_config(&conf); - print!("Do you want to proceed with this configuration? (yes/no) "); + // TODO : Show config + println!("Config: {conf:?}"); + print!("\nDo you want to proceed with this configuration? (yes/no) "); let mut input = String::new(); std::io::stdout().flush().expect("Error flushing stdout."); diff --git a/src/print.rs b/src/print.rs deleted file mode 100644 index b8b3594..0000000 --- a/src/print.rs +++ /dev/null @@ -1,223 +0,0 @@ -use yansi::{Color, Paint}; - -use crate::config::InstallConfig; - -pub fn print_config(conf: &InstallConfig) { - println!("🚀 Install Configuration:"); - - let mut root_info = Tree::new(); - - let mut drive_info = Tree::new(); - drive_info.add_str(format!( - "💾 {} {}", - conf.drive.boot.paint(Color::Red), - "[EFI]".paint(Color::Blue) - )); - drive_info.add_str(format!( - "{} {} {}", - if conf.drive.encryption.is_some() { - "🔒" - } else { - "💾" - }, - conf.drive.root.paint(Color::Red), - "[ROOT]".paint(Color::Blue) - )); - - root_info.add_tree("💾 Drive Selection", drive_info); - - let mut general_info = Tree::new(); - - general_info.add_str(format!( - "💎 {} {}", - "Mode:".paint(Color::Yellow), - conf.general.mode - )); - general_info.add_str(format!( - "🖥️ {} {}", - "Hostname:".paint(Color::Yellow), - conf.general.hostname - )); - general_info.add_str(format!( - "⌨️ {} {} {}", - "Keyboard:".paint(Color::Yellow), - conf.general.keyboard_layout, - conf.general - .keyboard_variant - .as_ref() - .unwrap_or(&String::new()) - )); - general_info.add_str(format!( - "🌍 {} {}", - "Locale:".paint(Color::Yellow), - conf.general.locale - )); - general_info.add_str(format!( - "⌛ {} {}", - "Timezone:".paint(Color::Yellow), - conf.general.timezone - )); - if conf.general.root_password.is_some() { - general_info.add_str(format!( - "🔑 {} {}", - "Root Password".paint(Color::Yellow), - "✔️".paint(Color::Green) - )); - } - - root_info.add_tree("🔨 General", general_info); - - let mut pkg_info = Tree::new(); - - if conf.pkg.docker.unwrap_or_default() { - pkg_info.add_str(format!("🐳 Docker {}", "✔️".paint(Color::Green))); - } - - if conf.pkg.virtualization.unwrap_or_default() { - pkg_info.add_str(format!("🎃 Virtualization {}", "✔️".paint(Color::Green))); - } - - if !conf.pkg.pkg.is_empty() { - pkg_info.add_str(format!( - "📦 Additional packages: {}", - conf.pkg.pkg.join(" ") - )); - } - - root_info.add_tree("📦 Packages", pkg_info); - - let mut users_info = Tree::new(); - - let empty = Vec::new(); - let user_conf = conf.user.as_ref().unwrap_or(&empty); - - for user in user_conf { - users_info.add_str(format!( - "👤 {} {}", - user.name, - if user.doas_root { "🔑" } else { "" } - )); - } - - root_info.add_tree("🧛 Users", users_info); - - if let Some(ssh_conf) = &conf.ssh { - let mut ssh_info = Tree::new(); - - if let Some(sshd_conf) = &ssh_conf.sshd_config { - ssh_info.add_str(format!("📖 Installing {sshd_conf} as sshd_config")); - } - - if let Some(keys) = &ssh_conf.key { - for key in keys { - let key_origin = key.key.split(" ").nth(2).unwrap_or_default(); - - ssh_info.add_str(format!( - "🔑 Key {} for {}", - key_origin.paint(Color::Blue), - key.users.join(", ").paint(Color::Yellow) - )); - } - } - - root_info.add_tree("🌐 SSH", ssh_info); - } - - if let Some(ai_conf) = &conf.ai { - let mut ai_info = Tree::new(); - - if ai_conf.gpu { - ai_info.add_str(format!("🟩 Use CUDA {}", "✔️".paint(Color::Green))); - } - - if let Some(models) = &ai_conf.models { - ai_info.add_str(format!("⬇️ Pull Models: {}", models.join(", "))); - } - - root_info.add_tree("🦙 Ollama", ai_info); - } - - println!("{}", root_info.render(0)); -} - -pub struct Tree { - elements: Vec, -} - -pub enum TreeEntry { - Tree(String, Tree), - Str(String), -} - -impl Tree { - pub fn new() -> Self { - Self { elements: vec![] } - } - - pub fn add_tree(&mut self, key: &str, item: Tree) { - self.elements.push(TreeEntry::Tree(key.to_string(), item)); - } - - pub fn add_str(&mut self, item: String) { - self.elements.push(TreeEntry::Str(item)); - } - - pub fn render(&self, depth: i32) -> String { - const DEPTH_INCREASE: i32 = 3; - - let mut ret = String::new(); - - let len = self.elements.len(); - - for (index, val) in self.elements.iter().enumerate() { - let padding = pad_with_bars(depth, DEPTH_INCREASE); - - let path_repr = if (index + 1) == len { - if matches!(val, TreeEntry::Tree(_, _)) { - "├─" - } else { - "└─" - } - } else { - "├─" - }; - - match val { - TreeEntry::Tree(key, tree) => { - if !tree.elements.is_empty() { - ret.push_str(&format!("{padding}{path_repr} {key}\n")); - ret.push_str(&tree.render(depth + DEPTH_INCREASE)) - } - } - TreeEntry::Str(str) => { - ret.push_str(&format!("{padding}{path_repr} {str}\n")); - } - } - } - - ret - } -} - -pub fn pad_with_bars(n: i32, depth_inc: i32) -> String { - let amount = n / depth_inc; - - let mut ret = String::new(); - - if amount >= 1 { - ret.push_str("│"); - } - - ret.push_str(&pad(n - amount)); - ret -} - -pub fn pad(n: i32) -> String { - let mut ret = String::new(); - - for _ in 0..n { - ret.push_str(" "); - } - - ret -}