Hobbling along
This commit is contained in:
parent
86a518f2fe
commit
8924bf5cb7
|
@ -81,7 +81,7 @@ impl Actionable for ConfigureNixDaemonService {
|
||||||
const DARWIN_NIX_DAEMON_DEST: &str =
|
const DARWIN_NIX_DAEMON_DEST: &str =
|
||||||
"/Library/LaunchDaemons/org.nixos.nix-daemon.plist";
|
"/Library/LaunchDaemons/org.nixos.nix-daemon.plist";
|
||||||
|
|
||||||
let src = Path::new("/nix/var/nix/profiles/default").join(DARWIN_NIX_DAEMON_DEST);
|
let src = Path::new("/nix/var/nix/profiles/default/Library/LaunchDaemons/org.nixos.nix-daemon.plist");
|
||||||
tokio::fs::copy(src.clone(), DARWIN_NIX_DAEMON_DEST)
|
tokio::fs::copy(src.clone(), DARWIN_NIX_DAEMON_DEST)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
|
|
|
@ -9,16 +9,18 @@ use crate::actions::{Action, ActionDescription, ActionState, Actionable};
|
||||||
pub struct CreateUser {
|
pub struct CreateUser {
|
||||||
name: String,
|
name: String,
|
||||||
uid: usize,
|
uid: usize,
|
||||||
|
groupname: String,
|
||||||
gid: usize,
|
gid: usize,
|
||||||
action_state: ActionState,
|
action_state: ActionState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateUser {
|
impl CreateUser {
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub fn plan(name: String, uid: usize, gid: usize) -> Self {
|
pub fn plan(name: String, uid: usize, groupname: String, gid: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
uid,
|
uid,
|
||||||
|
groupname,
|
||||||
gid,
|
gid,
|
||||||
action_state: ActionState::Uncompleted,
|
action_state: ActionState::Uncompleted,
|
||||||
}
|
}
|
||||||
|
@ -36,6 +38,7 @@ impl Actionable for CreateUser {
|
||||||
let Self {
|
let Self {
|
||||||
name,
|
name,
|
||||||
uid,
|
uid,
|
||||||
|
groupname: _,
|
||||||
gid,
|
gid,
|
||||||
action_state: _,
|
action_state: _,
|
||||||
} = self;
|
} = self;
|
||||||
|
@ -52,12 +55,14 @@ impl Actionable for CreateUser {
|
||||||
#[tracing::instrument(skip_all, fields(
|
#[tracing::instrument(skip_all, fields(
|
||||||
user = self.name,
|
user = self.name,
|
||||||
uid = self.uid,
|
uid = self.uid,
|
||||||
|
groupname = self.groupname,
|
||||||
gid = self.gid,
|
gid = self.gid,
|
||||||
))]
|
))]
|
||||||
async fn execute(&mut self) -> Result<(), Self::Error> {
|
async fn execute(&mut self) -> Result<(), Self::Error> {
|
||||||
let Self {
|
let Self {
|
||||||
name,
|
name,
|
||||||
uid,
|
uid,
|
||||||
|
groupname,
|
||||||
gid,
|
gid,
|
||||||
action_state,
|
action_state,
|
||||||
} = self;
|
} = self;
|
||||||
|
@ -77,15 +82,79 @@ impl Actionable for CreateUser {
|
||||||
| OperatingSystem::Darwin => {
|
| OperatingSystem::Darwin => {
|
||||||
execute_command(Command::new("/usr/bin/dscl").args([
|
execute_command(Command::new("/usr/bin/dscl").args([
|
||||||
".",
|
".",
|
||||||
"create",
|
"-create",
|
||||||
&format!("/Users/{name}"),
|
&format!("/Users/{name}"),
|
||||||
"UniqueId",
|
]))
|
||||||
|
.await
|
||||||
|
.map_err(Self::Error::Command)?;
|
||||||
|
execute_command(Command::new("/usr/bin/dscl").args([
|
||||||
|
".",
|
||||||
|
"-create",
|
||||||
|
&format!("/Users/{name}"),
|
||||||
|
"UniqueID",
|
||||||
&format!("{uid}"),
|
&format!("{uid}"),
|
||||||
|
]))
|
||||||
|
.await
|
||||||
|
.map_err(Self::Error::Command)?;
|
||||||
|
execute_command(Command::new("/usr/bin/dscl").args([
|
||||||
|
".",
|
||||||
|
"-create",
|
||||||
|
&format!("/Users/{name}"),
|
||||||
"PrimaryGroupID",
|
"PrimaryGroupID",
|
||||||
&format!("{gid}"),
|
&format!("{gid}"),
|
||||||
]))
|
]))
|
||||||
.await
|
.await
|
||||||
.map_err(Self::Error::Command)?;
|
.map_err(Self::Error::Command)?;
|
||||||
|
execute_command(Command::new("/usr/bin/dscl").args([
|
||||||
|
".",
|
||||||
|
"-create",
|
||||||
|
&format!("/Users/{name}"),
|
||||||
|
"NFSHomeDirectory",
|
||||||
|
"/var/empty",
|
||||||
|
]))
|
||||||
|
.await
|
||||||
|
.map_err(Self::Error::Command)?;
|
||||||
|
execute_command(Command::new("/usr/bin/dscl").args([
|
||||||
|
".",
|
||||||
|
"-create",
|
||||||
|
&format!("/Users/{name}"),
|
||||||
|
"UserShell",
|
||||||
|
"/sbin/nologin",
|
||||||
|
]))
|
||||||
|
.await
|
||||||
|
.map_err(Self::Error::Command)?;
|
||||||
|
execute_command(
|
||||||
|
Command::new("/usr/bin/dscl")
|
||||||
|
.args([
|
||||||
|
".",
|
||||||
|
"-append",
|
||||||
|
&format!("/Groups/{groupname}"),
|
||||||
|
"GroupMembership",
|
||||||
|
])
|
||||||
|
.arg(&name),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(Self::Error::Command)?;
|
||||||
|
execute_command(Command::new("/usr/bin/dscl").args([
|
||||||
|
".",
|
||||||
|
"-create",
|
||||||
|
&format!("/Users/{name}"),
|
||||||
|
"IsHidden",
|
||||||
|
"1",
|
||||||
|
]))
|
||||||
|
.await
|
||||||
|
.map_err(Self::Error::Command)?;
|
||||||
|
execute_command(
|
||||||
|
Command::new("/usr/sbin/dseditgroup")
|
||||||
|
.args(["-o", "edit"])
|
||||||
|
.arg("-a")
|
||||||
|
.arg(&name)
|
||||||
|
.arg("-t")
|
||||||
|
.arg(&name)
|
||||||
|
.arg(groupname),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(Self::Error::Command)?;
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
execute_command(Command::new("useradd").args([
|
execute_command(Command::new("useradd").args([
|
||||||
|
@ -124,6 +193,7 @@ impl Actionable for CreateUser {
|
||||||
let Self {
|
let Self {
|
||||||
name,
|
name,
|
||||||
uid,
|
uid,
|
||||||
|
groupname: _,
|
||||||
gid,
|
gid,
|
||||||
action_state: _,
|
action_state: _,
|
||||||
} = self;
|
} = self;
|
||||||
|
@ -146,6 +216,7 @@ impl Actionable for CreateUser {
|
||||||
let Self {
|
let Self {
|
||||||
name,
|
name,
|
||||||
uid: _,
|
uid: _,
|
||||||
|
groupname: _,
|
||||||
gid: _,
|
gid: _,
|
||||||
action_state,
|
action_state,
|
||||||
} = self;
|
} = self;
|
||||||
|
@ -163,7 +234,13 @@ impl Actionable for CreateUser {
|
||||||
patch: _,
|
patch: _,
|
||||||
}
|
}
|
||||||
| OperatingSystem::Darwin => {
|
| OperatingSystem::Darwin => {
|
||||||
todo!()
|
execute_command(Command::new("/usr/bin/dscl").args([
|
||||||
|
".",
|
||||||
|
"-delete",
|
||||||
|
&format!("/Users/{name}"),
|
||||||
|
]))
|
||||||
|
.await
|
||||||
|
.map_err(Self::Error::Command)?;
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
execute_command(Command::new("userdel").args([&name.to_string()]))
|
execute_command(Command::new("userdel").args([&name.to_string()]))
|
||||||
|
|
|
@ -56,9 +56,13 @@ impl Actionable for BootstrapVolume {
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(Self::Error::Command)?;
|
.map_err(Self::Error::Command)?;
|
||||||
execute_command(Command::new("launchctl").args(["-k", "system/org.nixos.darwin-store"]))
|
execute_command(Command::new("launchctl").args([
|
||||||
.await
|
"kickstart",
|
||||||
.map_err(Self::Error::Command)?;
|
"-k",
|
||||||
|
"system/org.nixos.darwin-store",
|
||||||
|
]))
|
||||||
|
.await
|
||||||
|
.map_err(Self::Error::Command)?;
|
||||||
|
|
||||||
tracing::trace!("Bootstrapped volume");
|
tracing::trace!("Bootstrapped volume");
|
||||||
*action_state = ActionState::Completed;
|
*action_state = ActionState::Completed;
|
||||||
|
|
|
@ -121,14 +121,9 @@ impl Actionable for CreateVolume {
|
||||||
}
|
}
|
||||||
tracing::debug!("Deleting volume");
|
tracing::debug!("Deleting volume");
|
||||||
|
|
||||||
execute_command(Command::new("/usr/sbin/diskutil").args([
|
execute_command(Command::new("/usr/sbin/diskutil").args(["apfs", "deleteVolume", name]))
|
||||||
"apfs",
|
.await
|
||||||
"deleteVolume",
|
.map_err(Self::Error::Command)?;
|
||||||
&format!("{}", disk.display()),
|
|
||||||
name,
|
|
||||||
]))
|
|
||||||
.await
|
|
||||||
.map_err(Self::Error::Command)?;
|
|
||||||
|
|
||||||
tracing::trace!("Deleted volume");
|
tracing::trace!("Deleted volume");
|
||||||
*action_state = ActionState::Completed;
|
*action_state = ActionState::Completed;
|
||||||
|
|
|
@ -73,15 +73,6 @@ impl Actionable for SetupDefaultProfile {
|
||||||
return Err(Self::Error::NoNssCacert); // TODO(@hoverbear): Fix this error
|
return Err(Self::Error::NoNssCacert); // TODO(@hoverbear): Fix this error
|
||||||
};
|
};
|
||||||
|
|
||||||
// Install `nix` itself into the store
|
|
||||||
execute_command(
|
|
||||||
Command::new(nix_pkg.join("bin/nix-env"))
|
|
||||||
.arg("-i")
|
|
||||||
.arg(&nix_pkg),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.map_err(SetupDefaultProfileError::Command)?;
|
|
||||||
|
|
||||||
// Find an `nss-cacert` package, add it too.
|
// Find an `nss-cacert` package, add it too.
|
||||||
let nss_ca_cert_pkg_glob = "/nix/store/*-nss-cacert-*";
|
let nss_ca_cert_pkg_glob = "/nix/store/*-nss-cacert-*";
|
||||||
let mut found_nss_ca_cert_pkg = None;
|
let mut found_nss_ca_cert_pkg = None;
|
||||||
|
@ -101,11 +92,29 @@ impl Actionable for SetupDefaultProfile {
|
||||||
return Err(Self::Error::NoNssCacert);
|
return Err(Self::Error::NoNssCacert);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Install `nix` itself into the store
|
||||||
|
execute_command(
|
||||||
|
Command::new(nix_pkg.join("bin/nix-env"))
|
||||||
|
.arg("-i")
|
||||||
|
.arg(&nix_pkg)
|
||||||
|
.env("HOME", dirs::home_dir().ok_or(Self::Error::NoRootHome)?)
|
||||||
|
.env(
|
||||||
|
"NIX_SSL_CERT_FILE",
|
||||||
|
nss_ca_cert_pkg.join("etc/ssl/certs/ca-bundle.crt"),
|
||||||
|
), /* This is apparently load bearing... */
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(SetupDefaultProfileError::Command)?;
|
||||||
|
|
||||||
// Install `nss-cacert` into the store
|
// Install `nss-cacert` into the store
|
||||||
execute_command(
|
execute_command(
|
||||||
Command::new(nix_pkg.join("bin/nix-env"))
|
Command::new(nix_pkg.join("bin/nix-env"))
|
||||||
.arg("-i")
|
.arg("-i")
|
||||||
.arg(&nss_ca_cert_pkg),
|
.arg(&nss_ca_cert_pkg)
|
||||||
|
.env(
|
||||||
|
"NIX_SSL_CERT_FILE",
|
||||||
|
nss_ca_cert_pkg.join("etc/ssl/certs/ca-bundle.crt"),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(SetupDefaultProfileError::Command)?;
|
.map_err(SetupDefaultProfileError::Command)?;
|
||||||
|
@ -199,4 +208,6 @@ pub enum SetupDefaultProfileError {
|
||||||
#[serde(serialize_with = "crate::serialize_error_to_display")]
|
#[serde(serialize_with = "crate::serialize_error_to_display")]
|
||||||
std::io::Error,
|
std::io::Error,
|
||||||
),
|
),
|
||||||
|
#[error("No root home found to place channel configuration in")]
|
||||||
|
NoRootHome,
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ impl CreateUsersAndGroup {
|
||||||
CreateUser::plan(
|
CreateUser::plan(
|
||||||
format!("{}{count}", settings.nix_build_user_prefix),
|
format!("{}{count}", settings.nix_build_user_prefix),
|
||||||
settings.nix_build_user_id_base + count,
|
settings.nix_build_user_id_base + count,
|
||||||
|
settings.nix_build_group_name.clone(),
|
||||||
settings.nix_build_group_id,
|
settings.nix_build_group_id,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -108,35 +109,30 @@ impl Actionable for CreateUsersAndGroup {
|
||||||
// Create group
|
// Create group
|
||||||
create_group.execute().await?;
|
create_group.execute().await?;
|
||||||
|
|
||||||
// Create users
|
// Mac is apparently not threadsafe here...
|
||||||
// TODO(@hoverbear): Abstract this, it will be common
|
for create_user in create_users.iter_mut() {
|
||||||
let mut set = JoinSet::new();
|
// let mut create_user_clone = create_user.clone();
|
||||||
|
// let _abort_handle = set.spawn(async move {
|
||||||
let mut errors = Vec::default();
|
create_user.execute().await?;
|
||||||
|
// Result::<_, CreateUserError>::Ok((idx, create_user_clone))
|
||||||
for (idx, create_user) in create_users.iter().enumerate() {
|
// });
|
||||||
let mut create_user_clone = create_user.clone();
|
|
||||||
let _abort_handle = set.spawn(async move {
|
|
||||||
create_user_clone.execute().await?;
|
|
||||||
Result::<_, CreateUserError>::Ok((idx, create_user_clone))
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while let Some(result) = set.join_next().await {
|
// while let Some(result) = set.join_next().await {
|
||||||
match result {
|
// match result {
|
||||||
Ok(Ok((idx, success))) => create_users[idx] = success,
|
// Ok(Ok((idx, success))) => create_users[idx] = success,
|
||||||
Ok(Err(e)) => errors.push(e),
|
// Ok(Err(e)) => errors.push(e),
|
||||||
Err(e) => return Err(e)?,
|
// Err(e) => return Err(e)?,
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
|
||||||
if !errors.is_empty() {
|
// if !errors.is_empty() {
|
||||||
if errors.len() == 1 {
|
// if errors.len() == 1 {
|
||||||
return Err(errors.into_iter().next().unwrap().into());
|
// return Err(errors.into_iter().next().unwrap().into());
|
||||||
} else {
|
// } else {
|
||||||
return Err(CreateUsersAndGroupError::CreateUsers(errors));
|
// return Err(CreateUsersAndGroupError::CreateUsers(errors));
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
tracing::trace!("Created users and groups");
|
tracing::trace!("Created users and groups");
|
||||||
*action_state = ActionState::Completed;
|
*action_state = ActionState::Completed;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::path::{Path, PathBuf};
|
use std::{
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::actions::base::{
|
use crate::actions::base::{
|
||||||
darwin::{
|
darwin::{
|
||||||
|
@ -7,7 +10,7 @@ use crate::actions::base::{
|
||||||
CreateVolume, CreateVolumeError, EnableOwnership, EnableOwnershipError, EncryptVolume,
|
CreateVolume, CreateVolumeError, EnableOwnership, EnableOwnershipError, EncryptVolume,
|
||||||
EncryptVolumeError, UnmountVolume, UnmountVolumeError,
|
EncryptVolumeError, UnmountVolume, UnmountVolumeError,
|
||||||
},
|
},
|
||||||
CreateOrAppendFile, CreateOrAppendFileError,
|
CreateFile, CreateFileError, CreateOrAppendFile, CreateOrAppendFileError,
|
||||||
};
|
};
|
||||||
use crate::actions::{base::darwin, Action, ActionDescription, ActionState, Actionable};
|
use crate::actions::{base::darwin, Action, ActionDescription, ActionState, Actionable};
|
||||||
|
|
||||||
|
@ -25,6 +28,7 @@ pub struct CreateApfsVolume {
|
||||||
create_volume: CreateVolume,
|
create_volume: CreateVolume,
|
||||||
create_or_append_fstab: CreateOrAppendFile,
|
create_or_append_fstab: CreateOrAppendFile,
|
||||||
encrypt_volume: Option<EncryptVolume>,
|
encrypt_volume: Option<EncryptVolume>,
|
||||||
|
setup_volume_daemon: CreateFile,
|
||||||
bootstrap_volume: BootstrapVolume,
|
bootstrap_volume: BootstrapVolume,
|
||||||
enable_ownership: EnableOwnership,
|
enable_ownership: EnableOwnership,
|
||||||
action_state: ActionState,
|
action_state: ActionState,
|
||||||
|
@ -39,9 +43,14 @@ impl CreateApfsVolume {
|
||||||
encrypt: Option<String>,
|
encrypt: Option<String>,
|
||||||
) -> Result<Self, CreateApfsVolumeError> {
|
) -> Result<Self, CreateApfsVolumeError> {
|
||||||
let disk = disk.as_ref();
|
let disk = disk.as_ref();
|
||||||
let create_or_append_synthetic_conf =
|
let create_or_append_synthetic_conf = CreateOrAppendFile::plan(
|
||||||
CreateOrAppendFile::plan("/etc/synthetic.conf", None, None, 0o0655, "nix".into())
|
"/etc/synthetic.conf",
|
||||||
.await?;
|
None,
|
||||||
|
None,
|
||||||
|
0o0655,
|
||||||
|
"nix\n".into(), /* The newline is required otherwise it segfaults */
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let create_synthetic_objects = CreateSyntheticObjects::plan().await?;
|
let create_synthetic_objects = CreateSyntheticObjects::plan().await?;
|
||||||
|
|
||||||
|
@ -64,6 +73,49 @@ impl CreateApfsVolume {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mount_command = if encrypt.is_some() {
|
||||||
|
vec![
|
||||||
|
"/bin/sh",
|
||||||
|
"-c",
|
||||||
|
"/usr/bin/security find-generic-password",
|
||||||
|
"-s",
|
||||||
|
"{name}",
|
||||||
|
"-w",
|
||||||
|
"|",
|
||||||
|
"/usr/sbin/diskutil",
|
||||||
|
"apfs",
|
||||||
|
"unlockVolume",
|
||||||
|
&name,
|
||||||
|
"-mountpoint",
|
||||||
|
"/nix",
|
||||||
|
"-stdinpassphrase",
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
vec!["/usr/sbin/diskutil", "mount", "-mountPoint", "/nix", &name]
|
||||||
|
};
|
||||||
|
// TODO(@hoverbear): Use plist lib we have in tree...
|
||||||
|
let mount_plist = format!(
|
||||||
|
"\
|
||||||
|
<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
|
||||||
|
<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n\
|
||||||
|
<plist version=\"1.0\">\n\
|
||||||
|
<dict>\n\
|
||||||
|
<key>RunAtLoad</key>\n\
|
||||||
|
<true/>\n\
|
||||||
|
<key>Label</key>\n\
|
||||||
|
<string>org.nixos.darwin-store</string>\n\
|
||||||
|
<key>ProgramArguments</key>\n\
|
||||||
|
<array>\n\
|
||||||
|
{}\
|
||||||
|
</array>\n\
|
||||||
|
</dict>\n\
|
||||||
|
</plist>\n\
|
||||||
|
\
|
||||||
|
", mount_command.iter().map(|v| format!("<string>{v}</string>\n")).collect::<Vec<_>>().join("\n")
|
||||||
|
);
|
||||||
|
let setup_volume_daemon =
|
||||||
|
CreateFile::plan(NIX_VOLUME_MOUNTD_DEST, None, None, None, mount_plist, false).await?;
|
||||||
|
|
||||||
let bootstrap_volume = BootstrapVolume::plan(NIX_VOLUME_MOUNTD_DEST).await?;
|
let bootstrap_volume = BootstrapVolume::plan(NIX_VOLUME_MOUNTD_DEST).await?;
|
||||||
let enable_ownership = EnableOwnership::plan("/nix").await?;
|
let enable_ownership = EnableOwnership::plan("/nix").await?;
|
||||||
|
|
||||||
|
@ -78,6 +130,7 @@ impl CreateApfsVolume {
|
||||||
create_volume,
|
create_volume,
|
||||||
create_or_append_fstab,
|
create_or_append_fstab,
|
||||||
encrypt_volume,
|
encrypt_volume,
|
||||||
|
setup_volume_daemon,
|
||||||
bootstrap_volume,
|
bootstrap_volume,
|
||||||
enable_ownership,
|
enable_ownership,
|
||||||
action_state: ActionState::Uncompleted,
|
action_state: ActionState::Uncompleted,
|
||||||
|
@ -121,6 +174,7 @@ impl Actionable for CreateApfsVolume {
|
||||||
create_volume,
|
create_volume,
|
||||||
create_or_append_fstab,
|
create_or_append_fstab,
|
||||||
encrypt_volume,
|
encrypt_volume,
|
||||||
|
setup_volume_daemon,
|
||||||
bootstrap_volume,
|
bootstrap_volume,
|
||||||
enable_ownership,
|
enable_ownership,
|
||||||
action_state,
|
action_state,
|
||||||
|
@ -139,7 +193,13 @@ impl Actionable for CreateApfsVolume {
|
||||||
if let Some(encrypt_volume) = encrypt_volume {
|
if let Some(encrypt_volume) = encrypt_volume {
|
||||||
encrypt_volume.execute().await?;
|
encrypt_volume.execute().await?;
|
||||||
}
|
}
|
||||||
|
setup_volume_daemon.execute().await?;
|
||||||
|
|
||||||
bootstrap_volume.execute().await?;
|
bootstrap_volume.execute().await?;
|
||||||
|
|
||||||
|
// TODO: Check wait
|
||||||
|
tokio::time::sleep(Duration::from_millis(5000)).await;
|
||||||
|
|
||||||
enable_ownership.execute().await?;
|
enable_ownership.execute().await?;
|
||||||
|
|
||||||
tracing::trace!("Created APFS volume");
|
tracing::trace!("Created APFS volume");
|
||||||
|
@ -179,6 +239,7 @@ impl Actionable for CreateApfsVolume {
|
||||||
create_volume,
|
create_volume,
|
||||||
create_or_append_fstab,
|
create_or_append_fstab,
|
||||||
encrypt_volume,
|
encrypt_volume,
|
||||||
|
setup_volume_daemon,
|
||||||
bootstrap_volume,
|
bootstrap_volume,
|
||||||
enable_ownership,
|
enable_ownership,
|
||||||
action_state,
|
action_state,
|
||||||
|
@ -191,6 +252,7 @@ impl Actionable for CreateApfsVolume {
|
||||||
|
|
||||||
enable_ownership.revert().await?;
|
enable_ownership.revert().await?;
|
||||||
bootstrap_volume.revert().await?;
|
bootstrap_volume.revert().await?;
|
||||||
|
setup_volume_daemon.revert().await?;
|
||||||
if let Some(encrypt_volume) = encrypt_volume {
|
if let Some(encrypt_volume) = encrypt_volume {
|
||||||
encrypt_volume.revert().await?;
|
encrypt_volume.revert().await?;
|
||||||
}
|
}
|
||||||
|
@ -217,6 +279,8 @@ impl From<CreateApfsVolume> for Action {
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error, Serialize)]
|
#[derive(Debug, thiserror::Error, Serialize)]
|
||||||
pub enum CreateApfsVolumeError {
|
pub enum CreateApfsVolumeError {
|
||||||
|
#[error(transparent)]
|
||||||
|
CreateFile(#[from] CreateFileError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
DarwinBootstrapVolume(#[from] BootstrapVolumeError),
|
DarwinBootstrapVolume(#[from] BootstrapVolumeError),
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
|
|
@ -26,7 +26,7 @@ impl PlaceChannelConfiguration {
|
||||||
let create_file = CreateFile::plan(
|
let create_file = CreateFile::plan(
|
||||||
dirs::home_dir()
|
dirs::home_dir()
|
||||||
.ok_or(PlaceChannelConfigurationError::NoRootHome)?
|
.ok_or(PlaceChannelConfigurationError::NoRootHome)?
|
||||||
.join("/.nix-channels"),
|
.join(".nix-channels"),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
0o0664,
|
0o0664,
|
||||||
|
|
|
@ -15,7 +15,6 @@ use super::{CreateNixTree, CreateNixTreeError, CreateUsersAndGroup, CreateUsersA
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||||
pub struct ProvisionNix {
|
pub struct ProvisionNix {
|
||||||
create_nix_dir: CreateDirectory,
|
|
||||||
fetch_nix: FetchNix,
|
fetch_nix: FetchNix,
|
||||||
create_users_and_group: CreateUsersAndGroup,
|
create_users_and_group: CreateUsersAndGroup,
|
||||||
create_nix_tree: CreateNixTree,
|
create_nix_tree: CreateNixTree,
|
||||||
|
@ -26,8 +25,6 @@ pub struct ProvisionNix {
|
||||||
impl ProvisionNix {
|
impl ProvisionNix {
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
pub async fn plan(settings: InstallSettings) -> Result<Self, ProvisionNixError> {
|
pub async fn plan(settings: InstallSettings) -> Result<Self, ProvisionNixError> {
|
||||||
let create_nix_dir = CreateDirectory::plan("/nix", None, None, 0o0755, true).await?;
|
|
||||||
|
|
||||||
let fetch_nix = FetchNix::plan(
|
let fetch_nix = FetchNix::plan(
|
||||||
settings.nix_package_url.clone(),
|
settings.nix_package_url.clone(),
|
||||||
PathBuf::from("/nix/temp-install-dir"),
|
PathBuf::from("/nix/temp-install-dir"),
|
||||||
|
@ -38,7 +35,6 @@ impl ProvisionNix {
|
||||||
let move_unpacked_nix =
|
let move_unpacked_nix =
|
||||||
MoveUnpackedNix::plan(PathBuf::from("/nix/temp-install-dir")).await?;
|
MoveUnpackedNix::plan(PathBuf::from("/nix/temp-install-dir")).await?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
create_nix_dir,
|
|
||||||
fetch_nix,
|
fetch_nix,
|
||||||
create_users_and_group,
|
create_users_and_group,
|
||||||
create_nix_tree,
|
create_nix_tree,
|
||||||
|
@ -53,7 +49,6 @@ impl Actionable for ProvisionNix {
|
||||||
type Error = ProvisionNixError;
|
type Error = ProvisionNixError;
|
||||||
fn describe_execute(&self) -> Vec<ActionDescription> {
|
fn describe_execute(&self) -> Vec<ActionDescription> {
|
||||||
let Self {
|
let Self {
|
||||||
create_nix_dir,
|
|
||||||
fetch_nix,
|
fetch_nix,
|
||||||
create_users_and_group,
|
create_users_and_group,
|
||||||
create_nix_tree,
|
create_nix_tree,
|
||||||
|
@ -64,7 +59,6 @@ impl Actionable for ProvisionNix {
|
||||||
vec![]
|
vec![]
|
||||||
} else {
|
} else {
|
||||||
let mut buf = Vec::default();
|
let mut buf = Vec::default();
|
||||||
buf.append(&mut create_nix_dir.describe_execute());
|
|
||||||
buf.append(&mut fetch_nix.describe_execute());
|
buf.append(&mut fetch_nix.describe_execute());
|
||||||
buf.append(&mut create_users_and_group.describe_execute());
|
buf.append(&mut create_users_and_group.describe_execute());
|
||||||
buf.append(&mut create_nix_tree.describe_execute());
|
buf.append(&mut create_nix_tree.describe_execute());
|
||||||
|
@ -77,7 +71,6 @@ impl Actionable for ProvisionNix {
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
async fn execute(&mut self) -> Result<(), Self::Error> {
|
async fn execute(&mut self) -> Result<(), Self::Error> {
|
||||||
let Self {
|
let Self {
|
||||||
create_nix_dir,
|
|
||||||
fetch_nix,
|
fetch_nix,
|
||||||
create_nix_tree,
|
create_nix_tree,
|
||||||
create_users_and_group,
|
create_users_and_group,
|
||||||
|
@ -91,8 +84,6 @@ impl Actionable for ProvisionNix {
|
||||||
*action_state = ActionState::Progress;
|
*action_state = ActionState::Progress;
|
||||||
tracing::debug!("Provisioning Nix");
|
tracing::debug!("Provisioning Nix");
|
||||||
|
|
||||||
create_nix_dir.execute().await?;
|
|
||||||
|
|
||||||
// We fetch nix while doing the rest, then move it over.
|
// We fetch nix while doing the rest, then move it over.
|
||||||
let mut fetch_nix_clone = fetch_nix.clone();
|
let mut fetch_nix_clone = fetch_nix.clone();
|
||||||
let fetch_nix_handle = tokio::task::spawn(async {
|
let fetch_nix_handle = tokio::task::spawn(async {
|
||||||
|
@ -116,7 +107,6 @@ impl Actionable for ProvisionNix {
|
||||||
|
|
||||||
fn describe_revert(&self) -> Vec<ActionDescription> {
|
fn describe_revert(&self) -> Vec<ActionDescription> {
|
||||||
let Self {
|
let Self {
|
||||||
create_nix_dir,
|
|
||||||
fetch_nix,
|
fetch_nix,
|
||||||
create_users_and_group,
|
create_users_and_group,
|
||||||
create_nix_tree,
|
create_nix_tree,
|
||||||
|
@ -131,7 +121,6 @@ impl Actionable for ProvisionNix {
|
||||||
buf.append(&mut create_nix_tree.describe_revert());
|
buf.append(&mut create_nix_tree.describe_revert());
|
||||||
buf.append(&mut create_users_and_group.describe_revert());
|
buf.append(&mut create_users_and_group.describe_revert());
|
||||||
buf.append(&mut fetch_nix.describe_revert());
|
buf.append(&mut fetch_nix.describe_revert());
|
||||||
buf.append(&mut create_nix_dir.describe_revert());
|
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,7 +128,6 @@ impl Actionable for ProvisionNix {
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
async fn revert(&mut self) -> Result<(), Self::Error> {
|
async fn revert(&mut self) -> Result<(), Self::Error> {
|
||||||
let Self {
|
let Self {
|
||||||
create_nix_dir,
|
|
||||||
fetch_nix,
|
fetch_nix,
|
||||||
create_nix_tree,
|
create_nix_tree,
|
||||||
create_users_and_group,
|
create_users_and_group,
|
||||||
|
@ -172,8 +160,6 @@ impl Actionable for ProvisionNix {
|
||||||
*fetch_nix = fetch_nix_handle.await.map_err(ProvisionNixError::from)??;
|
*fetch_nix = fetch_nix_handle.await.map_err(ProvisionNixError::from)??;
|
||||||
move_unpacked_nix.revert().await?;
|
move_unpacked_nix.revert().await?;
|
||||||
|
|
||||||
create_nix_dir.revert().await?;
|
|
||||||
|
|
||||||
tracing::trace!("Unprovisioned Nix");
|
tracing::trace!("Unprovisioned Nix");
|
||||||
*action_state = ActionState::Uncompleted;
|
*action_state = ActionState::Uncompleted;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -28,7 +28,10 @@ async fn execute_command(command: &mut Command) -> Result<Output, std::io::Error
|
||||||
true => Ok(output),
|
true => Ok(output),
|
||||||
false => Err(std::io::Error::new(
|
false => Err(std::io::Error::new(
|
||||||
std::io::ErrorKind::Other,
|
std::io::ErrorKind::Other,
|
||||||
format!("Command `{command_str}` failed status"),
|
format!(
|
||||||
|
"Command `{command_str}` failed status, stderr:\n{}\n",
|
||||||
|
String::from_utf8(output.stderr).unwrap_or_else(|_e| String::from("<Non-UTF-8>"))
|
||||||
|
),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
actions::{
|
actions::{
|
||||||
base::StartSystemdUnit,
|
base::{CreateDirectory, StartSystemdUnit},
|
||||||
meta::{ConfigureNix, ProvisionNix},
|
meta::{ConfigureNix, ProvisionNix},
|
||||||
Action, ActionError,
|
Action, ActionError,
|
||||||
},
|
},
|
||||||
|
@ -21,6 +21,10 @@ impl Plannable for LinuxMultiUser {
|
||||||
planner: Self.into(),
|
planner: Self.into(),
|
||||||
settings: settings.clone(),
|
settings: settings.clone(),
|
||||||
actions: vec![
|
actions: vec![
|
||||||
|
CreateDirectory::plan("/nix", None, None, 0o0755, true)
|
||||||
|
.await
|
||||||
|
.map(Action::from)
|
||||||
|
.map_err(ActionError::from)?,
|
||||||
ProvisionNix::plan(settings.clone())
|
ProvisionNix::plan(settings.clone())
|
||||||
.await
|
.await
|
||||||
.map(Action::from)
|
.map(Action::from)
|
||||||
|
|
|
@ -20,8 +20,10 @@ impl Planner {
|
||||||
match (Architecture::host(), OperatingSystem::host()) {
|
match (Architecture::host(), OperatingSystem::host()) {
|
||||||
(Architecture::X86_64, OperatingSystem::Linux) => Ok(Self::LinuxMultiUser),
|
(Architecture::X86_64, OperatingSystem::Linux) => Ok(Self::LinuxMultiUser),
|
||||||
(Architecture::Aarch64(_), OperatingSystem::Linux) => Ok(Self::LinuxMultiUser),
|
(Architecture::Aarch64(_), OperatingSystem::Linux) => Ok(Self::LinuxMultiUser),
|
||||||
(Architecture::X86_64, OperatingSystem::MacOSX { .. }) => Ok(Self::DarwinMultiUser),
|
(Architecture::X86_64, OperatingSystem::MacOSX { .. })
|
||||||
(Architecture::Aarch64(_), OperatingSystem::MacOSX { .. }) => Ok(Self::DarwinMultiUser),
|
| (Architecture::X86_64, OperatingSystem::Darwin) => Ok(Self::DarwinMultiUser),
|
||||||
|
(Architecture::Aarch64(_), OperatingSystem::MacOSX { .. })
|
||||||
|
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => Ok(Self::DarwinMultiUser),
|
||||||
_ => Err(PlannerError::UnsupportedArchitecture(target_lexicon::HOST)),
|
_ => Err(PlannerError::UnsupportedArchitecture(target_lexicon::HOST)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
actions::{
|
actions::{
|
||||||
base::StartSystemdUnit,
|
base::{CreateDirectory, StartSystemdUnit},
|
||||||
meta::{CreateSystemdSysext, ProvisionNix},
|
meta::{CreateSystemdSysext, ProvisionNix},
|
||||||
Action, ActionError,
|
Action, ActionError,
|
||||||
},
|
},
|
||||||
|
@ -27,6 +27,10 @@ impl Plannable for SteamDeck {
|
||||||
.await
|
.await
|
||||||
.map(Action::from)
|
.map(Action::from)
|
||||||
.map_err(ActionError::from)?,
|
.map_err(ActionError::from)?,
|
||||||
|
CreateDirectory::plan("/nix", None, None, 0o0755, true)
|
||||||
|
.await
|
||||||
|
.map(Action::from)
|
||||||
|
.map_err(ActionError::from)?,
|
||||||
ProvisionNix::plan(settings.clone())
|
ProvisionNix::plan(settings.clone())
|
||||||
.await
|
.await
|
||||||
.map(Action::from)
|
.map(Action::from)
|
||||||
|
|
|
@ -22,22 +22,32 @@ pub struct InstallSettings {
|
||||||
impl InstallSettings {
|
impl InstallSettings {
|
||||||
pub fn default() -> Result<Self, InstallSettingsError> {
|
pub fn default() -> Result<Self, InstallSettingsError> {
|
||||||
let url;
|
let url;
|
||||||
|
let nix_build_user_prefix;
|
||||||
|
let nix_build_user_id_base;
|
||||||
|
|
||||||
use target_lexicon::{Architecture, OperatingSystem};
|
use target_lexicon::{Architecture, OperatingSystem};
|
||||||
match (Architecture::host(), OperatingSystem::host()) {
|
match (Architecture::host(), OperatingSystem::host()) {
|
||||||
(Architecture::X86_64, OperatingSystem::Linux) => {
|
(Architecture::X86_64, OperatingSystem::Linux) => {
|
||||||
url = "https://releases.nixos.org/nix/nix-2.11.0/nix-2.11.0-x86_64-linux.tar.xz";
|
url = "https://releases.nixos.org/nix/nix-2.11.0/nix-2.11.0-x86_64-linux.tar.xz";
|
||||||
|
nix_build_user_prefix = "nixbld";
|
||||||
|
nix_build_user_id_base = 3000;
|
||||||
},
|
},
|
||||||
(Architecture::Aarch64(_), OperatingSystem::Linux) => {
|
(Architecture::Aarch64(_), OperatingSystem::Linux) => {
|
||||||
url = "https://releases.nixos.org/nix/nix-2.11.0/nix-2.11.0-aarch64-linux.tar.xz";
|
url = "https://releases.nixos.org/nix/nix-2.11.0/nix-2.11.0-aarch64-linux.tar.xz";
|
||||||
|
nix_build_user_prefix = "nixbld";
|
||||||
|
nix_build_user_id_base = 3000;
|
||||||
},
|
},
|
||||||
(Architecture::X86_64, OperatingSystem::MacOSX { .. })
|
(Architecture::X86_64, OperatingSystem::MacOSX { .. })
|
||||||
| (Architecture::X86_64, OperatingSystem::Darwin) => {
|
| (Architecture::X86_64, OperatingSystem::Darwin) => {
|
||||||
url = "https://releases.nixos.org/nix/nix-2.11.0/nix-2.11.0-x86_64-darwin.tar.xz";
|
url = "https://releases.nixos.org/nix/nix-2.11.0/nix-2.11.0-x86_64-darwin.tar.xz";
|
||||||
|
nix_build_user_prefix = "_nixbld";
|
||||||
|
nix_build_user_id_base = 300;
|
||||||
},
|
},
|
||||||
(Architecture::Aarch64(_), OperatingSystem::MacOSX { .. })
|
(Architecture::Aarch64(_), OperatingSystem::MacOSX { .. })
|
||||||
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => {
|
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => {
|
||||||
url = "https://releases.nixos.org/nix/nix-2.11.0/nix-2.11.0-aarch64-darwin.tar.xz";
|
url = "https://releases.nixos.org/nix/nix-2.11.0/nix-2.11.0-aarch64-darwin.tar.xz";
|
||||||
|
nix_build_user_prefix = "_nixbld";
|
||||||
|
nix_build_user_id_base = 300;
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(InstallSettingsError::UnsupportedArchitecture(
|
return Err(InstallSettingsError::UnsupportedArchitecture(
|
||||||
|
@ -53,8 +63,8 @@ impl InstallSettings {
|
||||||
modify_profile: Default::default(),
|
modify_profile: Default::default(),
|
||||||
nix_build_group_name: String::from("nixbld"),
|
nix_build_group_name: String::from("nixbld"),
|
||||||
nix_build_group_id: 3000,
|
nix_build_group_id: 3000,
|
||||||
nix_build_user_prefix: String::from("nixbld"),
|
nix_build_user_prefix: nix_build_user_prefix.to_string(),
|
||||||
nix_build_user_id_base: 3001,
|
nix_build_user_id_base,
|
||||||
nix_package_url: url
|
nix_package_url: url
|
||||||
.parse()
|
.parse()
|
||||||
.expect("Could not parse default Nix archive url, please report this issue"),
|
.expect("Could not parse default Nix archive url, please report this issue"),
|
||||||
|
|
Loading…
Reference in a new issue