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

[nix] Add DetSys installer behind feature flag #2303

Merged
merged 6 commits into from
Sep 25, 2024
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
2 changes: 2 additions & 0 deletions .github/workflows/cli-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-13]
use-detsys: [true, false]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
Expand All @@ -197,6 +198,7 @@ jobs:
- name: Install nix and devbox packages
run: |
export NIX_INSTALLER_NO_CHANNEL_ADD=1
export DEVBOX_FEATURE_DETSYS_INSTALLER=${{ matrix.use-detsys }}

# Setup github authentication to ensure Github's rate limits are not hit.
# If this works, we can consider refactoring this into a reusable github action helper.
Expand Down
3 changes: 3 additions & 0 deletions internal/boxcli/featureflag/detsys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package featureflag

var UseDetSysInstaller = disable("DETSYS_INSTALLER")
10 changes: 8 additions & 2 deletions internal/boxcli/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,27 @@ func setupCmd() *cobra.Command {
},
}

installNixCommand.Flags().Bool(nixDaemonFlag, false, "Install Nix in multi-user mode.")
installNixCommand.Flags().Bool(
nixDaemonFlag,
false,
"Install Nix in multi-user mode. This flag is not supported if you are using DetSys installer",
)
setupCommand.AddCommand(installNixCommand)
return setupCommand
}

func runInstallNixCmd(cmd *cobra.Command) error {
if nix.BinaryInstalled() {
// TODO: If existing installation is not detsys, but new installation is detsys can we detect
// that and replace it?
ux.Finfof(
cmd.ErrOrStderr(),
"Nix is already installed. If this is incorrect "+
"please remove the nix-shell binary from your path.\n",
)
return nil
}
return nix.Install(cmd.ErrOrStderr(), nixDaemonFlagVal(cmd)())
return nix.Install(cmd.ErrOrStderr(), nixDaemonFlagVal(cmd))
}

// ensureNixInstalled verifies that nix is installed and that it is of a supported version
Expand Down
29 changes: 26 additions & 3 deletions internal/nix/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/mattn/go-isatty"
"github.com/pkg/errors"

"go.jetpack.io/devbox/internal/boxcli/featureflag"
"go.jetpack.io/devbox/internal/boxcli/usererr"
"go.jetpack.io/devbox/internal/build"
"go.jetpack.io/devbox/internal/cmdutil"
Expand All @@ -28,7 +29,7 @@ const rootError = "warning: installing Nix as root is not supported by this scri

// Install runs the install script for Nix. daemon has 3 states
// nil is unset. false is --no-daemon. true is --daemon.
func Install(writer io.Writer, daemon *bool) error {
func Install(writer io.Writer, daemonFn func() *bool) error {
if isRoot() && build.OS() == build.OSWSL {
return usererr.New("Nix cannot be installed as root on WSL. Please run as a normal user with sudo access.")
}
Expand All @@ -39,7 +40,18 @@ func Install(writer io.Writer, daemon *bool) error {
defer r.Close()

installScript := "curl -L https://releases.nixos.org/nix/nix-2.24.7/install | sh -s"
if daemon != nil {
if featureflag.UseDetSysInstaller.Enabled() {
// Should we pin version? Or just trust detsys
installScript = "curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install"
if isLinuxWithoutSystemd() {
ux.Fwarningf(
writer,
"Could not detect systemd on your system. Installing Nix in root only mode (--init none).\n",
)
installScript += " linux --init none"
Copy link
Collaborator

Choose a reason for hiding this comment

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

I presume this is to manage the nix daemon.
How does the nix daemon get started without this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My understanding from the DetSys docs is that this makes it root only but will still work.

There are a few alternatives to this:

  • Warn and give user options (e.g. install systemd or use new --root-only)
  • Warn and install anyway

Copy link
Collaborator

Choose a reason for hiding this comment

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

Seems like they'll then need to run sudo to run devbox. I think emitting a warning (with a suggestion to install systemd and re-using the detsys installer manually) and continuing to install seems okay to minimize friction. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not quite, user needs sudo only if not root, so at least some cases (e.g. ubuntu dockerfile) work pretty well as is.

That said, printing a message is very low friction. I'm not 100% sure re-running detsys installation would fix it, I need to experiment a bit more.

}
installScript += " --no-confirm"
} else if daemon := daemonFn(); daemon != nil {
if *daemon {
installScript += " -- --daemon"
} else {
Expand Down Expand Up @@ -157,7 +169,7 @@ func EnsureNixInstalled(writer io.Writer, withDaemonFunc func() *bool) (err erro
fmt.Scanln() //nolint:errcheck
}

if err = Install(writer, withDaemonFunc()); err != nil {
if err = Install(writer, withDaemonFunc); err != nil {
return err
}

Expand All @@ -169,3 +181,14 @@ func EnsureNixInstalled(writer io.Writer, withDaemonFunc func() *bool) (err erro
fmt.Fprintln(writer, "Nix installed successfully. Devbox is ready to use!")
return nil
}

func isLinuxWithoutSystemd() bool {
if build.OS() != build.OSLinux {
return false
}
// My best interpretation of https://github.com/DeterminateSystems/nix-installer/blob/66ad2759a3ecb6da345373e3c413c25303305e25/src/action/common/configure_init_service.rs#L108-L118
if _, err := os.Stat("/run/systemd/system"); errors.Is(err, os.ErrNotExist) {
return true
}
return !cmdutil.Exists("systemctl")
}
Loading