upload a baseline that's been de-detsys'd

This commit is contained in:
ktemkin 2024-04-02 15:40:06 -06:00
parent 41dc9fecde
commit 220e252230
41 changed files with 180 additions and 1693 deletions

View file

@ -1,51 +0,0 @@
steps:
- label: nix-installer-x86_64-darwin
agents:
mac: 1
system: x86_64-darwin
nix: 1
command:
- nix --extra-experimental-features "nix-command flakes" build .#packages.x86_64-darwin.nix-installer -L
- cp result/bin/nix-installer ./nix-installer-x86_64-darwin
- buildkite-agent artifact upload nix-installer-x86_64-darwin
- label: nix-installer-aarch64-darwin
agents:
mac: 1
system: aarch64-darwin
nix: 1
command:
- nix --extra-experimental-features "nix-command flakes" build .#packages.aarch64-darwin.nix-installer -L
- cp result/bin/nix-installer ./nix-installer-aarch64-darwin
- buildkite-agent artifact upload nix-installer-aarch64-darwin
- label: nix-installer-x86_64-linux
agents:
system: x86_64-linux
nix: 1
command:
- nix --extra-experimental-features "nix-command flakes" build .#packages.x86_64-linux.nix-installer-static -L
- cp result/bin/nix-installer ./nix-installer-x86_64-linux
- buildkite-agent artifact upload nix-installer-x86_64-linux
- label: nix-installer-x86_64-linux-variants
agents:
system: x86_64-linux
nix: 1
command:
- nix --extra-experimental-features "nix-command flakes" develop --store ~/.ci-store --print-build-logs .# --command "cargo" build --no-default-features
- nix --extra-experimental-features "nix-command flakes" develop --store ~/.ci-store --print-build-logs .# --command "cargo" build --all-features
- nix --extra-experimental-features "nix-command flakes" build --store ~/.ci-store --print-build-logs .#packages.x86_64-linux.nix-installer
- label: nix-installer-i686-linux
agents:
system: x86_64-linux
nix: 1
command:
- nix --extra-experimental-features "nix-command flakes" build .#packages.i686-linux.nix-installer-static -L
- cp result/bin/nix-installer ./nix-installer-i686-linux
- buildkite-agent artifact upload nix-installer-i686-linux
- label: nix-installer-aarch64-linux
agents:
system: aarch64-linux
nix: 1
command:
- nix --extra-experimental-features "nix-command flakes" build .#packages.aarch64-linux.nix-installer-static -L
- cp result/bin/nix-installer ./nix-installer-aarch64-linux
- buildkite-agent artifact upload nix-installer-aarch64-linux

View file

@ -1,22 +0,0 @@
##### Description
<!---
Please include a short description of what your PR does and / or the motivation behind it
--->
##### Checklist
- [ ] Formatted with `cargo fmt`
- [ ] Built with `nix build`
- [ ] Ran flake checks with `nix flake check`
- [ ] Added or updated relevant tests (leave unchecked if not applicable)
- [ ] Added or updated relevant documentation (leave unchecked if not applicable)
- [ ] Linked to related issues (leave unchecked if not applicable)
##### Validating with `install.determinate.systems`
If a maintainer has added the `upload to s3` label to this PR, it will become available for installation via `install.determinate.systems`:
```shell
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix/pr/$PR_NUMBER | sh -s -- install
```

View file

@ -1,10 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "monthly"

View file

@ -1,340 +0,0 @@
name: CI
on:
pull_request:
push:
branches: [main]
jobs:
lints:
name: Lints
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Check Nixpkgs input
uses: DeterminateSystems/flake-checker-action@main
with:
fail-mode: true
check-outdated: false # PRs shouldn't fail because main's nixpkgs is out of date
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main
- name: Check rustfmt
run: nix develop --command check-rustfmt
- name: Check Clippy
run: nix develop --command check-clippy
- name: Check Spelling
run: nix develop --command check-spelling
- name: Check nixpkgs-fmt formatting
run: nix develop --command check-nixpkgs-fmt
- name: Check EditorConfig conformance
run: nix develop --command check-editorconfig
- name: Download Buildkite Artifacts
uses: EnricoMi/download-buildkite-artifact-action@v1.14
with:
buildkite_token: ${{ secrets.BUILDKITE_TOKEN }}
output_path: artifacts
- name: Output list of Buildkite artifacts
run: |
ls -lah artifacts/
ls -lah artifacts/**/*
# Mac's can't run this action, so we're forced to do this.
- name: Create Github cache from Buildkite artifacts
id: cache-buildkite-artifacts
uses: actions/cache/save@v3
with:
path: artifacts
key: buildkite-artifacts-${{ github.sha }}
run-x86_64-linux:
name: Run x86_64 Linux
runs-on: ubuntu-22.04
needs: [lints]
steps:
- uses: actions/checkout@v3
- name: Restore Github cache of Buildkite artifacts
id: cache-buildkite-artifacts
uses: actions/cache/restore@v3
with:
path: artifacts
key: buildkite-artifacts-${{ github.sha }}
- run: sudo apt install fish zsh
- name: Move & set executable
run: |
mkdir install-root
cp nix-installer.sh install-root/nix-installer.sh
mv ./artifacts/nix-installer-x86_64-linux-*/* install-root/nix-installer-x86_64-linux
chmod +x install-root/nix-installer-x86_64-linux install-root/nix-installer.sh
- name: Initial install
uses: DeterminateSystems/nix-installer-action@main
with:
local-root: install-root/
logger: pretty
log-directives: nix_installer=debug
backtrace: full
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Initial uninstall (without a `nix run` first)
run: sudo -E /nix/nix-installer uninstall
env:
NIX_INSTALLER_NO_CONFIRM: true
NIX_INSTALLER_LOGGER: pretty
NIX_INSTALLER_LOG_DIRECTIVES: nix_installer=debug
RUST_BACKTRACE: full
- name: Ensure `nix` is removed
run: |
if systemctl is-active nix-daemon.socket; then
echo "nix-daemon.socket was still running"
exit 1
fi
if systemctl is-active nix-daemon.service; then
echo "nix-daemon.service was still running"
exit 1
fi
if [ -e /nix ]; then
echo "/nix exists"
exit 1
fi
- name: Repeated install
uses: DeterminateSystems/nix-installer-action@main
with:
local-root: install-root/
logger: pretty
log-directives: nix_installer=debug
backtrace: full
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: echo $PATH
run: echo $PATH
- name: Test `nix` with `$GITHUB_PATH`
if: success() || failure()
run: |
nix run nixpkgs#hello
nix profile install nixpkgs#hello
hello
nix store gc
nix run nixpkgs#hello
- name: Test bash
run: nix-instantiate -E 'builtins.currentTime' --eval
if: success() || failure()
shell: bash --login {0}
- name: Test sh
run: nix-instantiate -E 'builtins.currentTime' --eval
if: success() || failure()
shell: sh -l {0}
- name: Test zsh
run: nix-instantiate -E 'builtins.currentTime' --eval
if: success() || failure()
shell: zsh --login --interactive {0}
- name: Test fish
run: nix-instantiate -E 'builtins.currentTime' --eval
if: success() || failure()
shell: fish --login {0}
- name: Repeated uninstall
run: sudo -E /nix/nix-installer uninstall
env:
NIX_INSTALLER_NO_CONFIRM: true
NIX_INSTALLER_LOGGER: pretty
NIX_INSTALLER_LOG_DIRECTIVES: nix_installer=debug
RUST_BACKTRACE: full
- name: Ensure `nix` is removed
run: |
if systemctl is-active nix-daemon.socket; then
echo "nix-daemon.socket was still running"
exit 1
fi
if systemctl is-active nix-daemon.service; then
echo "nix-daemon.service was still running"
exit 1
fi
if [ -e /nix ]; then
echo "/nix exists"
exit 1
fi
run-x86_64-linux-no-init:
name: Run x86_64 Linux (No init)
runs-on: ubuntu-22.04
needs: [lints]
steps:
- uses: actions/checkout@v3
- name: Restore Github cache of Buildkite artifacts
id: cache-buildkite-artifacts
uses: actions/cache/restore@v3
with:
path: artifacts
key: buildkite-artifacts-${{ github.sha }}
- run: sudo apt install fish zsh
- name: Move & set executable
run: |
mkdir install-root
cp nix-installer.sh install-root/nix-installer.sh
mv ./artifacts/nix-installer-x86_64-linux-*/* install-root/nix-installer-x86_64-linux
chmod +x install-root/nix-installer-x86_64-linux install-root/nix-installer.sh
- name: Initial install
uses: DeterminateSystems/nix-installer-action@main
with:
init: none
planner: linux
local-root: install-root/
logger: pretty
log-directives: nix_installer=debug
backtrace: full
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Ensure daemon was not configured with init
run: |
if systemctl is-active nix-daemon.socket; then
echo "nix-daemon.socket was running"
exit 1
fi
if systemctl is-active nix-daemon.service; then
echo "nix-daemon.service was running"
exit 1
fi
- name: Initial uninstall (without a `nix run` first)
run: sudo -E /nix/nix-installer uninstall
env:
NIX_INSTALLER_NO_CONFIRM: true
NIX_INSTALLER_LOGGER: pretty
NIX_INSTALLER_LOG_DIRECTIVES: nix_installer=debug
RUST_BACKTRACE: full
- name: Ensure `nix` is removed
run: |
if [ -e /nix ]; then
echo "/nix exists"
exit 1
fi
- name: Repeated install
uses: DeterminateSystems/nix-installer-action@main
with:
init: none
planner: linux
local-root: install-root/
logger: pretty
log-directives: nix_installer=debug
backtrace: full
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: echo $PATH
run: echo $PATH
- name: Test `nix` with `$GITHUB_PATH`
if: success() || failure()
run: |
sudo -i nix run nixpkgs#hello
sudo -i nix profile install nixpkgs#hello
hello
sudo -i nix store gc
sudo -i nix run nixpkgs#hello
- name: Test bash
run: sudo -i nix-instantiate -E 'builtins.currentTime' --eval
if: success() || failure()
shell: bash --login {0}
- name: Test sh
run: sudo -i nix-instantiate -E 'builtins.currentTime' --eval
if: success() || failure()
shell: sh -l {0}
- name: Test zsh
run: sudo -i nix-instantiate -E 'builtins.currentTime' --eval
if: success() || failure()
shell: zsh --login --interactive {0}
- name: Test fish
run: sudo -i nix-instantiate -E 'builtins.currentTime' --eval
if: success() || failure()
shell: fish --login {0}
- name: Repeated uninstall
run: sudo -E /nix/nix-installer uninstall
env:
NIX_INSTALLER_NO_CONFIRM: true
NIX_INSTALLER_LOGGER: pretty
NIX_INSTALLER_LOG_DIRECTIVES: nix_installer=debug
RUST_BACKTRACE: full
- name: Ensure `nix` is removed
run: |
if systemctl is-active nix-daemon.socket; then
echo "nix-daemon.socket was running"
exit 1
fi
if systemctl is-active nix-daemon.service; then
echo "nix-daemon.service was running"
exit 1
fi
if [ -e /nix ]; then
echo "/nix exists"
exit 1
fi
run-x86_64-darwin:
name: Run x86_64 Darwin
runs-on: macos-12
needs: [lints]
steps:
- uses: actions/checkout@v3
- name: Restore Github cache of Buildkite artifacts
id: cache-buildkite-artifacts
uses: actions/cache/restore@v3
with:
path: artifacts
key: buildkite-artifacts-${{ github.sha }}
- run: brew install fish coreutils
- name: Move & set executable
run: |
mkdir install-root
cp nix-installer.sh install-root/nix-installer.sh
mv ./artifacts/nix-installer-x86_64-darwin-*/* install-root/nix-installer-x86_64-darwin
chmod +x install-root/nix-installer-x86_64-darwin install-root/nix-installer.sh
- name: Initial install
uses: DeterminateSystems/nix-installer-action@main
with:
local-root: install-root/
logger: pretty
log-directives: nix_installer=debug
backtrace: full
github-token: ${{ secrets.GITHUB_TOKEN }}
extra-conf: |
trusted-users = root runner
- name: Initial uninstall (without a `nix run` first)
run: sudo -E /nix/nix-installer uninstall
env:
NIX_INSTALLER_NO_CONFIRM: true
NIX_INSTALLER_LOGGER: pretty
NIX_INSTALLER_LOG_DIRECTIVES: nix_installer=debug
RUST_BACKTRACE: full
- name: Repeated install
uses: DeterminateSystems/nix-installer-action@main
with:
local-root: install-root/
logger: pretty
log-directives: nix_installer=debug
backtrace: full
github-token: ${{ secrets.GITHUB_TOKEN }}
extra-conf: trusted-users = root runner
- name: echo $PATH
run: echo $PATH
- name: Test `nix` with `$GITHUB_PATH`
if: success() || failure()
run: |
nix run nixpkgs#hello
nix profile install nixpkgs#hello
hello
nix store gc
nix run nixpkgs#hello
- name: Test bash
run: nix-instantiate -E 'builtins.currentTime' --eval
if: success() || failure()
shell: bash --login {0}
- name: Test sh
run: nix-instantiate -E 'builtins.currentTime' --eval
if: success() || failure()
shell: sh -l {0}
- name: Test zsh
run: nix-instantiate -E 'builtins.currentTime' --eval
if: success() || failure()
shell: zsh --login --interactive {0}
- name: Test fish
run: nix-instantiate -E 'builtins.currentTime' --eval
if: success() || failure()
shell: fish --login {0}
- name: Repeated uninstall
run: sudo -E /nix/nix-installer uninstall
env:
NIX_INSTALLER_NO_CONFIRM: true
NIX_INSTALLER_LOGGER: pretty
NIX_INSTALLER_LOG_DIRECTIVES: nix_installer=debug
RUST_BACKTRACE: full

View file

@ -1,46 +0,0 @@
name: Release Branch
on:
push:
branches:
# NOTE: make sure any branches here are also valid directory names,
# otherwise creating the directory and uploading to s3 will fail
- 'main'
jobs:
release:
concurrency: release
runs-on: ubuntu-latest
permissions:
id-token: write # In order to request a JWT for AWS auth
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Download Buildkite Artifacts
uses: EnricoMi/download-buildkite-artifact-action@v1.14
with:
buildkite_token: ${{ secrets.BUILDKITE_TOKEN }}
output_path: artifacts
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ secrets.AWS_S3_UPLOAD_ROLE }}
aws-region: us-east-2
- name: Publish Release (Branch)
env:
AWS_BUCKET: ${{ secrets.AWS_S3_UPLOAD_BUCKET }}
run: |
BRANCH="branch_${{ github.ref_name }}"
GIT_ISH="$GITHUB_SHA"
./upload_s3.sh "$BRANCH" "$GIT_ISH" "https://install.determinate.systems/nix/rev/$GIT_ISH"
- name: Install Instructions (Branch)
run: |
cat <<EOF
This commit can be installed by running the following command:
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix/rev/$GITHUB_SHA | sh -s -- install
The latest commit from this branch can be installed by running the following command:
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix/branch/${{ github.ref_name }} | sh -s -- install
EOF

View file

@ -1,55 +0,0 @@
name: Release PR
on:
pull_request:
types:
- opened
- reopened
- synchronize
- labeled
jobs:
release:
concurrency: release
# Only intra-repo PRs are allowed to have PR artifacts uploaded
# We only want to trigger once the upload once in the case the upload label is added, not when any label is added
if: |
github.event.pull_request.head.repo.full_name == 'DeterminateSystems/nix-installer'
&& (
(github.event.action == 'labeled' && github.event.label.name == 'upload to s3')
|| (github.event.action != 'labeled' && contains(github.event.pull_request.labels.*.name, 'upload to s3'))
)
runs-on: ubuntu-latest
permissions:
id-token: write # In order to request a JWT for AWS auth
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Download Buildkite Artifacts
uses: EnricoMi/download-buildkite-artifact-action@v1.14
with:
buildkite_token: ${{ secrets.BUILDKITE_TOKEN }}
output_path: artifacts
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ secrets.AWS_S3_UPLOAD_ROLE }}
aws-region: us-east-2
- name: Publish Release (PR)
env:
AWS_BUCKET: ${{ secrets.AWS_S3_UPLOAD_BUCKET }}
run: |
PR="pr_${{ github.event.pull_request.number }}"
GIT_ISH="${{ github.event.pull_request.head.sha }}"
./upload_s3.sh "$PR" "$GIT_ISH" "https://install.determinate.systems/nix/rev/$GIT_ISH"
- name: Install Instructions (PR)
run: |
cat <<EOF
This commit can be installed by running the following command:
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix/rev/${{ github.event.pull_request.head.sha }} | sh -s -- install
The latest commit from this PR can be installed by running the following command:
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix/pr/${{ github.event.pull_request.number }} | sh -s -- install
EOF

View file

@ -1,47 +0,0 @@
name: Release Tags
on:
push:
tags:
- "v*.*.*"
jobs:
release:
concurrency: release
runs-on: ubuntu-latest
permissions:
contents: write # In order to upload artifacts to GitHub releases
id-token: write # In order to request a JWT for AWS auth
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Download Buildkite Artifacts
uses: EnricoMi/download-buildkite-artifact-action@v1.14
with:
buildkite_token: ${{ secrets.BUILDKITE_TOKEN }}
output_path: artifacts
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ secrets.AWS_S3_UPLOAD_ROLE }}
aws-region: us-east-2
- name: Publish Release to S3 (Tag)
env:
AWS_BUCKET: ${{ secrets.AWS_S3_UPLOAD_BUCKET }}
run: |
./upload_s3.sh "$GITHUB_REF_NAME" "$GITHUB_SHA" "https://install.determinate.systems/nix/tag/$GITHUB_REF_NAME"
- name: Publish Release to GitHub (Tag)
uses: softprops/action-gh-release@v1
with:
fail_on_unmatched_files: true
draft: true
files: |
artifacts/**
nix-installer.sh
- name: Install Instructions (Tag)
run: |
cat <<EOF
This tag can be installed by running the following command:
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix/tag/$GITHUB_REF_NAME | sh -s -- install
EOF

View file

@ -1,20 +0,0 @@
name: update-flake-lock
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * 0'
jobs:
lockfile:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
- name: Enable magic Nix cache
uses: DeterminateSystems/magic-nix-cache-action@main
- name: Check flake
uses: DeterminateSystems/flake-checker-action@main
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@main

3
.gitignore vendored
View file

@ -2,4 +2,5 @@
.ci-store .ci-store
.direnv .direnv
result* result*
src/action/linux/selinux/nix.mod src/action/linux/selinux/nix.mod
.idea

View file

@ -60,8 +60,7 @@ representative at an online or offline event.
## Enforcement ## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at reported to the community leaders responsible for enforcement at [community@lix.systems](community@lix.systems).
[coc-grahamc@determinate.systems](coc-grahamc@determinate.systems) or [coc-ana@determinate.systems](coc-ana@determinate.systems) .
All complaints will be reviewed and investigated promptly and fairly. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the All community leaders are obligated to respect the privacy and security of the

View file

@ -69,7 +69,7 @@ Here are how to do various kinds of contributions.
## Bug Reports ## Bug Reports
Create an issue on [the issue page](https://github.com/DeterminateSystems/nix-installer/issues). Create an issue on [the issue page](https://git.lix.systems/lix-project/lix-installer/issues).
It should contain: It should contain:
@ -85,10 +85,10 @@ It should contain:
For **minor** fixes, documentation, or changes which **do not** have a For **minor** fixes, documentation, or changes which **do not** have a
tangible impact on user experience, feel free to open a tangible impact on user experience, feel free to open a
[pull request](https://github.com/DeterminateSystems/nix-installer/pulls) directly. [pull request](https://git.lix.systems/lix-project/lix-installer/pulls) directly.
If the code improvement is not minor, such as new features or user facing If the code improvement is not minor, such as new features or user facing
changes, an [issue](https://github.com/DeterminateSystems/nix-installer/issues) changes, an [issue](https://git.lix.systems/lix-project/lix-installer/issues)
proposing the change is **required** for non-maintainers. proposing the change is **required** for non-maintainers.
Please: Please:
@ -103,7 +103,7 @@ Please:
## Non-code contributions ## Non-code contributions
Please open an [issue](https://github.com/DeterminateSystems/nix-installer/issues) Please open an [issue](https://git.lix.systems/lix-project/lix-installer/issues)
to chat about your contribution and figure out how to best integrate it into to chat about your contribution and figure out how to best integrate it into
the project. the project.
@ -162,8 +162,8 @@ These should be visible in `nix flake show`:
``` ```
nix flake show nix flake show
warning: Git tree '/home/ana/git/determinatesystems/nix-installer' is dirty warning: Git tree '/home/ana/git/detsys/nix-installer' is dirty
git+file:///home/ana/git/determinatesystems/nix-installer git+file:///home/ana/git/detsys/nix-installer
# ... # ...
├───hydraJobs ├───hydraJobs
│ └───vm-test │ └───vm-test
@ -201,12 +201,6 @@ nix build .#hydraJobs.vm-test.rhel-v7.x86_64-linux.all -L -j 4
> You may wish to set `-j 4` to some other number. Some OS's (Ubuntu 16.04) exhibit problems rapidly updating their users/groups on a system running dozens of VMs. > You may wish to set `-j 4` to some other number. Some OS's (Ubuntu 16.04) exhibit problems rapidly updating their users/groups on a system running dozens of VMs.
For PR review, you can also test arbitrary branches or checkouts like so:
```bash
nix build github:determinatesystems/nix-installer/${BRANCH}#hydraJobs.vm-test.ubuntu-v22_04.x86_64-linux.install-default -L
```
<details> <details>
<summary><strong>Adding a distro?</strong></summary> <summary><strong>Adding a distro?</strong></summary>
@ -249,8 +243,8 @@ These should be visible in `nix flake show`:
``` ```
nix flake show nix flake show
warning: Git tree '/home/ana/git/determinatesystems/nix-installer' is dirty warning: Git tree '/home/ana/git/detsys/nix-installer' is dirty
git+file:///home/ana/git/determinatesystems/nix-installer git+file:///home/ana/git/detsys/nix-installer
# ... # ...
├───hydraJobs ├───hydraJobs
│ ├───container-test │ ├───container-test
@ -291,12 +285,6 @@ To run a specific distribution listed in the `nix flake show` output:
nix build .#hydraJobs.container-test.ubuntu-v22_04.x86_64-linux.docker -L nix build .#hydraJobs.container-test.ubuntu-v22_04.x86_64-linux.docker -L
``` ```
For PR review, you can also test arbitrary branches or checkouts like so:
```bash
nix build github:determinatesystems/nix-installer/${BRANCH}#hydraJobs.container-test.ubuntu-v22_04.x86_64-linux.podman -L
```
<details> <details>
<summary><strong>Adding a distro?</strong></summary> <summary><strong>Adding a distro?</strong></summary>
@ -390,11 +378,6 @@ To cut a release:
+ **Warning:** While you can re-release Github releases, it is not possible to do the same on `crates.io` + **Warning:** While you can re-release Github releases, it is not possible to do the same on `crates.io`
* Create a PR bumping the version up one minor in the `Cargo.toml`, `flake.nix`, and fixture JSON files, adding `-unreleased` at the end (`v0.0.2-unreleased`) * Create a PR bumping the version up one minor in the `Cargo.toml`, `flake.nix`, and fixture JSON files, adding `-unreleased` at the end (`v0.0.2-unreleased`)
# Who maintains `nix-installer` and why? # Who maintains `lix-installer` and why?
`nix-installer` is maintained by [Determinate Systems](https://determinate.systems/) in `lix-installer` is maintained by [the Lix community](https://lix.systems/) as part of the Lix Project.
an effort to explore Nix installer ideas.
Determinate Systems has no plans to monetize or relicense `nix-installer`. If your
enterprise requires a support contact in order to adopt a tool, please contact
Determinate Systems and something can be worked out.

88
Cargo.lock generated
View file

@ -851,6 +851,50 @@ version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "lix-installer"
version = "0.17.1"
dependencies = [
"async-trait",
"bytes 1.5.0",
"clap",
"color-eyre",
"dirs",
"dyn-clone",
"eyre",
"glob",
"indexmap 2.2.3",
"is_ci",
"nix",
"nix-config-parser",
"os-release",
"owo-colors 4.0.0",
"plist",
"rand",
"reqwest",
"semver",
"serde",
"serde_json",
"serde_with",
"strum",
"sysctl",
"tar",
"target-lexicon",
"tempfile",
"term",
"thiserror",
"tokio",
"tracing",
"tracing-error",
"tracing-subscriber",
"typetag",
"url",
"uuid",
"walkdir",
"which",
"xz2",
]
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.11" version = "0.4.11"
@ -941,50 +985,6 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "nix-installer"
version = "0.17.1"
dependencies = [
"async-trait",
"bytes 1.5.0",
"clap",
"color-eyre",
"dirs",
"dyn-clone",
"eyre",
"glob",
"indexmap 2.2.3",
"is_ci",
"nix",
"nix-config-parser",
"os-release",
"owo-colors 4.0.0",
"plist",
"rand",
"reqwest",
"semver",
"serde",
"serde_json",
"serde_with",
"strum",
"sysctl",
"tar",
"target-lexicon",
"tempfile",
"term",
"thiserror",
"tokio",
"tracing",
"tracing-error",
"tracing-subscriber",
"typetag",
"url",
"uuid",
"walkdir",
"which",
"xz2",
]
[[package]] [[package]]
name = "nu-ansi-term" name = "nu-ansi-term"
version = "0.46.0" version = "0.46.0"

View file

@ -1,12 +1,12 @@
[package] [package]
name = "nix-installer" name = "lix-installer"
description = "The Determinate Nix Installer" description = "The Determinate Nix Installer"
version = "0.17.1" version = "0.17.1"
edition = "2021" edition = "2021"
resolver = "2" resolver = "2"
license = "LGPL-2.1" license = "LGPL-2.1"
repository = "https://github.com/DeterminateSystems/nix-installer" repository = "https://git.lix.systems/lix-project/lix-installer"
documentation = "https://docs.rs/nix-installer/latest/nix_installer" documentation = "https://docs.rs/lix-installer/latest/lix_installer"
[package.metadata.riff.targets.aarch64-apple-darwin] [package.metadata.riff.targets.aarch64-apple-darwin]
build-inputs = ["darwin.apple_sdk.frameworks.Security"] build-inputs = ["darwin.apple_sdk.frameworks.Security"]
@ -15,12 +15,11 @@ build-inputs = ["darwin.apple_sdk.frameworks.Security"]
build-inputs = ["darwin.apple_sdk.frameworks.Security"] build-inputs = ["darwin.apple_sdk.frameworks.Security"]
[features] [features]
default = ["cli", "diagnostics"] default = ["cli"]
cli = ["eyre", "color-eyre", "clap", "tracing-subscriber", "tracing-error"] cli = ["eyre", "color-eyre", "clap", "tracing-subscriber", "tracing-error"]
diagnostics = ["is_ci"]
[[bin]] [[bin]]
name = "nix-installer" name = "lix-installer"
required-features = [ "cli" ] required-features = [ "cli" ]
[dependencies] [dependencies]

252
README.md
View file

@ -1,57 +1,39 @@
# The Determinate Nix Installer # The Lix Installer
[![Crates.io](https://img.shields.io/crates/v/nix-installer)](https://crates.io/crates/nix-installer) A fast, friendly, and reliable tool to help you use Lix, the community implementation of the nix tooling.
[![Docs.rs](https://img.shields.io/docsrs/nix-installer)](https://docs.rs/nix-installer/latest/nix_installer/) Based on the [Determinate Installer](https://install.determinate.systems).
A fast, friendly, and reliable tool to help you use [Nix] with Flakes everywhere.
```bash ```bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install curl --proto '=https' --tlsv1.2 -sSf -L https://install.lix.systems/nix | sh -s -- install
``` ```
The `nix-installer` has successfully completed over 2,000,000 installs in a number of environments, including [Github Actions](#as-a-github-action) and [GitLab](#on-gitlab):
| Platform | Multi User | `root` only | Maturity |
|------------------------------|:------------------:|:-----------:|:-----------------:|
| Linux (x86_64 & aarch64) | ✓ (via [systemd]) | ✓ | Stable |
| MacOS (x86_64 & aarch64) | ✓ | | Stable (See note) |
| Valve Steam Deck (SteamOS) | ✓ | | Stable |
| WSL2 (x86_64 & aarch64) | ✓ (via [systemd]) | ✓ | Stable |
| Podman Linux Containers | ✓ (via [systemd]) | ✓ | Stable |
| Docker Containers | | ✓ | Stable |
| Linux (i686) | ✓ (via [systemd]) | ✓ | Unstable |
> **Note**
> On **MacOS only**, removing users and/or groups may fail if there are no users who are logged in graphically.
## Usage ## Usage
Install Nix with the default planner and options: Install Nix with the default planner and options:
```bash ```bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install curl --proto '=https' --tlsv1.2 -sSf -L https://install.lix.systems/lix | sh -s -- install
``` ```
Or, to download a platform specific Installer binary yourself: Or, to download a platform specific Installer binary yourself:
```bash ```bash
$ curl -sL -o nix-installer https://install.determinate.systems/nix/nix-installer-x86_64-linux $ curl -sL -o lix-installer https://install.lix.systems/lix/lix-installer-x86_64-linux
$ chmod +x nix-installer $ chmod +x lix-installer
$ ./nix-installer $ ./lix-installer
``` ```
`nix-installer` installs Nix by following a *plan* made by a *planner*. Review the available planners: `lix-installer` installs Lix by following a *plan* made by a *planner*. Review the available planners:
```bash ```bash
$ ./nix-installer install --help $ ./lix-installer install --help
Execute an install (possibly using an existing plan) Execute an install (possibly using an existing plan)
To pass custom options, select a planner, for example `nix-installer install linux-multi --help` To pass custom options, select a planner, for example `lix-installer install linux-multi --help`
Usage: nix-installer install [OPTIONS] [PLAN] Usage: lix-installer install [OPTIONS] [PLAN]
nix-installer install <COMMAND> lix-installer install <COMMAND>
Commands: Commands:
linux linux
@ -66,10 +48,10 @@ Commands:
Planners have their own options and defaults, sharing most of them in common: Planners have their own options and defaults, sharing most of them in common:
```bash ```bash
$ ./nix-installer install linux --help $ ./lix-installer install linux --help
A planner for Linux installs A planner for Linux installs
Usage: nix-installer install linux [OPTIONS] Usage: lix-installer install linux [OPTIONS]
Options: Options:
# ... # ...
@ -90,74 +72,33 @@ Options:
Planners can be configured via environment variable or command arguments: Planners can be configured via environment variable or command arguments:
```bash ```bash
$ curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | NIX_BUILD_GROUP_NAME=nixbuilder sh -s -- install linux-multi --nix-build-group-id 4000 $ curl --proto '=https' --tlsv1.2 -sSf -L https://install.lix.systems/lix | NIX_BUILD_GROUP_NAME=nixbuilder sh -s -- install linux-multi --nix-build-group-id 4000
# Or... # Or...
$ NIX_BUILD_GROUP_NAME=nixbuilder ./nix-installer install linux-multi --nix-build-group-id 4000 $ NIX_BUILD_GROUP_NAME=nixbuilder ./lix-installer install linux-multi --nix-build-group-id 4000
``` ```
### Upgrading Nix ### Upgrading Lix
You can upgrade Nix to the version described in [`DeterminateSystems/nix-upgrade`][nix-upgrade] by running: You can upgrade Lix with:
``` ```
sudo -i nix upgrade-nix sudo -i nix upgrade-nix
``` ```
Alternatively, you can [uninstall](#uninstalling) and [reinstall](#usage) with a different version of the `nix-installer`. Alternatively, you can [uninstall](#uninstalling) and [reinstall](#usage) with a different version of the `lix-installer`.
### Uninstalling ### Uninstalling
You can remove a `nix-installer`-installed Nix by running You can remove a `lix-installer`-installed Nix by running
```bash ```bash
/nix/nix-installer uninstall /nix/lix-installer uninstall
``` ```
### As a Github Action
You can use the [`nix-installer-action`](https://github.com/DeterminateSystems/nix-installer-action) Github Action like so:
```yaml
on:
pull_request:
push:
branches: [main]
jobs:
lints:
name: Build
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
- name: Run `nix build`
run: nix build .
```
### On GitLab
GitLab CI runners are typically Docker based and run as the `root` user. This means `systemd` is not present, so the `--init none` option needs to be passed to the Linux planner.
On the default [GitLab.com](https://gitlab.com/) runners, `nix` can be installed and used like so:
```yaml
test:
script:
- curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux --no-confirm --init none
- . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
- nix run nixpkgs#hello
- nix profile install nixpkgs#hello
- hello
```
If you are using different runners, the above example may need to be adjusted.
### Without systemd (Linux only) ### Without systemd (Linux only)
> **Warning** > **Warning**
> When `--init none` is used, _only_ `root` or users who can elevate to `root` privileges can run Nix: > When `--init none` is used, _only_ `root` or users who can elevate to `root` privileges can run Lix's nix command:
> >
> ```bash > ```bash
> sudo -i nix run nixpkgs#hello > sudo -i nix run nixpkgs#hello
@ -166,7 +107,7 @@ If you are using different runners, the above example may need to be adjusted.
If you don't use [systemd], you can still install Nix by explicitly specifying the `linux` plan and `--init none`: If you don't use [systemd], you can still install Nix by explicitly specifying the `linux` plan and `--init none`:
```bash ```bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux --init none curl --proto '=https' --tlsv1.2 -sSf -L https://install.lix.systems/lix | sh -s -- install linux --init none
``` ```
### In a container ### In a container
@ -176,7 +117,7 @@ In Docker/Podman containers or WSL2 instances where an init (like `systemd`) is
For containers (without an init): For containers (without an init):
> **Warning** > **Warning**
> When `--init none` is used, _only_ `root` or users who can elevate to `root` privileges can run Nix: > When `--init none` is used, _only_ `root` or users who can elevate to `root` privileges can run Lix's nix command:
> >
> ```bash > ```bash
> sudo -i nix run nixpkgs#hello > sudo -i nix run nixpkgs#hello
@ -187,7 +128,7 @@ For containers (without an init):
FROM ubuntu:latest FROM ubuntu:latest
RUN apt update -y RUN apt update -y
RUN apt install curl -y RUN apt install curl -y
RUN curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux \ RUN curl --proto '=https' --tlsv1.2 -sSf -L https://install.lix.systems/lix | sh -s -- install linux \
--extra-conf "sandbox = false" \ --extra-conf "sandbox = false" \
--init none \ --init none \
--no-confirm --no-confirm
@ -212,7 +153,7 @@ For containers with a systemd init:
FROM ubuntu:latest FROM ubuntu:latest
RUN apt update -y RUN apt update -y
RUN apt install curl systemd -y RUN apt install curl systemd -y
RUN curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux \ RUN curl --proto '=https' --tlsv1.2 -sSf -L https://install.lix.systems/lix | sh -s -- install linux \
--extra-conf "sandbox = false" \ --extra-conf "sandbox = false" \
--no-start-daemon \ --no-start-daemon \
--no-confirm --no-confirm
@ -234,11 +175,11 @@ On some container tools, such as `docker`, `sandbox = false` can be omitted. Omi
### In WSL2 ### In WSL2
We **strongly recommend** [enabling systemd](https://ubuntu.com/blog/ubuntu-wsl-enable-systemd), then installing Nix as normal: We **strongly recommend** [enabling systemd](https://ubuntu.com/blog/ubuntu-wsl-enable-systemd), then installing Lix as normal:
```bash ```bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install curl --proto '=https' --tlsv1.2 -sSf -L https://install.lix.systems/lix | sh -s -- install
``` ```
If [WSLg][wslg] is enabled, you can do things like open a Linux Firefox from Windows on Powershell: If [WSLg][wslg] is enabled, you can do things like open a Linux Firefox from Windows on Powershell:
@ -257,7 +198,7 @@ wsl nix run --impure github:guibou/nixGL nix run nixpkgs#obs-studio
If enabling systemd is not an option, pass `--init none` at the end of the command: If enabling systemd is not an option, pass `--init none` at the end of the command:
> **Warning** > **Warning**
> When `--init none` is used, _only_ `root` or users who can elevate to `root` privileges can run Nix: > When `--init none` is used, _only_ `root` or users who can elevate to `root` privileges can run Lix's nix commands:
> >
> ```bash > ```bash
> sudo -i nix run nixpkgs#hello > sudo -i nix run nixpkgs#hello
@ -265,7 +206,7 @@ If enabling systemd is not an option, pass `--init none` at the end of the comma
```bash ```bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install linux --init none curl --proto '=https' --tlsv1.2 -sSf -L https://install.lix.systems/lix | sh -s -- install linux --init none
``` ```
### Skip confirmation ### Skip confirmation
@ -273,7 +214,7 @@ curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix
If you'd like to bypass the confirmation step, you can apply the `--no-confirm` flag: If you'd like to bypass the confirmation step, you can apply the `--no-confirm` flag:
```bash ```bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install --no-confirm curl --proto '=https' --tlsv1.2 -sSf -L https://install.lix.systems/lix | sh -s -- install --no-confirm
``` ```
This is especially useful when using the installer in non-interactive scripts. This is especially useful when using the installer in non-interactive scripts.
@ -281,11 +222,11 @@ This is especially useful when using the installer in non-interactive scripts.
## Quirks ## Quirks
While `nix-installer` tries to provide a comprehensive and unquirky experience, there are unfortunately some issues which may require manual intervention or operator choices. While `lix-installer` tries to provide a comprehensive and unquirky experience, there are unfortunately some issues which may require manual intervention or operator choices.
### Using MacOS after removing `nix` while `nix-darwin` was still installed, network requests fail ### Using MacOS after removing `nix` while `nix-darwin` was still installed, network requests fail
If `nix` was previously uninstalled without uninstalling `nix-darwin` first, users may experience errors similar to this: If any variant of `nix` was previously uninstalled without uninstalling `nix-darwin` first, users may experience errors similar to this:
```bash ```bash
$ nix shell nixpkgs#curl $ nix shell nixpkgs#curl
@ -310,56 +251,46 @@ It's possible to resolve this situation by removing the `org.nixos.activate-syst
```bash ```bash
$ sudo rm /Library/LaunchDaemons/org.nixos.activate-system.plist $ sudo rm /Library/LaunchDaemons/org.nixos.activate-system.plist
$ sudo launchctl bootout system/org.nixos.activate-system $ sudo launchctl bootout system/org.nixos.activate-system
$ /nix/nix-installer uninstall $ /nix/lix-installer uninstall
$ sudo rm /etc/ssl/certs/ca-certificates.crt $ sudo rm /etc/ssl/certs/ca-certificates.crt
``` ```
Then run the `nix-installer` again, and it should work. Then run the `lix-installer` again, and it should work.
Up-to-date versions of the `nix-installer` will refuse to uninstall until `nix-darwin` is uninstalled first, helping mitigate this problem. Up-to-date versions of the `lix-installer` will refuse to uninstall until `nix-darwin` is uninstalled first, helping mitigate this problem.
## Building a binary ## Building a binary
Since you'll be using `nix-installer` to install Nix on systems without Nix, the default build is a static binary. Since you'll be using `lix-installer` to install Nix on systems without Nix, the default build is a static binary.
Build a portable Linux binary on a system with Nix: Build a portable Linux binary on a system with Nix:
```bash ```bash
# to build a local copy # to build a local copy
nix build -L ".#nix-installer-static" nix build -L ".#lix-installer-static"
# to build the remote main development branch
nix build -L "github:determinatesystems/nix-installer#nix-installer-static"
# for a specific version of the installer:
export NIX_INSTALLER_TAG="v0.6.0"
nix build -L "github:determinatesystems/nix-installer/$NIX_INSTALLER_TAG#nix-installer-static"
``` ```
On Mac: On Mac:
```bash ```bash
# to build a local copy # to build a local copy
nix build -L ".#nix-installer" nix build -L ".#lix-installer"
# to build the remote main development branch
nix build -L "github:determinatesystems/nix-installer#nix-installer"
# for a specific version of the installer:
export NIX_INSTALLER_TAG="v0.6.0"
nix build -L "github:determinatesystems/nix-installer/$NIX_INSTALLER_TAG#nix-installer"
``` ```
Then copy the `result/bin/nix-installer` to the machine you wish to run it on. Then copy the `result/bin/lix-installer` to the machine you wish to run it on.
You can also add `nix-installer` to a system without Nix via `cargo`, there are no system dependencies to worry about: You can also add `lix-installer` to a system without Lix via `cargo`. There are no system dependencies to worry about:
```bash ```bash
# to build and run a local copy # to build and run a local copy
RUSTFLAGS="--cfg tokio_unstable" cargo run -- --help RUSTFLAGS="--cfg tokio_unstable" cargo run -- --help
# to build the remote main development branch # to build the remote main development branch
RUSTFLAGS="--cfg tokio_unstable" cargo install --git https://github.com/DeterminateSystems/nix-installer RUSTFLAGS="--cfg tokio_unstable" cargo install --git https://git.lix.systems/lix-project/lix-installer
nix-installer --help lix-installer --help
# for a specific version of the installer: # for a specific version of the installer:
export NIX_INSTALLER_TAG="v0.6.0" export NIX_INSTALLER_TAG="v0.6.0"
RUSTFLAGS="--cfg tokio_unstable" cargo install --git https://github.com/DeterminateSystems/nix-installer --tag $NIX_INSTALLER_TAG RUSTFLAGS="--cfg tokio_unstable" cargo install --git https://git.lix.systems/lix-project/lix-installer --tag $NIX_INSTALLER_TAG
nix-installer --help lix-installer --help
``` ```
To make this build portable, pass ` --target x86_64-unknown-linux-musl`. To make this build portable, pass ` --target x86_64-unknown-linux-musl`.
@ -373,10 +304,10 @@ To make this build portable, pass ` --target x86_64-unknown-linux-musl`.
> **Warning** > **Warning**
> Use as a library is still experimental. This feature is likely to be removed in the future without an advocate. If you're using this, please let us know and we can make a path to stabilization. > Use as a library is still experimental. This feature is likely to be removed in the future without an advocate. If you're using this, please let us know and we can make a path to stabilization.
Add `nix-installer` to your dependencies: Add `lix-installer` to your dependencies:
```bash ```bash
cargo add nix-installer cargo add lix-installer
``` ```
If you are **building a CLI**, check out the `cli` feature flag for `clap` integration. If you are **building a CLI**, check out the `cli` feature flag for `clap` integration.
@ -389,39 +320,14 @@ You'll also need to edit your `.cargo/config.toml` to use `tokio_unstable` as we
rustflags=["--cfg", "tokio_unstable"] rustflags=["--cfg", "tokio_unstable"]
``` ```
Then it's possible to review the [documentation](https://docs.rs/nix-installer/latest/nix_installer/): Then it's possible to review the [documentation](https://docs.rs/lix-installer/latest/lix_installer/):
```bash ```bash
cargo doc --open -p nix-installer cargo doc --open -p lix-installer
```
Documentation is also available via `nix` build:
```bash
nix build github:DeterminateSystems/nix-installer#nix-installer.doc
firefox result-doc/nix-installer/index.html
``` ```
## Accessing other versions ## Accessing other versions
For users who desire version pinning, the version of `nix-installer` to use can be specified in the `curl` command:
```bash
VERSION="v0.6.0"
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix/tag/${VERSION} | sh -s -- install
```
To discover which versions are available, or download the binaries for any release, check the [Github Releases](https://github.com/DeterminateSystems/nix-installer/releases).
These releases can be downloaded and used directly:
```bash
VERSION="v0.6.0"
ARCH="aarch64-linux"
curl -sSf -L https://github.com/DeterminateSystems/nix-installer/releases/download/${VERSION}/nix-installer-${ARCH} -o nix-installer
./nix-installer install
```
Each installer version has an [associated supported nix version](src/settings.rs) -- if you pin the installer version, you'll also indirectly pin to the associated nix version. Each installer version has an [associated supported nix version](src/settings.rs) -- if you pin the installer version, you'll also indirectly pin to the associated nix version.
You can also override the `nix` version via `--nix-package-url` or `NIX_INSTALLER_NIX_PACKAGE_URL=` but doing so is not recommended since we haven't tested that combination. You can also override the `nix` version via `--nix-package-url` or `NIX_INSTALLER_NIX_PACKAGE_URL=` but doing so is not recommended since we haven't tested that combination.
@ -440,63 +346,13 @@ Differing from the upstream [Nix](https://github.com/NixOS/nix) installer script
+ `auto-optimise-store` is set to `true` (On Linux only) + `auto-optimise-store` is set to `true` (On Linux only)
* `extra-nix-path` is set to `nixpkgs=flake:nixpkgs` * `extra-nix-path` is set to `nixpkgs=flake:nixpkgs`
* `max-jobs` is set to `auto` * `max-jobs` is set to `auto`
* `upgrade-nix-store-path-url` is set to `https://install.determinate.systems/nix-upgrade/stable/universal` * `upgrade-nix-store-path-url` is set to `https://install.lix.systems/lix-upgrade/stable/universal`
* an installation receipt (for uninstalling) is stored at `/nix/receipt.json` as well as a copy of the install binary at `/nix/nix-installer` * an installation receipt (for uninstalling) is stored at `/nix/receipt.json` as well as a copy of the install binary at `/nix/lix-installer`
* `nix-channel --update` is not run, `~/.nix-channels` is not provisioned * `nix-channel --update` is not run, `~/.nix-channels` is not provisioned
* `ssl-cert-file` is set in `/etc/nix/nix.conf` if the `ssl-cert-file` argument is used. * `ssl-cert-file` is set in `/etc/nix/nix.conf` if the `ssl-cert-file` argument is used.
## Motivations
The existing upstream scripts do a good job, however they are difficult to maintain. ## No Telemetry Included
Subtle differences in the shell implementations and tool used in the scripts make it difficult to make meaningful changes to the installer. The Lix installer respects user privacy, and thus collects no information.
The Determinate Nix installer has numerous advantages:
* survives macOS upgrades
* keeping an installation receipt for easy uninstallation
* offering users a chance to review an accurate, calculated install plan
* having 'planners' which can create appropriate install plans for complicated targets
* offering users with a failing install the chance to do a best-effort revert
* improving performance by maximizing parallel operations
* supporting a expanded test suite including 'curing' cases
* supporting SELinux and OSTree based distributions without asking users to make compromises
* operating as a single, static binary with external dependencies such as `openssl`, only calling existing system tools (like `useradd`) where necessary
* As a MacOS remote build target, ensures `nix` is not absent from path
It has been wonderful to collaborate with other participants in the Nix Installer Working Group and members of the broader community. The working group maintains a [foundation owned fork of the installer](https://github.com/nixos/experimental-nix-installer/).
## Diagnostics
The goal of the Determinate Nix Installer is to successfully and correctly install Nix.
The `curl | sh` pipeline and the installer collects a little bit of diagnostic information to help us make that true.
Here is a table of the [diagnostic data we collect][diagnosticdata]:
| Field | Use |
| --------------------- | ----------------------------------------------------------------------------------------------------- |
| `version` | The version of the Determinate Nix Installer. |
| `planner` | The method of installing Nix (`linux`, `macos`, `steam-deck`) |
| `configured_settings` | The names of planner settings which were changed from their default. Does _not_ include the values. |
| `os_name` | The running operating system. |
| `os_version` | The version of the operating system. |
| `triple` | The architecture/operating system/binary format of your system. |
| `is_ci` | Whether the installer is being used in CI (e.g. GitHub Actions). |
| `action` | Either `Install` or `Uninstall`. |
| `status` | One of `Success`, `Failure`, `Pending`, or `Cancelled`. |
| `attribution` | Optionally defined by the user, associate the diagnostics of this run to the provided value. |
| `failure_chain` | A high level description of what the failure was, if any. For example: `Command("diskutil")` if the command `diskutil list` failed. |
To disable diagnostic reporting, set the diagnostics URL to an empty string by passing `--diagnostic-endpoint=""` or setting `NIX_INSTALLER_DIAGNOSTIC_ENDPOINT=""`.
You can read the full privacy policy for [Determinate Systems][detsys], the creators of the Determinate Nix Installer, [here][privacy].
[detsys]: https://determinate.systems/
[diagnosticdata]: https://github.com/DeterminateSystems/nix-installer/blob/f9f927840d532b71f41670382a30cfcbea2d8a35/src/diagnostics.rs#L29-L43
[privacy]: https://determinate.systems/policies/privacy
[systemd]: https://systemd.io
[wslg]: https://github.com/microsoft/wslg
[nixgl]: https://github.com/guibou/nixGL
[Nix]: https://nixos.org
[nix-upgrade]: https://github.com/DeterminateSystems/nix-upgrade/blob/main/versions.nix

View file

@ -1,11 +1,11 @@
{ {
description = "The Determinate Nix Installer"; description = "The Lix Installer";
inputs = { inputs = {
nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1.0.tar.gz"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
fenix = { fenix = {
url = "https://flakehub.com/f/nix-community/fenix/0.1.1584.tar.gz"; url = "github:nix-community/fenix";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
@ -65,10 +65,10 @@
rustc = toolchain; rustc = toolchain;
}; };
sharedAttrs = { sharedAttrs = {
pname = "nix-installer"; pname = "lix-installer";
version = "0.17.1"; version = "0.17.1";
src = builtins.path { src = builtins.path {
name = "nix-installer-source"; name = "lix-installer-source";
path = self; path = self;
filter = (path: type: baseNameOf path != "nix" && baseNameOf path != ".github"); filter = (path: type: baseNameOf path != "nix" && baseNameOf path != ".github");
}; };
@ -93,27 +93,27 @@
''; '';
}; };
postInstall = '' postInstall = ''
cp nix-installer.sh $out/bin/nix-installer.sh cp lix-installer.sh $out/bin/lix-installer.sh
''; '';
}; };
in in
rec { rec {
nix-installer = naerskLib.buildPackage sharedAttrs; lix-installer = naerskLib.buildPackage sharedAttrs;
} // nixpkgs.lib.optionalAttrs (prev.stdenv.system == "x86_64-linux") rec { } // nixpkgs.lib.optionalAttrs (prev.stdenv.system == "x86_64-linux") rec {
default = nix-installer-static; default = lix-installer-static;
nix-installer-static = naerskLib.buildPackage lix-installer-static = naerskLib.buildPackage
(sharedAttrs // { (sharedAttrs // {
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl"; CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
}); });
} // nixpkgs.lib.optionalAttrs (prev.stdenv.system == "i686-linux") rec { } // nixpkgs.lib.optionalAttrs (prev.stdenv.system == "i686-linux") rec {
default = nix-installer-static; default = lix-installer-static;
nix-installer-static = naerskLib.buildPackage lix-installer-static = naerskLib.buildPackage
(sharedAttrs // { (sharedAttrs // {
CARGO_BUILD_TARGET = "i686-unknown-linux-musl"; CARGO_BUILD_TARGET = "i686-unknown-linux-musl";
}); });
} // nixpkgs.lib.optionalAttrs (prev.stdenv.system == "aarch64-linux") rec { } // nixpkgs.lib.optionalAttrs (prev.stdenv.system == "aarch64-linux") rec {
default = nix-installer-static; default = lix-installer-static;
nix-installer-static = naerskLib.buildPackage lix-installer-static = naerskLib.buildPackage
(sharedAttrs // { (sharedAttrs // {
CARGO_BUILD_TARGET = "aarch64-unknown-linux-musl"; CARGO_BUILD_TARGET = "aarch64-unknown-linux-musl";
}); });
@ -190,18 +190,18 @@
packages = forAllSystems ({ system, pkgs, ... }: packages = forAllSystems ({ system, pkgs, ... }:
{ {
inherit (pkgs) nix-installer; inherit (pkgs) lix-installer;
} // nixpkgs.lib.optionalAttrs (system == "x86_64-linux") { } // nixpkgs.lib.optionalAttrs (system == "x86_64-linux") {
inherit (pkgs) nix-installer-static; inherit (pkgs) lix-installer-static;
default = pkgs.nix-installer-static; default = pkgs.lix-installer-static;
} // nixpkgs.lib.optionalAttrs (system == "i686-linux") { } // nixpkgs.lib.optionalAttrs (system == "i686-linux") {
inherit (pkgs) nix-installer-static; inherit (pkgs) lix-installer-static;
default = pkgs.nix-installer-static; default = pkgs.lix-installer-static;
} // nixpkgs.lib.optionalAttrs (system == "aarch64-linux") { } // nixpkgs.lib.optionalAttrs (system == "aarch64-linux") {
inherit (pkgs) nix-installer-static; inherit (pkgs) lix-installer-static;
default = pkgs.nix-installer-static; default = pkgs.lix-installer-static;
} // nixpkgs.lib.optionalAttrs (pkgs.stdenv.isDarwin) { } // nixpkgs.lib.optionalAttrs (pkgs.stdenv.isDarwin) {
default = pkgs.nix-installer; default = pkgs.lix-installer;
}); });
hydraJobs = { hydraJobs = {

View file

@ -1,11 +1,11 @@
#!/bin/sh #!/bin/sh
# shellcheck shell=dash # shellcheck shell=dash
# If you need an offline install, or you'd prefer to run the binary directly, head to # If you need an offline install, or you'd prefer to run the binary directly, head to
# https://github.com/DeterminateSystems/nix-installer/releases then pick the version and platform # https://git.lix.systems/lix-project/lix-installer/releases then pick the version and platform
# most appropriate for your deployment target. # most appropriate for your deployment target.
# #
# This is just a little script that selects and downloads the right `nix-installer`. It does # This is just a little script that selects and downloads the right `lix-installer`. It does
# platform detection, downloads the installer, and runs it; that's it. # platform detection, downloads the installer, and runs it; that's it.
# #
# It runs on Unix shells like {a,ba,da,k,z}sh. It uses the common `local` # It runs on Unix shells like {a,ba,da,k,z}sh. It uses the common `local`
@ -17,7 +17,7 @@ if [ "$KSH_VERSION" = 'Version JM 93t+ 2010-03-05' ]; then
# The version of ksh93 that ships with many illumos systems does not # The version of ksh93 that ships with many illumos systems does not
# support the "local" extension. Print a message rather than fail in # support the "local" extension. Print a message rather than fail in
# subtle ways later on: # subtle ways later on:
echo 'nix-installer does not work with this ksh93 version; please try bash!' >&2 echo 'lix-installer does not work with this ksh93 version; please try bash!' >&2
exit 1 exit 1
fi fi
@ -25,7 +25,7 @@ fi
set -u set -u
# If NIX_INSTALLER_FORCE_ALLOW_HTTP is unset or empty, default it. # If NIX_INSTALLER_FORCE_ALLOW_HTTP is unset or empty, default it.
NIX_INSTALLER_BINARY_ROOT="${NIX_INSTALLER_BINARY_ROOT:-https://install.determinate.systems/nix}" NIX_INSTALLER_BINARY_ROOT="${NIX_INSTALLER_BINARY_ROOT:-https://install.lix.systems/lix}"
main() { main() {
downloader --check downloader --check
@ -47,7 +47,7 @@ main() {
;; ;;
esac esac
local _url="${NIX_INSTALLER_OVERRIDE_URL-${NIX_INSTALLER_BINARY_ROOT}/nix-installer-${_arch}${_ext}}" local _url="${NIX_INSTALLER_OVERRIDE_URL-${NIX_INSTALLER_BINARY_ROOT}/lix-installer-${_arch}${_ext}}"
local _dir local _dir
if ! _dir="$(ensure mktemp -d)"; then if ! _dir="$(ensure mktemp -d)"; then
@ -55,7 +55,7 @@ main() {
# propagate exit status. # propagate exit status.
exit 1 exit 1
fi fi
local _file="${_dir}/nix-installer${_ext}" local _file="${_dir}/lix-installer${_ext}"
local _ansi_escapes_are_valid=false local _ansi_escapes_are_valid=false
if [ -t 2 ]; then if [ -t 2 ]; then
@ -95,7 +95,7 @@ main() {
ensure chmod u+x "$_file" ensure chmod u+x "$_file"
if [ ! -x "$_file" ]; then if [ ! -x "$_file" ]; then
printf '%s\n' "Cannot execute $_file (likely because of mounting /tmp as noexec)." 1>&2 printf '%s\n' "Cannot execute $_file (likely because of mounting /tmp as noexec)." 1>&2
printf '%s\n' "Please copy the file to a location where you can execute binaries and run ./nix-installer${_ext}." 1>&2 printf '%s\n' "Please copy the file to a location where you can execute binaries and run ./lix-installer${_ext}." 1>&2
exit 1 exit 1
fi fi
@ -229,7 +229,7 @@ get_architecture() {
} }
say() { say() {
printf 'nix-installer: %s\n' "$1" printf 'lix-installer: %s\n' "$1"
} }
err() { err() {

View file

@ -1,9 +1,9 @@
FROM default FROM default
COPY nix-installer /nix-installer COPY lix-installer /lix-installer
RUN chmod +x /nix-installer RUN chmod +x /lix-installer
COPY binary-tarball /binary-tarball COPY binary-tarball /binary-tarball
RUN mv /binary-tarball/nix-*.tar.xz nix.tar.xz RUN mv /binary-tarball/nix-*.tar.xz nix.tar.xz
RUN /nix-installer/bin/nix-installer install linux --logger pretty --log-directive nix_installer=debug --nix-package-url file:///nix.tar.xz --init none --extra-conf "sandbox = false" --no-confirm -vvv RUN /nix-installer/bin/lix-installer install linux --logger pretty --log-directive nix_installer=debug --nix-package-url file:///nix.tar.xz --init none --extra-conf "sandbox = false" --no-confirm -vvv
ENV PATH="${PATH}:/nix/var/nix/profiles/default/bin" ENV PATH="${PATH}:/nix/var/nix/profiles/default/bin"
RUN nix-build --no-substitute -E 'derivation { name = "foo"; system = "x86_64-linux"; builder = "/bin/sh"; args = ["-c" "echo foobar > $out"]; }' RUN nix-build --no-substitute -E 'derivation { name = "foo"; system = "x86_64-linux"; builder = "/bin/sh"; args = ["-c" "echo foobar > $out"]; }'
RUN /nix/nix-installer uninstall --no-confirm RUN /nix/lix-installer uninstall --no-confirm

View file

@ -410,7 +410,7 @@ impl Action for CreateOrMergeNixConfig {
} }
new_config new_config
.push_str("# Generated by https://github.com/DeterminateSystems/nix-installer.\n"); .push_str("# Generated by https://install.lix.systems/.\n");
new_config.push_str("# See `/nix/nix-installer --version` for the version details.\n"); new_config.push_str("# See `/nix/nix-installer --version` for the version details.\n");
new_config.push('\n'); new_config.push('\n');

View file

@ -131,7 +131,7 @@ impl PlaceNixConfiguration {
); );
settings.insert( settings.insert(
"upgrade-nix-store-path-url".to_string(), "upgrade-nix-store-path-url".to_string(),
"https://install.determinate.systems/nix-upgrade/stable/universal".to_string(), "https://install.lix.systems/lix-upgrade/stable/universal".to_string(),
); );
let create_directory = CreateDirectory::plan(NIX_CONF_FOLDER, None, None, 0o0755, force) let create_directory = CreateDirectory::plan(NIX_CONF_FOLDER, None, None, 0o0755, force)

View file

@ -27,9 +27,9 @@ impl CreateNixHookService {
pub async fn plan() -> Result<StatefulAction<Self>, ActionError> { pub async fn plan() -> Result<StatefulAction<Self>, ActionError> {
let mut this = Self { let mut this = Self {
path: PathBuf::from( path: PathBuf::from(
"/Library/LaunchDaemons/systems.determinate.nix-installer.nix-hook.plist", "/Library/LaunchDaemons/systems.lix.nix-installer.nix-hook.plist",
), ),
service_label: "systems.determinate.nix-installer.nix-hook".into(), service_label: "systems.lix.nix-installer.nix-hook".into(),
needs_bootout: false, needs_bootout: false,
}; };

View file

@ -24,7 +24,7 @@ You can manually plan, execute, then revert an [`Action`] like so:
```rust,no_run ```rust,no_run
# async fn wrapper() { # async fn wrapper() {
use nix_installer::action::base::CreateDirectory; use lix_installer::action::base::CreateDirectory;
let mut action = CreateDirectory::plan("/nix", None, None, 0o0755, true).await.unwrap(); let mut action = CreateDirectory::plan("/nix", None, None, 0o0755, true).await.unwrap();
action.try_execute().await.unwrap(); action.try_execute().await.unwrap();
action.try_revert().await.unwrap(); action.try_revert().await.unwrap();
@ -46,7 +46,7 @@ A custom [`Action`] can be created then used in a custom [`Planner`](crate::plan
```rust,no_run ```rust,no_run
use std::{error::Error, collections::HashMap}; use std::{error::Error, collections::HashMap};
use tracing::{Span, span}; use tracing::{Span, span};
use nix_installer::{ use lix_installer::{
InstallPlan, InstallPlan,
settings::{CommonSettings, InstallSettingsError}, settings::{CommonSettings, InstallSettingsError},
planner::{Planner, PlannerError}, planner::{Planner, PlannerError},
@ -152,20 +152,6 @@ impl Planner for MyPlanner {
Ok(settings) Ok(settings)
} }
#[cfg(feature = "diagnostics")]
async fn diagnostic_data(&self) -> Result<nix_installer::diagnostics::DiagnosticData, PlannerError> {
Ok(nix_installer::diagnostics::DiagnosticData::new(
self.common.diagnostic_attribution.clone(),
self.common.diagnostic_endpoint.clone(),
self.typetag_name().into(),
self.configured_settings()
.await?
.into_keys()
.collect::<Vec<_>>(),
self.common.ssl_cert_file.clone(),
)?)
}
} }
# async fn custom_planner_install() -> color_eyre::Result<()> { # async fn custom_planner_install() -> color_eyre::Result<()> {
@ -329,12 +315,6 @@ impl ActionError {
pub fn action_tag(&self) -> &ActionTag { pub fn action_tag(&self) -> &ActionTag {
&self.action_tag &self.action_tag
} }
#[cfg(feature = "diagnostics")]
pub fn diagnostic(&self) -> String {
use crate::diagnostics::ErrorDiagnostic;
self.kind.diagnostic()
}
} }
impl std::fmt::Display for ActionError { impl std::fmt::Display for ActionError {
@ -493,8 +473,6 @@ pub enum ActionErrorKind {
command = .command, command = .command,
)] )]
Command { Command {
#[cfg(feature = "diagnostics")]
program: String,
command: String, command: String,
#[source] #[source]
error: std::io::Error, error: std::io::Error,
@ -511,8 +489,6 @@ pub enum ActionErrorKind {
} }
)] )]
CommandOutput { CommandOutput {
#[cfg(feature = "diagnostics")]
program: String,
command: String, command: String,
output: Output, output: Output,
}, },
@ -555,7 +531,7 @@ pub enum ActionErrorKind {
MissingRemoveUserFromGroupCommand, MissingRemoveUserFromGroupCommand,
#[error("\ #[error("\
Could not detect systemd; you may be able to get up and running without systemd with `nix-installer install linux --init none`.\n\ 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.\ See https://git.lix.systems/lix-project/lix-installer#without-systemd-linux-only for documentation on usage and drawbacks.\
")] ")]
SystemdMissing, SystemdMissing,
#[error("`{command}` failed, message: {message}")] #[error("`{command}` failed, message: {message}")]
@ -575,16 +551,12 @@ pub enum ActionErrorKind {
impl ActionErrorKind { impl ActionErrorKind {
pub fn command(command: &tokio::process::Command, error: std::io::Error) -> Self { pub fn command(command: &tokio::process::Command, error: std::io::Error) -> Self {
Self::Command { Self::Command {
#[cfg(feature = "diagnostics")]
program: command.as_std().get_program().to_string_lossy().into(),
command: format!("{:?}", command.as_std()), command: format!("{:?}", command.as_std()),
error, error,
} }
} }
pub fn command_output(command: &tokio::process::Command, output: std::process::Output) -> Self { pub fn command_output(command: &tokio::process::Command, output: std::process::Output) -> Self {
Self::CommandOutput { Self::CommandOutput {
#[cfg(feature = "diagnostics")]
program: command.as_std().get_program().to_string_lossy().into(),
command: format!("{:?}", command.as_std()), command: format!("{:?}", command.as_std()),
output, output,
} }
@ -602,60 +574,3 @@ impl HasExpectedErrors for ActionErrorKind {
} }
} }
} }
#[cfg(feature = "diagnostics")]
impl crate::diagnostics::ErrorDiagnostic for ActionErrorKind {
fn diagnostic(&self) -> String {
let static_str: &'static str = (self).into();
let context = match self {
Self::Child(child) => vec![child.diagnostic()],
Self::MultipleChildren(children) => {
children.iter().map(|child| child.diagnostic()).collect()
},
Self::Read(path, _)
| Self::Open(path, _)
| Self::Write(path, _)
| Self::Flush(path, _)
| Self::SetPermissions(_, path, _)
| Self::GettingMetadata(path, _)
| Self::CreateDirectory(path, _)
| Self::PathWasNotFile(path)
| Self::Remove(path, _) => {
vec![path.to_string_lossy().to_string()]
},
Self::Rename(first_path, second_path, _)
| Self::Copy(first_path, second_path, _)
| Self::Symlink(first_path, second_path, _) => {
vec![
first_path.to_string_lossy().to_string(),
second_path.to_string_lossy().to_string(),
]
},
Self::NoGroup(name) | Self::NoUser(name) => {
vec![name.clone()]
},
Self::Command {
program,
command: _,
error: _,
}
| Self::CommandOutput {
program,
command: _,
output: _,
} => {
vec![program.clone()]
},
_ => vec![],
};
format!(
"{}({})",
static_str,
context
.iter()
.map(|v| format!("\"{v}\""))
.collect::<Vec<_>>()
.join(", ")
)
}
}

View file

@ -1,7 +1,7 @@
use std::{io::IsTerminal, process::ExitCode}; use std::{io::IsTerminal, process::ExitCode};
use clap::Parser; use clap::Parser;
use nix_installer::cli::CommandExecute; use lix_installer::cli::CommandExecute;
#[tokio::main] #[tokio::main]
async fn main() -> eyre::Result<ExitCode> { async fn main() -> eyre::Result<ExitCode> {
@ -17,7 +17,7 @@ async fn main() -> eyre::Result<ExitCode> {
}) })
.install()?; .install()?;
let cli = nix_installer::cli::NixInstallerCli::parse(); let cli = lix_installer::cli::NixInstallerCli::parse();
cli.instrumentation.setup()?; cli.instrumentation.setup()?;

View file

@ -20,7 +20,7 @@ pub trait CommandExecute {
} }
/** /**
The Determinate Nix installer The Determinate Nix installer (lix variant)
A fast, friendly, and reliable tool to help you use Nix with Flakes everywhere. A fast, friendly, and reliable tool to help you use Nix with Flakes everywhere.
*/ */
@ -122,13 +122,6 @@ pub fn ensure_root() -> eyre::Result<()> {
} }
} }
#[cfg(feature = "diagnostics")]
if is_ci::cached() {
// Normally `sudo` would erase those envs, so we detect and pass that along specifically to avoid having to pass around
// a bunch of environment variables
env_list.push("NIX_INSTALLER_CI=1".to_string());
}
if !env_list.is_empty() { if !env_list.is_empty() {
arg_vec_cstring arg_vec_cstring
.push(CString::new("env").wrap_err("Building a `env` argument for `sudo`")?); .push(CString::new("env").wrap_err("Building a `env` argument for `sudo`")?);

View file

@ -25,13 +25,13 @@ use color_eyre::{
use owo_colors::OwoColorize; use owo_colors::OwoColorize;
const EXISTING_INCOMPATIBLE_PLAN_GUIDANCE: &str = "\ const EXISTING_INCOMPATIBLE_PLAN_GUIDANCE: &str = "\
If you are trying to upgrade Nix, try running `sudo -i nix upgrade-nix` instead.\n\ If you are trying to upgrade Lix, try running `sudo -i nix upgrade-nix` instead.\n\
If you are trying to install Nix over an existing install (from an incompatible `nix-installer` install), try running `/nix/nix-installer uninstall` then try to install again.\n\ If you are trying to install Lix over an existing install (from an incompatible `nix-installer` install), try running `/nix/nix-installer uninstall` then try to install again.\n\
If you are using `nix-installer` in an automated curing process and seeing this message, consider pinning the version you use via https://github.com/DeterminateSystems/nix-installer#accessing-other-versions.\ If you are using `lix-installer` in an automated curing process and seeing this message, consider pinning the version you use via https://git.lix.systems/lix-project/lix-installer#accessing-other-versions.\
"; ";
/** /**
Install Nix using a planner Install Lix-Nix using a planner
By default, an appropriate planner is heuristically determined based on the system. By default, an appropriate planner is heuristically determined based on the system.
@ -90,7 +90,7 @@ impl CommandExecute for Install {
.wrap_err("Reading plan")?; .wrap_err("Reading plan")?;
Some( Some(
serde_json::from_str(&install_plan_string).wrap_err_with(|| { serde_json::from_str(&install_plan_string).wrap_err_with(|| {
format!("Unable to parse existing receipt `{RECEIPT_LOCATION}`, it may be from an incompatible version of `nix-installer`. Try running `/nix/nix-installer uninstall`, then installing again.") format!("Unable to parse existing receipt `{RECEIPT_LOCATION}`, it may be from an incompatible version of `nix-installer` or `lix-installer`. Try running `/nix/nix-installer uninstall`, then installing again.")
})?, })?,
) )
}, },
@ -99,7 +99,7 @@ impl CommandExecute for Install {
let uninstall_command = match Path::new("/nix/nix-installer").exists() { let uninstall_command = match Path::new("/nix/nix-installer").exists() {
true => "/nix/nix-installer uninstall".into(), true => "/nix/nix-installer uninstall".into(),
false => format!("curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix/tag/v{} | sh -s -- uninstall", env!("CARGO_PKG_VERSION")), false => format!("curl --proto '=https' --tlsv1.2 -sSf -L https://install.lix.systems/lix/tag/v{} | sh -s -- uninstall", env!("CARGO_PKG_VERSION")),
}; };
let mut install_plan = match (planner, plan) { let mut install_plan = match (planner, plan) {

View file

@ -129,7 +129,7 @@ impl CommandExecute for Uninstall {
format!( format!(
"\ "\
Unable to parse plan, this plan was created by `nix-installer` version `{plan_version}`, this is `nix-installer` version `{current_version}`\n\ Unable to parse plan, this plan was created by `nix-installer` version `{plan_version}`, this is `nix-installer` version `{current_version}`\n\
To uninstall, either run `/nix/nix-installer uninstall` or `curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix/tag/v{plan_version} | sh -s -- uninstall`\ To uninstall, either run `/nix/nix-installer uninstall` or `curl --proto '=https' --tlsv1.2 -sSf -L https://install.lix.systems/lix/tag/v{plan_version} | sh -s -- uninstall`\
").red().to_string() ").red().to_string()
}); });
}, },
@ -147,7 +147,7 @@ impl CommandExecute for Uninstall {
\n\ \n\
Found existing plan in `{RECEIPT_LOCATION}` which was created by a version incompatible `nix-installer`.\n\ Found existing plan in `{RECEIPT_LOCATION}` which was created by a version incompatible `nix-installer`.\n\
\n \n
To uninstall, either run `/nix/nix-installer uninstall` or `curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix/tag/v${version} | sh -s -- uninstall`\n\ To uninstall, either run `/nix/nix-installer uninstall` or `curl --proto '=https' --tlsv1.2 -sSf -L https://install.lix.systems/lix/tag/v${version} | sh -s -- uninstall`\n\
\n\ \n\
").red() ").red()
); );

View file

@ -1,277 +0,0 @@
/*! Diagnostic reporting functionality
When enabled with the `diagnostics` feature (default) this module provides automated install success/failure reporting to an endpoint.
That endpoint can be a URL such as `https://our.project.org/nix-installer/diagnostics` or `file:///home/$USER/diagnostic.json` which receives a [`DiagnosticReport`] in JSON format.
*/
use std::{path::PathBuf, time::Duration};
use os_release::OsRelease;
use reqwest::Url;
use crate::{
action::ActionError, parse_ssl_cert, planner::PlannerError, settings::InstallSettingsError,
CertificateError, NixInstallerError,
};
/// The static of an action attempt
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub enum DiagnosticStatus {
Cancelled,
Success,
Pending,
Failure,
}
/// The action attempted
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, Copy)]
pub enum DiagnosticAction {
Install,
Uninstall,
}
/// A report sent to an endpoint
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct DiagnosticReport {
pub attribution: Option<String>,
pub version: String,
pub planner: String,
pub configured_settings: Vec<String>,
pub os_name: String,
pub os_version: String,
pub triple: String,
pub is_ci: bool,
pub action: DiagnosticAction,
pub status: DiagnosticStatus,
/// Generally this includes the [`strum::IntoStaticStr`] representation of the error, we take special care not to include parameters of the error (which may include secrets)
pub failure_chain: Option<Vec<String>>,
}
/// A preparation of data to be sent to the `endpoint`.
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, Default)]
pub struct DiagnosticData {
attribution: Option<String>,
version: String,
planner: String,
configured_settings: Vec<String>,
os_name: String,
os_version: String,
triple: String,
is_ci: bool,
endpoint: Option<Url>,
ssl_cert_file: Option<PathBuf>,
/// Generally this includes the [`strum::IntoStaticStr`] representation of the error, we take special care not to include parameters of the error (which may include secrets)
failure_chain: Option<Vec<String>>,
}
impl DiagnosticData {
pub fn new(
attribution: Option<String>,
endpoint: Option<String>,
planner: String,
configured_settings: Vec<String>,
ssl_cert_file: Option<PathBuf>,
) -> Result<Self, DiagnosticError> {
let endpoint = match endpoint {
Some(endpoint) => diagnostic_endpoint_parser(&endpoint)?,
None => None,
};
let (os_name, os_version) = match OsRelease::new() {
Ok(os_release) => (os_release.name, os_release.version),
Err(_) => ("unknown".into(), "unknown".into()),
};
let is_ci = is_ci::cached()
|| std::env::var("NIX_INSTALLER_CI").unwrap_or_else(|_| "0".into()) == "1";
Ok(Self {
attribution,
endpoint,
version: env!("CARGO_PKG_VERSION").into(),
planner,
configured_settings,
os_name,
os_version,
triple: target_lexicon::HOST.to_string(),
is_ci,
ssl_cert_file: ssl_cert_file.and_then(|v| v.canonicalize().ok()),
failure_chain: None,
})
}
pub fn failure(mut self, err: &NixInstallerError) -> Self {
let mut failure_chain = vec![];
let diagnostic = err.diagnostic();
failure_chain.push(diagnostic);
let mut walker: &dyn std::error::Error = &err;
while let Some(source) = walker.source() {
if let Some(downcasted) = source.downcast_ref::<ActionError>() {
let downcasted_diagnostic = downcasted.kind().diagnostic();
failure_chain.push(downcasted_diagnostic);
}
if let Some(downcasted) = source.downcast_ref::<Box<ActionError>>() {
let downcasted_diagnostic = downcasted.kind().diagnostic();
failure_chain.push(downcasted_diagnostic);
}
if let Some(downcasted) = source.downcast_ref::<PlannerError>() {
let downcasted_diagnostic = downcasted.diagnostic();
failure_chain.push(downcasted_diagnostic);
}
if let Some(downcasted) = source.downcast_ref::<InstallSettingsError>() {
let downcasted_diagnostic = downcasted.diagnostic();
failure_chain.push(downcasted_diagnostic);
}
if let Some(downcasted) = source.downcast_ref::<DiagnosticError>() {
let downcasted_diagnostic = downcasted.diagnostic();
failure_chain.push(downcasted_diagnostic);
}
walker = source;
}
self.failure_chain = Some(failure_chain);
self
}
pub fn report(&self, action: DiagnosticAction, status: DiagnosticStatus) -> DiagnosticReport {
let Self {
attribution,
version,
planner,
configured_settings,
os_name,
os_version,
triple,
is_ci,
endpoint: _,
ssl_cert_file: _,
failure_chain,
} = self;
DiagnosticReport {
attribution: attribution.clone(),
version: version.clone(),
planner: planner.clone(),
configured_settings: configured_settings.clone(),
os_name: os_name.clone(),
os_version: os_version.clone(),
triple: triple.clone(),
is_ci: *is_ci,
action,
status,
failure_chain: failure_chain.clone(),
}
}
#[tracing::instrument(level = "debug", skip_all)]
pub async fn send(
self,
action: DiagnosticAction,
status: DiagnosticStatus,
) -> Result<(), DiagnosticError> {
let serialized = serde_json::to_string_pretty(&self.report(action, status))?;
let endpoint = match self.endpoint {
Some(endpoint) => endpoint,
None => return Ok(()),
};
match endpoint.scheme() {
"https" | "http" => {
tracing::debug!("Sending diagnostic to `{endpoint}`");
let mut buildable_client = reqwest::Client::builder();
if let Some(ssl_cert_file) = &self.ssl_cert_file {
let ssl_cert = parse_ssl_cert(ssl_cert_file).await.ok();
if let Some(ssl_cert) = ssl_cert {
buildable_client = buildable_client.add_root_certificate(ssl_cert);
}
}
let client = buildable_client.build().map_err(DiagnosticError::Reqwest)?;
let res = client
.post(endpoint.clone())
.body(serialized)
.header("Content-Type", "application/json")
.timeout(Duration::from_millis(3000))
.send()
.await;
if let Err(_err) = res {
tracing::info!("Failed to send diagnostic to `{endpoint}`, continuing")
}
},
"file" => {
let path = endpoint.path();
tracing::debug!("Writing diagnostic to `{path}`");
let res = tokio::fs::write(path, serialized).await;
if let Err(_err) = res {
tracing::info!("Failed to send diagnostic to `{path}`, continuing")
}
},
_ => return Err(DiagnosticError::UnknownUrlScheme),
};
Ok(())
}
}
#[non_exhaustive]
#[derive(thiserror::Error, Debug, strum::IntoStaticStr)]
pub enum DiagnosticError {
#[error("Unknown url scheme")]
UnknownUrlScheme,
#[error("Request error")]
Reqwest(
#[from]
#[source]
reqwest::Error,
),
/// Parsing URL
#[error("Parsing URL")]
Parse(
#[source]
#[from]
url::ParseError,
),
#[error("Write path `{0}`")]
Write(std::path::PathBuf, #[source] std::io::Error),
#[error("Serializing receipt")]
Serializing(
#[from]
#[source]
serde_json::Error,
),
#[error(transparent)]
Certificate(#[from] CertificateError),
}
pub trait ErrorDiagnostic {
fn diagnostic(&self) -> String;
}
impl ErrorDiagnostic for DiagnosticError {
fn diagnostic(&self) -> String {
let static_str: &'static str = (self).into();
static_str.to_string()
}
}
pub fn diagnostic_endpoint_parser(input: &str) -> Result<Option<Url>, DiagnosticError> {
match Url::parse(input) {
Ok(v) => match v.scheme() {
"https" | "http" | "file" => Ok(Some(v)),
_ => Err(DiagnosticError::UnknownUrlScheme),
},
Err(url::ParseError::RelativeUrlWithoutBase) => {
match Url::parse(&format!("file://{input}")) {
Ok(v) => Ok(Some(v)),
Err(file_error) => Err(file_error)?,
}
},
Err(url_error) => Err(url_error)?,
}
}
pub fn diagnostic_endpoint_validator(input: &str) -> Result<String, DiagnosticError> {
let _ = diagnostic_endpoint_parser(input)?;
Ok(input.to_string())
}

View file

@ -74,14 +74,6 @@ pub enum NixInstallerError {
InstallSettingsError, InstallSettingsError,
), ),
#[cfg(feature = "diagnostics")]
/// Diagnostic error
#[error("Diagnostic error")]
Diagnostic(
#[from]
#[source]
crate::diagnostics::DiagnosticError,
),
/// Could not parse the value as a version requirement in order to ensure it's compatible /// Could not parse the value as a version requirement in order to ensure it's compatible
#[error("Could not parse `{0}` as a version requirement in order to ensure it's compatible")] #[error("Could not parse `{0}` as a version requirement in order to ensure it's compatible")]
InvalidVersionRequirement(String, semver::Error), InvalidVersionRequirement(String, semver::Error),
@ -115,36 +107,6 @@ impl HasExpectedErrors for NixInstallerError {
this @ NixInstallerError::IncompatibleVersion { binary: _, plan: _ } => { this @ NixInstallerError::IncompatibleVersion { binary: _, plan: _ } => {
Some(Box::new(this)) Some(Box::new(this))
}, },
#[cfg(feature = "diagnostics")]
NixInstallerError::Diagnostic(_) => None,
} }
} }
} }
#[cfg(feature = "diagnostics")]
impl crate::diagnostics::ErrorDiagnostic for NixInstallerError {
fn diagnostic(&self) -> String {
let static_str: &'static str = (self).into();
let context = match self {
Self::SelfTest(self_tests) => self_tests
.iter()
.map(|self_test| self_test.diagnostic())
.collect::<Vec<_>>(),
Self::Action(action_error) => vec![action_error.diagnostic()],
Self::ActionRevert(action_errors) => action_errors
.iter()
.map(|action_error| action_error.diagnostic())
.collect(),
_ => vec![],
};
format!(
"{}({})",
static_str,
context
.iter()
.map(|v| format!("\"{v}\""))
.collect::<Vec<_>>()
.join(", ")
)
}
}

View file

@ -1,6 +1,6 @@
/*! The Determinate [Nix](https://github.com/NixOS/nix) Installer /*! The [Lix](https://lix.systems) Installer
`nix-installer` breaks down into three main concepts: `lix-installer` breaks down into three main concepts:
* [`Action`]: An executable or revertable step, possibly orchestrating sub-[`Action`]s using things * [`Action`]: An executable or revertable step, possibly orchestrating sub-[`Action`]s using things
like [`JoinSet`](tokio::task::JoinSet)s. like [`JoinSet`](tokio::task::JoinSet)s.
@ -10,12 +10,12 @@
It is possible to create custom [`Action`]s and [`Planner`](planner::Planner)s to suit the needs of your project, team, or organization. It is possible to create custom [`Action`]s and [`Planner`](planner::Planner)s to suit the needs of your project, team, or organization.
In the simplest case, `nix-installer` can be asked to determine a default plan for the platform and install In the simplest case, `lix-installer` can be asked to determine a default plan for the platform and install
it, uninstalling if anything goes wrong: it, uninstalling if anything goes wrong:
```rust,no_run ```rust,no_run
use std::error::Error; use std::error::Error;
use nix_installer::InstallPlan; use lix_installer::InstallPlan;
# async fn default_install() -> color_eyre::Result<()> { # async fn default_install() -> color_eyre::Result<()> {
let mut plan = InstallPlan::default().await?; let mut plan = InstallPlan::default().await?;
@ -38,7 +38,7 @@ Sometimes choosing a specific planner is desired:
```rust,no_run ```rust,no_run
use std::error::Error; use std::error::Error;
use nix_installer::{InstallPlan, planner::Planner}; use lix_installer::{InstallPlan, planner::Planner};
# async fn chosen_planner_install() -> color_eyre::Result<()> { # async fn chosen_planner_install() -> color_eyre::Result<()> {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
@ -72,8 +72,6 @@ match plan.install(None).await {
pub mod action; pub mod action;
#[cfg(feature = "cli")] #[cfg(feature = "cli")]
pub mod cli; pub mod cli;
#[cfg(feature = "diagnostics")]
pub mod diagnostics;
mod error; mod error;
mod os; mod os;
mod plan; mod plan;

View file

@ -22,18 +22,12 @@ pub struct InstallPlan {
pub(crate) actions: Vec<StatefulAction<Box<dyn Action>>>, pub(crate) actions: Vec<StatefulAction<Box<dyn Action>>>,
pub(crate) planner: Box<dyn Planner>, pub(crate) planner: Box<dyn Planner>,
#[cfg(feature = "diagnostics")]
pub(crate) diagnostic_data: Option<crate::diagnostics::DiagnosticData>,
} }
impl InstallPlan { impl InstallPlan {
pub async fn default() -> Result<Self, NixInstallerError> { pub async fn default() -> Result<Self, NixInstallerError> {
let planner = BuiltinPlanner::default().await?; let planner = BuiltinPlanner::default().await?;
#[cfg(feature = "diagnostics")]
let diagnostic_data = Some(planner.diagnostic_data().await?);
let planner = planner.boxed(); let planner = planner.boxed();
let actions = planner.plan().await?; let actions = planner.plan().await?;
@ -41,8 +35,6 @@ impl InstallPlan {
planner, planner,
actions, actions,
version: current_version()?, version: current_version()?,
#[cfg(feature = "diagnostics")]
diagnostic_data,
}) })
} }
@ -50,9 +42,6 @@ impl InstallPlan {
where where
P: Planner + 'static, P: Planner + 'static,
{ {
#[cfg(feature = "diagnostics")]
let diagnostic_data = Some(planner.diagnostic_data().await?);
// Some Action `plan` calls may fail if we don't do these checks // Some Action `plan` calls may fail if we don't do these checks
planner.pre_install_check().await?; planner.pre_install_check().await?;
@ -61,8 +50,6 @@ impl InstallPlan {
planner: planner.boxed(), planner: planner.boxed(),
actions, actions,
version: current_version()?, version: current_version()?,
#[cfg(feature = "diagnostics")]
diagnostic_data,
}) })
} }
@ -101,7 +88,7 @@ impl InstallPlan {
let buf = format!( let buf = format!(
"\ "\
Nix install plan (v{version})\n\ Lix install plan (v{version})\n\
Planner: {planner}{maybe_default_setting_note}\n\ Planner: {planner}{maybe_default_setting_note}\n\
\n\ \n\
{maybe_plan_settings}\ {maybe_plan_settings}\
@ -173,17 +160,6 @@ impl InstallPlan {
tracing::error!("Error saving receipt: {:?}", err); tracing::error!("Error saving receipt: {:?}", err);
} }
#[cfg(feature = "diagnostics")]
if let Some(diagnostic_data) = &self.diagnostic_data {
diagnostic_data
.clone()
.send(
crate::diagnostics::DiagnosticAction::Install,
crate::diagnostics::DiagnosticStatus::Cancelled,
)
.await?;
}
return Err(NixInstallerError::Cancelled); return Err(NixInstallerError::Cancelled);
} }
} }
@ -194,17 +170,6 @@ impl InstallPlan {
tracing::error!("Error saving receipt: {:?}", err); tracing::error!("Error saving receipt: {:?}", err);
} }
let err = NixInstallerError::Action(err); let err = NixInstallerError::Action(err);
#[cfg(feature = "diagnostics")]
if let Some(diagnostic_data) = &self.diagnostic_data {
diagnostic_data
.clone()
.failure(&err)
.send(
crate::diagnostics::DiagnosticAction::Install,
crate::diagnostics::DiagnosticStatus::Failure,
)
.await?;
}
return Err(err); return Err(err);
} }
@ -216,30 +181,7 @@ impl InstallPlan {
.await .await
.map_err(NixInstallerError::SelfTest) .map_err(NixInstallerError::SelfTest)
{ {
#[cfg(feature = "diagnostics")]
if let Some(diagnostic_data) = &self.diagnostic_data {
diagnostic_data
.clone()
.failure(&err)
.send(
crate::diagnostics::DiagnosticAction::Install,
crate::diagnostics::DiagnosticStatus::Failure,
)
.await?;
}
tracing::warn!("{err:?}") tracing::warn!("{err:?}")
} else {
#[cfg(feature = "diagnostics")]
if let Some(diagnostic_data) = &self.diagnostic_data {
diagnostic_data
.clone()
.send(
crate::diagnostics::DiagnosticAction::Install,
crate::diagnostics::DiagnosticStatus::Success,
)
.await?;
}
} }
Ok(()) Ok(())
@ -270,7 +212,7 @@ impl InstallPlan {
let buf = format!( let buf = format!(
"\ "\
Nix uninstall plan (v{version})\n\ Lix uninstall plan (v{version})\n\
\n\ \n\
Planner: {planner}{maybe_default_setting_note}\n\ Planner: {planner}{maybe_default_setting_note}\n\
\n\ \n\
@ -345,16 +287,6 @@ impl InstallPlan {
tracing::error!("Error saving receipt: {:?}", err); tracing::error!("Error saving receipt: {:?}", err);
} }
#[cfg(feature = "diagnostics")]
if let Some(diagnostic_data) = &self.diagnostic_data {
diagnostic_data
.clone()
.send(
crate::diagnostics::DiagnosticAction::Uninstall,
crate::diagnostics::DiagnosticStatus::Cancelled,
)
.await?;
}
return Err(NixInstallerError::Cancelled); return Err(NixInstallerError::Cancelled);
} }
} }
@ -366,32 +298,9 @@ impl InstallPlan {
} }
if errors.is_empty() { if errors.is_empty() {
#[cfg(feature = "diagnostics")]
if let Some(diagnostic_data) = &self.diagnostic_data {
diagnostic_data
.clone()
.send(
crate::diagnostics::DiagnosticAction::Uninstall,
crate::diagnostics::DiagnosticStatus::Success,
)
.await?;
}
Ok(()) Ok(())
} else { } else {
let error = NixInstallerError::ActionRevert(errors); let error = NixInstallerError::ActionRevert(errors);
#[cfg(feature = "diagnostics")]
if let Some(diagnostic_data) = &self.diagnostic_data {
diagnostic_data
.clone()
.failure(&error)
.send(
crate::diagnostics::DiagnosticAction::Uninstall,
crate::diagnostics::DiagnosticStatus::Failure,
)
.await?;
}
Err(error) Err(error)
} }
} }

View file

@ -126,19 +126,6 @@ impl Planner for Linux {
Ok(settings) Ok(settings)
} }
#[cfg(feature = "diagnostics")]
async fn diagnostic_data(&self) -> Result<crate::diagnostics::DiagnosticData, PlannerError> {
Ok(crate::diagnostics::DiagnosticData::new(
self.settings.diagnostic_attribution.clone(),
self.settings.diagnostic_endpoint.clone(),
self.typetag_name().into(),
self.configured_settings()
.await?
.into_keys()
.collect::<Vec<_>>(),
self.settings.ssl_cert_file.clone(),
)?)
}
async fn pre_uninstall_check(&self) -> Result<(), PlannerError> { async fn pre_uninstall_check(&self) -> Result<(), PlannerError> {
check_not_wsl1()?; check_not_wsl1()?;

View file

@ -238,20 +238,6 @@ impl Planner for Macos {
Ok(settings) Ok(settings)
} }
#[cfg(feature = "diagnostics")]
async fn diagnostic_data(&self) -> Result<crate::diagnostics::DiagnosticData, PlannerError> {
Ok(crate::diagnostics::DiagnosticData::new(
self.settings.diagnostic_attribution.clone(),
self.settings.diagnostic_endpoint.clone(),
self.typetag_name().into(),
self.configured_settings()
.await?
.into_keys()
.collect::<Vec<_>>(),
self.settings.ssl_cert_file.clone(),
)?)
}
async fn pre_uninstall_check(&self) -> Result<(), PlannerError> { async fn pre_uninstall_check(&self) -> Result<(), PlannerError> {
check_nix_darwin_not_installed().await?; check_nix_darwin_not_installed().await?;

View file

@ -12,7 +12,7 @@ A custom [`Planner`] can be created:
```rust,no_run ```rust,no_run
use std::{error::Error, collections::HashMap}; use std::{error::Error, collections::HashMap};
use nix_installer::{ use lix_installer::{
InstallPlan, InstallPlan,
settings::{CommonSettings, InstallSettingsError}, settings::{CommonSettings, InstallSettingsError},
planner::{Planner, PlannerError}, planner::{Planner, PlannerError},
@ -69,19 +69,6 @@ impl Planner for MyPlanner {
Ok(settings) Ok(settings)
} }
#[cfg(feature = "diagnostics")]
async fn diagnostic_data(&self) -> Result<nix_installer::diagnostics::DiagnosticData, PlannerError> {
Ok(nix_installer::diagnostics::DiagnosticData::new(
self.common.diagnostic_attribution.clone(),
self.common.diagnostic_endpoint.clone(),
self.typetag_name().into(),
self.configured_settings()
.await?
.into_keys()
.collect::<Vec<_>>(),
self.common.ssl_cert_file.clone(),
)?)
}
} }
# async fn custom_planner_install() -> color_eyre::Result<()> { # async fn custom_planner_install() -> color_eyre::Result<()> {
@ -154,9 +141,6 @@ pub trait Planner: std::fmt::Debug + Send + Sync + dyn_clone::DynClone {
async fn pre_install_check(&self) -> Result<(), PlannerError> { async fn pre_install_check(&self) -> Result<(), PlannerError> {
Ok(()) Ok(())
} }
#[cfg(feature = "diagnostics")]
async fn diagnostic_data(&self) -> Result<crate::diagnostics::DiagnosticData, PlannerError>;
} }
dyn_clone::clone_trait_object!(Planner); dyn_clone::clone_trait_object!(Planner);
@ -309,21 +293,6 @@ impl BuiltinPlanner {
} }
} }
#[cfg(feature = "diagnostics")]
pub async fn diagnostic_data(
&self,
) -> Result<crate::diagnostics::DiagnosticData, PlannerError> {
match self {
#[cfg(target_os = "linux")]
BuiltinPlanner::Linux(i) => i.diagnostic_data().await,
#[cfg(target_os = "linux")]
BuiltinPlanner::SteamDeck(i) => i.diagnostic_data().await,
#[cfg(target_os = "linux")]
BuiltinPlanner::Ostree(i) => i.diagnostic_data().await,
#[cfg(target_os = "macos")]
BuiltinPlanner::Macos(i) => i.diagnostic_data().await,
}
}
} }
#[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone)] #[derive(Debug, Deserialize, Serialize, PartialEq, Eq, Clone)]
@ -392,8 +361,8 @@ impl Default for FishShellProfileLocations {
#[non_exhaustive] #[non_exhaustive]
#[derive(thiserror::Error, Debug, strum::IntoStaticStr)] #[derive(thiserror::Error, Debug, strum::IntoStaticStr)]
pub enum PlannerError { pub enum PlannerError {
/// `nix-installer` does not have a default planner for the target architecture right now /// `lix-installer` does not have a default planner for the target architecture right now
#[error("`nix-installer` does not have a default planner for the `{0}` architecture right now, pass a specific archetype")] #[error("`lix-installer` does not have a default planner for the `{0}` architecture right now, pass a specific archetype")]
UnsupportedArchitecture(target_lexicon::Triple), UnsupportedArchitecture(target_lexicon::Triple),
/// Error executing action /// Error executing action
#[error("Error executing action")] #[error("Error executing action")]
@ -433,9 +402,6 @@ pub enum PlannerError {
/// Failed to execute command /// Failed to execute command
#[error("Failed to execute command `{0}`")] #[error("Failed to execute command `{0}`")]
Command(String, #[source] std::io::Error), Command(String, #[source] std::io::Error),
#[cfg(feature = "diagnostics")]
#[error(transparent)]
Diagnostic(#[from] crate::diagnostics::DiagnosticError),
} }
impl HasExpectedErrors for PlannerError { impl HasExpectedErrors for PlannerError {
@ -465,16 +431,7 @@ impl HasExpectedErrors for PlannerError {
this @ PlannerError::NixExists => Some(Box::new(this)), this @ PlannerError::NixExists => Some(Box::new(this)),
this @ PlannerError::Wsl1 => Some(Box::new(this)), this @ PlannerError::Wsl1 => Some(Box::new(this)),
PlannerError::Command(_, _) => None, PlannerError::Command(_, _) => None,
#[cfg(feature = "diagnostics")]
PlannerError::Diagnostic(diagnostic_error) => Some(Box::new(diagnostic_error)),
} }
} }
} }
#[cfg(feature = "diagnostics")]
impl crate::diagnostics::ErrorDiagnostic for PlannerError {
fn diagnostic(&self) -> String {
let static_str: &'static str = (self).into();
static_str.to_string()
}
}

View file

@ -266,19 +266,6 @@ impl Planner for Ostree {
Ok(settings) Ok(settings)
} }
#[cfg(feature = "diagnostics")]
async fn diagnostic_data(&self) -> Result<crate::diagnostics::DiagnosticData, PlannerError> {
Ok(crate::diagnostics::DiagnosticData::new(
self.settings.diagnostic_attribution.clone(),
self.settings.diagnostic_endpoint.clone(),
self.typetag_name().into(),
self.configured_settings()
.await?
.into_keys()
.collect::<Vec<_>>(),
self.settings.ssl_cert_file.clone(),
)?)
}
async fn pre_uninstall_check(&self) -> Result<(), PlannerError> { async fn pre_uninstall_check(&self) -> Result<(), PlannerError> {
check_not_wsl1()?; check_not_wsl1()?;

View file

@ -385,20 +385,6 @@ impl Planner for SteamDeck {
Ok(settings) Ok(settings)
} }
#[cfg(feature = "diagnostics")]
async fn diagnostic_data(&self) -> Result<crate::diagnostics::DiagnosticData, PlannerError> {
Ok(crate::diagnostics::DiagnosticData::new(
self.settings.diagnostic_attribution.clone(),
self.settings.diagnostic_endpoint.clone(),
self.typetag_name().into(),
self.configured_settings()
.await?
.into_keys()
.collect::<Vec<_>>(),
self.settings.ssl_cert_file.clone(),
)?)
}
async fn pre_uninstall_check(&self) -> Result<(), PlannerError> { async fn pre_uninstall_check(&self) -> Result<(), PlannerError> {
super::linux::check_not_wsl1()?; super::linux::check_not_wsl1()?;

View file

@ -26,27 +26,6 @@ pub enum SelfTestError {
SystemTime(#[from] std::time::SystemTimeError), SystemTime(#[from] std::time::SystemTimeError),
} }
#[cfg(feature = "diagnostics")]
impl crate::diagnostics::ErrorDiagnostic for SelfTestError {
fn diagnostic(&self) -> String {
let static_str: &'static str = (self).into();
let context = match self {
Self::ShellFailed { shell, .. } => vec![shell.to_string()],
Self::Command { shell, .. } => vec![shell.to_string()],
Self::SystemTime(_) => vec![],
};
format!(
"{}({})",
static_str,
context
.iter()
.map(|v| format!("\"{v}\""))
.collect::<Vec<_>>()
.join(", ")
)
}
}
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum Shell { pub enum Shell {
Sh, Sh,

View file

@ -203,48 +203,6 @@ pub struct CommonSettings {
) )
)] )]
pub force: bool, pub force: bool,
#[cfg(feature = "diagnostics")]
/// Relate the install diagnostic to a specific value
#[cfg_attr(
feature = "cli",
clap(
long,
default_value = None,
env = "NIX_INSTALLER_DIAGNOSTIC_ATTRIBUTION",
global = true
)
)]
pub diagnostic_attribution: Option<String>,
#[cfg(feature = "diagnostics")]
/// The URL or file path for an installation diagnostic to be sent
///
/// Sample of the data sent:
///
/// {
/// "attribution": null,
/// "version": "0.4.0",
/// "planner": "linux",
/// "configured_settings": [ "modify_profile" ],
/// "os_name": "Ubuntu",
/// "os_version": "22.04.1 LTS (Jammy Jellyfish)",
/// "triple": "x86_64-unknown-linux-gnu",
/// "is_ci": false,
/// "action": "Install",
/// "status": "Success"
/// }
///
/// To disable diagnostic reporting, unset the default with `--diagnostic-endpoint ""`, or `NIX_INSTALLER_DIAGNOSTIC_ENDPOINT=""`
#[clap(
long,
env = "NIX_INSTALLER_DIAGNOSTIC_ENDPOINT",
global = true,
value_parser = crate::diagnostics::diagnostic_endpoint_validator,
num_args = 0..=1, // Required to allow `--diagnostic-endpoint` or `NIX_INSTALLER_DIAGNOSTIC_ENDPOINT=""`
default_value = "https://install.determinate.systems/nix/diagnostic"
)]
pub diagnostic_endpoint: Option<String>,
} }
impl CommonSettings { impl CommonSettings {
@ -313,10 +271,6 @@ impl CommonSettings {
extra_conf: Default::default(), extra_conf: Default::default(),
force: false, force: false,
ssl_cert_file: Default::default(), ssl_cert_file: Default::default(),
#[cfg(feature = "diagnostics")]
diagnostic_attribution: None,
#[cfg(feature = "diagnostics")]
diagnostic_endpoint: Some("https://install.determinate.systems/nix/diagnostic".into()),
}) })
} }
@ -334,10 +288,6 @@ impl CommonSettings {
extra_conf, extra_conf,
force, force,
ssl_cert_file, ssl_cert_file,
#[cfg(feature = "diagnostics")]
diagnostic_attribution: _,
#[cfg(feature = "diagnostics")]
diagnostic_endpoint,
} = self; } = self;
let mut map = HashMap::default(); let mut map = HashMap::default();
@ -373,13 +323,6 @@ impl CommonSettings {
map.insert("ssl_cert_file".into(), serde_json::to_value(ssl_cert_file)?); map.insert("ssl_cert_file".into(), serde_json::to_value(ssl_cert_file)?);
map.insert("extra_conf".into(), serde_json::to_value(extra_conf)?); map.insert("extra_conf".into(), serde_json::to_value(extra_conf)?);
map.insert("force".into(), serde_json::to_value(force)?); map.insert("force".into(), serde_json::to_value(force)?);
#[cfg(feature = "diagnostics")]
map.insert(
"diagnostic_endpoint".into(),
serde_json::to_value(diagnostic_endpoint)?,
);
Ok(map) Ok(map)
} }
} }
@ -665,14 +608,6 @@ impl clap::builder::TypedValueParser for UrlOrPathOrString {
} }
} }
#[cfg(feature = "diagnostics")]
impl crate::diagnostics::ErrorDiagnostic for InstallSettingsError {
fn diagnostic(&self) -> String {
let static_str: &'static str = (self).into();
static_str.to_string()
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{FromStr, PathBuf, Url, UrlOrPath, UrlOrPathOrString}; use super::{FromStr, PathBuf, Url, UrlOrPath, UrlOrPathOrString};

View file

@ -416,7 +416,6 @@
"ssl_cert_file": null, "ssl_cert_file": null,
"extra_conf": [], "extra_conf": [],
"force": false, "force": false,
"diagnostic_endpoint": "https://install.determinate.systems/nix/diagnostic"
}, },
"init": { "init": {
"init": "Systemd", "init": "Systemd",
@ -431,7 +430,6 @@
"os_version": "22.04.2 LTS (Jammy Jellyfish)", "os_version": "22.04.2 LTS (Jammy Jellyfish)",
"triple": "x86_64-unknown-linux-musl", "triple": "x86_64-unknown-linux-musl",
"is_ci": false, "is_ci": false,
"endpoint": "https://install.determinate.systems/nix/diagnostic",
"ssl_cert_file": null, "ssl_cert_file": null,
"failure_chain": null "failure_chain": null
} }

View file

@ -400,7 +400,6 @@
"ssl_cert_file": null, "ssl_cert_file": null,
"extra_conf": [], "extra_conf": [],
"force": false, "force": false,
"diagnostic_endpoint": "https://install.determinate.systems/nix/diagnostic"
} }
}, },
"diagnostic_data": { "diagnostic_data": {
@ -411,7 +410,6 @@
"os_version": "22.04.2 LTS (Jammy Jellyfish)", "os_version": "22.04.2 LTS (Jammy Jellyfish)",
"triple": "x86_64-unknown-linux-musl", "triple": "x86_64-unknown-linux-musl",
"is_ci": false, "is_ci": false,
"endpoint": "https://install.determinate.systems/nix/diagnostic",
"ssl_cert_file": null, "ssl_cert_file": null,
"failure_chain": null "failure_chain": null
} }

View file

@ -427,7 +427,6 @@
"ssl_cert_file": null, "ssl_cert_file": null,
"extra_conf": [], "extra_conf": [],
"force": false, "force": false,
"diagnostic_endpoint": "https://install.determinate.systems/nix/diagnostic"
}, },
"encrypt": null, "encrypt": null,
"case_sensitive": false, "case_sensitive": false,
@ -442,7 +441,6 @@
"os_version": "unknown", "os_version": "unknown",
"triple": "aarch64-apple-darwin", "triple": "aarch64-apple-darwin",
"is_ci": false, "is_ci": false,
"endpoint": "https://install.determinate.systems/nix/diagnostic",
"ssl_cert_file": null, "ssl_cert_file": null,
"failure_chain": null "failure_chain": null
} }

View file

@ -1,4 +1,4 @@
use nix_installer::InstallPlan; use lix_installer::InstallPlan;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
const LINUX: &str = include_str!("./fixtures/linux/linux.json"); const LINUX: &str = include_str!("./fixtures/linux/linux.json");

View file

@ -1,71 +0,0 @@
set -eu
DEST="$1"
GIT_ISH="$2"
DEST_INSTALL_URL="$3"
is_tag() {
if [[ "$GITHUB_REF_TYPE" == "tag" ]]; then
return 0
else
return 1
fi
}
# If the revision directory has already been created in S3 somehow, we don't want to reupload
if aws s3 ls "$AWS_BUCKET"/"$GIT_ISH"/; then
# Only exit if it's not a tag (since we're tagging a commit previously pushed to main)
if ! is_tag; then
echo "Revision $GIT_ISH was already uploaded; exiting"
exit 1
fi
fi
sudo chown $USER: -R artifacts/
mkdir "$DEST"
mkdir "$GIT_ISH"
cp nix-installer.sh "$DEST"/
cp nix-installer.sh "$GIT_ISH"/
for artifact in $(find artifacts/ -type f); do
chmod +x "$artifact"
cp "$artifact" "$DEST"/
cp "$artifact" "$GIT_ISH"/
done
sed -i "s@https://install.determinate.systems/nix@$DEST_INSTALL_URL@" "$DEST/nix-installer.sh"
sed -i "s@https://install.determinate.systems/nix@https://install.determinate.systems/nix/rev/$GIT_ISH@" "$GIT_ISH/nix-installer.sh"
if is_tag; then
cp "$DEST/nix-installer.sh" ./nix-installer.sh
fi
# If any artifact already exists in S3 and the hash is the same, we don't want to reupload
check_reupload() {
dest="$1"
for file in $(find "$dest" -type f); do
artifact_path="$dest"/"$(basename "$artifact")"
md5="$(md5sum "$artifact" | cut -d' ' -f1)"
obj="$(aws s3api head-object --bucket "$AWS_BUCKET" --key "$artifact_path" || echo '{}')"
obj_md5="$(jq -r .ETag <<<"$obj" | jq -r)" # head-object call returns ETag quoted, so `jq -r` again to unquote it
if [[ "$md5" == "$obj_md5" ]]; then
echo "Artifact $artifact was already uploaded; exiting"
# If we already uploaded to a tag, that's probably bad
is_tag && exit 1 || exit 0
fi
done
}
check_reupload "$DEST"
if ! is_tag; then
check_reupload "$GIT_ISH"
fi
aws s3 sync "$DEST"/ s3://"$AWS_BUCKET"/"$DEST"/ --acl public-read
if ! is_tag; then
aws s3 sync "$GIT_ISH"/ s3://"$AWS_BUCKET"/"$GIT_ISH"/ --acl public-read
fi