From fa6439bce8318f21202848a1c73e6174ee52e937 Mon Sep 17 00:00:00 2001 From: JMARyA Date: Tue, 15 Apr 2025 22:58:08 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20iso=20with=20custom=20user,=20pass,?= =?UTF-8?q?=20uid=20+=20systemd=20units?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/args.rs | 6 +++++- src/create_iso.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 18 ++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/args.rs b/src/args.rs index ee015cb..875b293 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,4 +1,4 @@ -use clap::{arg, command}; +use clap::{ArgAction, arg, command}; pub fn get_args() -> clap::ArgMatches { command!() @@ -10,6 +10,10 @@ pub fn get_args() -> clap::ArgMatches { .arg(arg!(--no_tmp "Create ISO on disk")) .arg(arg!(--kb_layout "Create ISO with this keyboard layout")) .arg(arg!(--kb_variant "Create ISO with this keyboard layout variant")) + .arg(arg!(--user "Change the system user")) + .arg(arg!(--pass "Change the system users password")) + .arg(arg!(--uid "Change the system users UID")) + .arg(arg!(--unit "Include a systemd unit").action(ArgAction::Append)) .arg(arg!(--install "Create ISO which automatically installs upon boot.")) ) .subcommand( diff --git a/src/create_iso.rs b/src/create_iso.rs index 7842a2b..5708ecf 100644 --- a/src/create_iso.rs +++ b/src/create_iso.rs @@ -1,3 +1,5 @@ +use std::os::unix::fs::symlink; + use yansi::{Color, Paint}; use crate::{expect_yes, install::uncomment_tag, linux::is_root, linux::run_command, print_status}; @@ -18,6 +20,8 @@ pub fn create_iso( no_tmp: bool, kb_layout: &str, kb_variant: Option<&str>, + user: Option<(String, String, u16)>, + systemd_units: Vec, install: Option<&String>, ) { if !is_root() { @@ -50,6 +54,56 @@ pub fn create_iso( setup_auto_install(&install_conf); } + if let Some((user, pass, uid)) = user { + print_status(&format!("Setting user {user}")); + let hashed_pw = run_command( + &["openssl", "passwd", "-6"], + Some(&format!("{pass}\n{pass}\n")), + false, + ) + .0; + std::fs::write( + "./iso/airootfs/etc/doas.conf", + format!("permit persist {user} as root\n"), + ) + .unwrap(); + + std::fs::write("./iso/airootfs/etc/passwd", format!("root:x:0:0:root:/root:/usr/bin/zsh\n{user}:x:{uid}:{uid}::/home/{user}:/usr/bin/zsh\n")).unwrap(); + std::fs::write( + "./iso/airootfs/etc/shadow", + format!("root::14871::::::\n{user}:{hashed_pw}"), + ) + .unwrap(); + std::fs::write( + "./iso/airootfs/etc/sddm.conf.d/autologin.conf", + format!("[Autologin]\nUser={user}\nSession=plasma\nRelogin=true\n"), + ) + .unwrap(); + } + + for unit in systemd_units { + print_status("Including unit file {unit}"); + let file_name = std::path::Path::new(&unit) + .file_name() + .unwrap() + .to_str() + .unwrap(); + + let target_dir = std::path::Path::new("./iso/airootfs/etc/systemd/system"); + let target_path = target_dir.join(file_name); + + // Copy unit file to target systemd directory + std::fs::create_dir_all(target_dir).expect("Failed to create systemd directory"); + std::fs::copy(&unit, &target_path).expect("Failed to copy unit file"); + + // Enable the unit by symlinking it to multi-user.target.wants/ + let wants_dir = target_dir.join("multi-user.target.wants"); + std::fs::create_dir_all(&wants_dir).expect("Failed to create wants directory"); + + let symlink_path = wants_dir.join(file_name); + symlink(&target_path, &symlink_path).expect("Failed to create symlink"); + } + print_status("Setting keyboard layout"); std::fs::create_dir_all("./iso/airootfs/etc/skel/.config").unwrap(); std::fs::write( diff --git a/src/main.rs b/src/main.rs index 712e405..510a160 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,11 +26,29 @@ fn main() { iso_args.get_one("kb_variant").map(|x: &String| x.as_str()); let auto_install_config: Option<&String> = iso_args.get_one("install"); + let user: Option<&String> = iso_args.get_one("user"); + let pass: Option<&String> = iso_args.get_one("pass"); + let uid: Option<&String> = iso_args.get_one("uid"); + + let user = if user.is_some() && pass.is_some() { + Some(( + user.unwrap().to_string(), + pass.unwrap().to_string(), + uid.map(|x| x.parse().unwrap()).unwrap_or(1000), + )) + } else { + None + }; + + let units: Vec<_> = iso_args.get_many("unit").unwrap_or_default().collect(); + create_iso( without_gui, no_tmp, kb_layout, kb_variant, + user, + units.into_iter().map(|x: &String| x.to_string()).collect(), auto_install_config, ); std::process::exit(0);