Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default to systemd, refer to documentation if systemd is not available #336

Merged
merged 1 commit into from
Mar 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,21 @@ jobs:
run: nix build .
```

## Without systemd (Linux only)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this shouldn't be the second "use case", but somewhat lower?

But also I want this to be visible before the other below use cases that specify --init none... Could just add a link back in place of their "> When --init none is..." notices.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your preference here. I think this is a fine location but am not picky!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Myeah, I think this is fine for now. We can always add more docs / more backlinking!


> **Warning**
> When installed this way, _only_ `root` or users who can elevate to `root` privileges can run Nix:
>
> ```bash
> sudo -i nix run nixpkgs#hello
> ```

If you don't use [systemd], you can still install Nix by explicitly specifying the `linux` plan and `--init none`:

```bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux --init none
```

## In a container

In Docker/Podman containers or WSL2 instances where an init (like `systemd`) is not present, pass `--init none`.
Expand Down
7 changes: 7 additions & 0 deletions src/action/common/configure_init_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ impl ConfigureInitService {
},
#[cfg(target_os = "linux")]
InitSystem::Systemd => {
// If /run/systemd/system exists, we can be reasonably sure the machine is booted
// with systemd: https://www.freedesktop.org/software/systemd/man/sd_booted.html
if !(Path::new("/run/systemd/system").exists() || which::which("systemctl").is_ok())
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to #392. On WSL without systemd running, the systemctl command does exist (Ubuntu 22.04.1 from the windows store). So this check would not error, even though systemd needs to be configured in /etc/wsl.conf. It would also be good to point users to the microsoft docs where they document on how to configure this, or maybe even configure the file for people so they only have to reboot.

Note that /run/systemd/system does not exist, so if the check only looked for that it would error succesfully

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tracking this down!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be a case of a simple logic error, as in, the following would work:

-if !(Path::new("/run/systemd/system").exists() || which::which("systemctl").is_ok())
---
+if (!Path::new("/run/systemd/system").exists() || !which::which("systemctl").is_ok())

Although I'm not sure what the original intention was

{
return Err(ActionError::SystemdMissing);
}

Self::check_if_systemd_unit_exists(SERVICE_SRC, SERVICE_DEST).await?;
Self::check_if_systemd_unit_exists(SOCKET_SRC, SOCKET_DEST).await?;
},
Expand Down
5 changes: 5 additions & 0 deletions src/action/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,11 @@ pub enum ActionError {
MissingGroupDeletionCommand,
#[error("Could not find a supported command to remove users from groups in PATH; please install `gpasswd` or `deluser`")]
MissingRemoveUserFromGroupCommand,
#[error("\
Could not detect systemd; you may be able to get up and running without systemd with `nix-installer install linux --init none`.\n\
See https://github.com/DeterminateSystems/nix-installer#without-systemd-linux-only for documentation on usage and drawbacks.\
")]
SystemdMissing,
}

impl ActionError {
Expand Down
25 changes: 8 additions & 17 deletions src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,13 +340,11 @@ impl CommonSettings {
}
}
#[cfg(target_os = "linux")]
async fn linux_detect_init() -> (InitSystem, bool) {
async fn linux_detect_systemd_started() -> bool {
use std::process::Stdio;

let mut detected = InitSystem::None;
let mut started = false;
if std::path::Path::new("/run/systemd/system").exists() {
detected = InitSystem::Systemd;
started = if tokio::process::Command::new("systemctl")
.arg("status")
.stdin(Stdio::null())
Expand All @@ -365,7 +363,7 @@ async fn linux_detect_init() -> (InitSystem, bool) {
}

// TODO: Other inits
(detected, started)
started
}

// Builder Pattern
Expand Down Expand Up @@ -465,33 +463,26 @@ pub struct InitSettings {
impl InitSettings {
/// The default settings for the given Architecture & Operating System
pub async fn default() -> Result<Self, InstallSettingsError> {
let init;
let start_daemon;

use target_lexicon::{Architecture, OperatingSystem};
match (Architecture::host(), OperatingSystem::host()) {
let (init, start_daemon) = match (Architecture::host(), OperatingSystem::host()) {
#[cfg(target_os = "linux")]
(Architecture::X86_64, OperatingSystem::Linux) => {
(init, start_daemon) = linux_detect_init().await;
(InitSystem::Systemd, linux_detect_systemd_started().await)
},
#[cfg(target_os = "linux")]
(Architecture::X86_32(_), OperatingSystem::Linux) => {
(init, start_daemon) = linux_detect_init().await;
(InitSystem::Systemd, linux_detect_systemd_started().await)
},
#[cfg(target_os = "linux")]
(Architecture::Aarch64(_), OperatingSystem::Linux) => {
(init, start_daemon) = linux_detect_init().await;
(InitSystem::Systemd, linux_detect_systemd_started().await)
},
#[cfg(target_os = "macos")]
(Architecture::X86_64, OperatingSystem::MacOSX { .. })
| (Architecture::X86_64, OperatingSystem::Darwin) => {
(init, start_daemon) = (InitSystem::Launchd, true);
},
| (Architecture::X86_64, OperatingSystem::Darwin) => (InitSystem::Launchd, true),
#[cfg(target_os = "macos")]
(Architecture::Aarch64(_), OperatingSystem::MacOSX { .. })
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => {
(init, start_daemon) = (InitSystem::Launchd, true);
},
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => (InitSystem::Launchd, true),
_ => {
return Err(InstallSettingsError::UnsupportedArchitecture(
target_lexicon::HOST,
Expand Down