Compare commits
3 commits
ffbc2e5e72
...
753f53d4da
Author | SHA1 | Date | |
---|---|---|---|
753f53d4da | |||
59203d9085 | |||
26cd7c264c |
9 changed files with 82 additions and 45 deletions
14
README.md
14
README.md
|
@ -2,9 +2,10 @@
|
||||||
navOS Installer
|
navOS Installer
|
||||||
|
|
||||||
## Create install medium
|
## Create install medium
|
||||||
You can create a bootable install medium either with or without GUI:
|
You can create a bootable install medium with various predefined options:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
navinstall create-iso [--without_gui]
|
navinstall create-iso [--without_gui] [--kb_layout <LAYOUT>] [--kb_variant <VARIANT>]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Install a system
|
## Install a system
|
||||||
|
@ -15,3 +16,12 @@ navinstall install config.toml
|
||||||
|
|
||||||
`config.toml` is a system configuration describing how to install the system.
|
`config.toml` is a system configuration describing how to install the system.
|
||||||
Example configurations can be found [here](installs) or at `/usr/share/navinstall/installs/`.
|
Example configurations can be found [here](installs) or at `/usr/share/navinstall/installs/`.
|
||||||
|
|
||||||
|
## Create an unattended installer
|
||||||
|
You can create an install medium which immidiately upon boot installs a configuration:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
navinstall create-iso --install config.toml
|
||||||
|
```
|
||||||
|
|
||||||
|
> <b style="color:orange">⚠️ WARNING</b>: This is potentially destructive and will probably wipe all data on the disks if randomly booted from.
|
||||||
|
|
|
@ -55,6 +55,17 @@ name = "u"
|
||||||
# User password
|
# User password
|
||||||
password = "pass"
|
password = "pass"
|
||||||
|
|
||||||
|
# User ID
|
||||||
|
uid = 1001
|
||||||
|
|
||||||
|
# The home directory of the user
|
||||||
|
home_dir = "/home/u"
|
||||||
|
# You can leave the user without a home dir using:
|
||||||
|
# home_dir = ""
|
||||||
|
|
||||||
|
# Set the shell of the user
|
||||||
|
shell = "/bin/bash"
|
||||||
|
|
||||||
# Allow user to use `doas` as root
|
# Allow user to use `doas` as root
|
||||||
doas_root= true
|
doas_root= true
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,9 @@ pub struct SSHKey {
|
||||||
pub struct UserConfig {
|
pub struct UserConfig {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub password: String,
|
pub password: String,
|
||||||
|
pub uid: Option<u32>,
|
||||||
|
pub home_dir: Option<String>,
|
||||||
|
pub shell: Option<String>,
|
||||||
pub doas_root: Option<bool>,
|
pub doas_root: Option<bool>,
|
||||||
pub docker: Option<bool>,
|
pub docker: Option<bool>,
|
||||||
pub virtualization: Option<bool>,
|
pub virtualization: Option<bool>,
|
||||||
|
|
|
@ -35,6 +35,7 @@ pub fn first_boot_values(conf: &GeneralConfig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::os::unix::fs::symlink(tz_link, "/mnt/etc/localtime").unwrap();
|
std::os::unix::fs::symlink(tz_link, "/mnt/etc/localtime").unwrap();
|
||||||
|
arch_chroot(&["hwclock", "--systohc"], None, false);
|
||||||
|
|
||||||
// Keymap
|
// Keymap
|
||||||
print_status("Writing /etc/vconsole.conf");
|
print_status("Writing /etc/vconsole.conf");
|
||||||
|
@ -49,8 +50,6 @@ pub fn first_boot_values(conf: &GeneralConfig) {
|
||||||
uncomment_first_value_of(&conf.locale, "/mnt/etc/locale.gen");
|
uncomment_first_value_of(&conf.locale, "/mnt/etc/locale.gen");
|
||||||
arch_chroot(&["locale-gen"], None, false);
|
arch_chroot(&["locale-gen"], None, false);
|
||||||
|
|
||||||
arch_chroot(&["hwclock", "--systohc"], None, false);
|
|
||||||
|
|
||||||
if let Some(root_pw) = &conf.root_password {
|
if let Some(root_pw) = &conf.root_password {
|
||||||
change_passwd("root", root_pw);
|
change_passwd("root", root_pw);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ pub fn setup_mkinitcpio(conf: &DriveConfig) {
|
||||||
std::fs::write("/mnt/etc/kernel/cmdline", format!("root={}", conf.root)).unwrap();
|
std::fs::write("/mnt/etc/kernel/cmdline", format!("root={}", conf.root)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : more configs
|
|
||||||
print_status("Writing /etc/mkinitcpio.conf");
|
print_status("Writing /etc/mkinitcpio.conf");
|
||||||
install_file(
|
install_file(
|
||||||
"/mnt/etc/mkinitcpio.conf",
|
"/mnt/etc/mkinitcpio.conf",
|
||||||
|
|
|
@ -76,6 +76,7 @@ pub fn uncomment_tag(tag: &str, file: &str) {
|
||||||
std::fs::write(file, new).unwrap();
|
std::fs::write(file, new).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Install a config on a new system
|
||||||
pub fn install(conf: InstallConfig) {
|
pub fn install(conf: InstallConfig) {
|
||||||
// Drive Setup
|
// Drive Setup
|
||||||
format_drives(&conf.drive);
|
format_drives(&conf.drive);
|
||||||
|
|
|
@ -13,7 +13,35 @@ pub fn setup_users(conf: &[UserConfig]) {
|
||||||
let mut doas_conf = String::new();
|
let mut doas_conf = String::new();
|
||||||
|
|
||||||
for user in conf {
|
for user in conf {
|
||||||
arch_chroot(&["useradd", "-m", &user.name], None, false);
|
let mut cmd = vec!["useradd"];
|
||||||
|
|
||||||
|
if let Some(home_dir) = &user.home_dir {
|
||||||
|
if home_dir.is_empty() {
|
||||||
|
cmd.push("-M");
|
||||||
|
} else {
|
||||||
|
cmd.push("-m");
|
||||||
|
cmd.push("-d");
|
||||||
|
cmd.push(home_dir);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cmd.push("-m");
|
||||||
|
}
|
||||||
|
|
||||||
|
let uid = user.uid.map(|x| x.to_string());
|
||||||
|
|
||||||
|
if let Some(uid) = &uid {
|
||||||
|
cmd.push("-u");
|
||||||
|
cmd.push(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(shell) = &user.shell {
|
||||||
|
cmd.push("-s");
|
||||||
|
cmd.push(shell);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.push(&user.name);
|
||||||
|
|
||||||
|
arch_chroot(&cmd, None, false);
|
||||||
|
|
||||||
change_passwd(&user.name, &user.password);
|
change_passwd(&user.name, &user.password);
|
||||||
|
|
||||||
|
|
62
src/main.rs
62
src/main.rs
|
@ -50,25 +50,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
Some(("create-img", install_args)) => {
|
Some(("create-img", install_args)) => {
|
||||||
let config_file: &String = install_args.get_one("config").unwrap();
|
let config_file: &String = install_args.get_one("config").unwrap();
|
||||||
let config_content = std::fs::read_to_string(config_file);
|
let conf = read_conf(config_file);
|
||||||
|
|
||||||
let conf: InstallConfig = match config_content {
|
|
||||||
Ok(content) => match toml::from_str(&content) {
|
|
||||||
Ok(config) => config,
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!(
|
|
||||||
"{} {}",
|
|
||||||
"Error: Could not deserialize TOML file.".paint(Color::Red),
|
|
||||||
e.paint(Color::Red)
|
|
||||||
);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(_) => {
|
|
||||||
eprintln!("{}", "Error: Could not read config file.".paint(Color::Red));
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
println!("Installing to a disk image is not yet supported");
|
println!("Installing to a disk image is not yet supported");
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
@ -81,25 +63,7 @@ fn main() {
|
||||||
|
|
||||||
let config_file: &String = install_args.get_one("config").unwrap();
|
let config_file: &String = install_args.get_one("config").unwrap();
|
||||||
let force = install_args.get_flag("force");
|
let force = install_args.get_flag("force");
|
||||||
let config_content = std::fs::read_to_string(config_file);
|
let conf = read_conf(config_file);
|
||||||
|
|
||||||
let conf: InstallConfig = match config_content {
|
|
||||||
Ok(content) => match toml::from_str(&content) {
|
|
||||||
Ok(config) => config,
|
|
||||||
Err(e) => {
|
|
||||||
eprintln!(
|
|
||||||
"{} {}",
|
|
||||||
"Error: Could not deserialize TOML file.".paint(Color::Red),
|
|
||||||
e.paint(Color::Red)
|
|
||||||
);
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(_) => {
|
|
||||||
eprintln!("{}", "Error: Could not read config file.".paint(Color::Red));
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if !force {
|
if !force {
|
||||||
print_config(&conf);
|
print_config(&conf);
|
||||||
|
@ -128,3 +92,25 @@ pub fn expect_yes() {
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn read_conf(config_file: &str) -> InstallConfig {
|
||||||
|
let config_content = std::fs::read_to_string(config_file);
|
||||||
|
|
||||||
|
match config_content {
|
||||||
|
Ok(content) => match toml::from_str(&content) {
|
||||||
|
Ok(config) => config,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!(
|
||||||
|
"{} {}",
|
||||||
|
"Error: Could not deserialize TOML file.".paint(Color::Red),
|
||||||
|
e.paint(Color::Red)
|
||||||
|
);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
eprintln!("{}", "Error: Could not read config file.".paint(Color::Red));
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue