iso with custom user, pass, uid + systemd units
All checks were successful
ci/woodpecker/push/build Pipeline was successful

This commit is contained in:
JMARyA 2025-04-15 22:58:08 +02:00
parent 93b254055a
commit fa6439bce8
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
3 changed files with 77 additions and 1 deletions

View file

@ -1,4 +1,4 @@
use clap::{arg, command}; use clap::{ArgAction, arg, command};
pub fn get_args() -> clap::ArgMatches { pub fn get_args() -> clap::ArgMatches {
command!() command!()
@ -10,6 +10,10 @@ pub fn get_args() -> clap::ArgMatches {
.arg(arg!(--no_tmp "Create ISO on disk")) .arg(arg!(--no_tmp "Create ISO on disk"))
.arg(arg!(--kb_layout <LAYOUT> "Create ISO with this keyboard layout")) .arg(arg!(--kb_layout <LAYOUT> "Create ISO with this keyboard layout"))
.arg(arg!(--kb_variant <VARIANT> "Create ISO with this keyboard layout variant")) .arg(arg!(--kb_variant <VARIANT> "Create ISO with this keyboard layout variant"))
.arg(arg!(--user <USER> "Change the system user"))
.arg(arg!(--pass <PASS> "Change the system users password"))
.arg(arg!(--uid <UID> "Change the system users UID"))
.arg(arg!(--unit <UNIT> "Include a systemd unit").action(ArgAction::Append))
.arg(arg!(--install <CONFIG> "Create ISO which automatically installs <CONFIG> upon boot.")) .arg(arg!(--install <CONFIG> "Create ISO which automatically installs <CONFIG> upon boot."))
) )
.subcommand( .subcommand(

View file

@ -1,3 +1,5 @@
use std::os::unix::fs::symlink;
use yansi::{Color, Paint}; use yansi::{Color, Paint};
use crate::{expect_yes, install::uncomment_tag, linux::is_root, linux::run_command, print_status}; 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, no_tmp: bool,
kb_layout: &str, kb_layout: &str,
kb_variant: Option<&str>, kb_variant: Option<&str>,
user: Option<(String, String, u16)>,
systemd_units: Vec<String>,
install: Option<&String>, install: Option<&String>,
) { ) {
if !is_root() { if !is_root() {
@ -50,6 +54,56 @@ pub fn create_iso(
setup_auto_install(&install_conf); 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"); print_status("Setting keyboard layout");
std::fs::create_dir_all("./iso/airootfs/etc/skel/.config").unwrap(); std::fs::create_dir_all("./iso/airootfs/etc/skel/.config").unwrap();
std::fs::write( std::fs::write(

View file

@ -26,11 +26,29 @@ fn main() {
iso_args.get_one("kb_variant").map(|x: &String| x.as_str()); iso_args.get_one("kb_variant").map(|x: &String| x.as_str());
let auto_install_config: Option<&String> = iso_args.get_one("install"); 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( create_iso(
without_gui, without_gui,
no_tmp, no_tmp,
kb_layout, kb_layout,
kb_variant, kb_variant,
user,
units.into_iter().map(|x: &String| x.to_string()).collect(),
auto_install_config, auto_install_config,
); );
std::process::exit(0); std::process::exit(0);