init-less install (#188)
* wip * Add dockerfile * Add readme bits * Fix logic inversion * Relax init detection error * Tidying heuristics * Fix doc tests * Mac supports start-daemon false * Get VM tests working * Add instructions * Some target_os flagging * More target flagging * Fix lints * Fixup more mac-only stuff * cfg flag examples too * Fix planner wording * More os specific lint fixing * More refinement on mac and the README * Add new CI jobs to test no-daemon * Use nix-installer-pr to point at branch * Tests with no-init * init/no-daemon are linux only * nix tests support a per-distro all attribute * Add working podman test * Expand docker tests * Add contributing notes * format * Support both podman and docker * Update contributing * Add Windows WSL test script for Ubuntu * format nix tests * More ignores to check-spelling * Add systemd based wsl test * We don't have root-only darwin * Reflect review nits * Reenable tests * Restore mac plan * Flag off os specific tests * Better cfg flagging * Remove dead comments * Rework readme to look better with new sections * Correct codeblock language * Remove some warnings
This commit is contained in:
parent
4d2e2c3911
commit
d69f335703
1
.dockerignore
Normal file
1
.dockerignore
Normal file
|
@ -0,0 +1 @@
|
|||
target
|
128
.github/workflows/ci.yml
vendored
128
.github/workflows/ci.yml
vendored
|
@ -12,7 +12,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Cache lint store (x86_64-linux)
|
||||
|
@ -36,7 +36,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Cache build store (x86_64-linux)
|
||||
|
@ -67,7 +67,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Cache build store (x86_64-linux)
|
||||
|
@ -100,7 +100,7 @@ jobs:
|
|||
cp nix-installer.sh install-root/nix-installer.sh
|
||||
mv nix-installer install-root/nix-installer-x86_64-linux
|
||||
- name: Initial install
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||
with:
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
|
@ -129,7 +129,7 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
- name: Repeated install
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||
with:
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
|
@ -184,6 +184,113 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
|
||||
run-x86_64-linux-no-init:
|
||||
name: Run x86_64 Linux (No init)
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [build-x86_64-linux, lints]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: sudo apt install fish zsh
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: nix-installer-x86_64-linux
|
||||
- name: Move & set executable
|
||||
run: |
|
||||
chmod +x ./nix-installer
|
||||
mkdir install-root
|
||||
cp nix-installer.sh install-root/nix-installer.sh
|
||||
mv nix-installer install-root/nix-installer-x86_64-linux
|
||||
- name: Initial install
|
||||
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||
with:
|
||||
init: none
|
||||
planner: linux-multi
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
log-directives: nix_installer=trace
|
||||
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=trace
|
||||
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@start-daemon-and-init
|
||||
with:
|
||||
init: none
|
||||
planner: linux-multi
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
log-directives: nix_installer=trace
|
||||
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#fortune
|
||||
sudo -i nix profile install nixpkgs#fortune
|
||||
fortune
|
||||
sudo -i nix store gc
|
||||
sudo -i nix run nixpkgs#fortune
|
||||
- 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=trace
|
||||
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-steam-deck:
|
||||
name: Run Steam Deck (mock)
|
||||
runs-on: ubuntu-22.04
|
||||
|
@ -207,7 +314,7 @@ jobs:
|
|||
sudo chmod +x /bin/steamos-readonly
|
||||
sudo useradd -m deck
|
||||
- name: Initial install
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||
with:
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
|
@ -242,7 +349,7 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
- name: Repeated install
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||
with:
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
|
@ -309,7 +416,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Runs clippy as part of the preBuild.
|
||||
|
@ -339,7 +446,7 @@ jobs:
|
|||
cp nix-installer.sh install-root/nix-installer.sh
|
||||
mv nix-installer install-root/nix-installer-x86_64-darwin
|
||||
- name: Initial install
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||
with:
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
|
@ -356,7 +463,7 @@ jobs:
|
|||
NIX_INSTALLER_LOG_DIRECTIVES: nix_installer=trace
|
||||
RUST_BACKTRACE: full
|
||||
- name: Repeated install
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||
with:
|
||||
local-root: install-root/
|
||||
logger: pretty
|
||||
|
@ -397,4 +504,3 @@ jobs:
|
|||
NIX_INSTALLER_LOGGER: pretty
|
||||
NIX_INSTALLER_LOG_DIRECTIVES: nix_installer=trace
|
||||
RUST_BACKTRACE: full
|
||||
|
120
CONTRIBUTING.md
120
CONTRIBUTING.md
|
@ -156,7 +156,7 @@ It's perfectly fine if they are manual or labor intensive, as these should be a
|
|||
|
||||
## `qemu` VM tests
|
||||
|
||||
In `nix/tests/vm-test` there exists some Nix derivations which we expose in the flake via `hydraJobs`.
|
||||
For x86_64 Linux we have some additional QEMU based tests. In `nix/tests/vm-test` there exists some Nix derivations which we expose in the flake via `hydraJobs`.
|
||||
|
||||
These should be visible in `nix flake show`:
|
||||
|
||||
|
@ -190,13 +190,13 @@ git+file:///home/ana/git/determinatesystems/nix-installer
|
|||
To run all of the currently supported tests:
|
||||
|
||||
```bash
|
||||
nix build .#hydraJobs.vm-test.all.x86_64-linux.install-default -L
|
||||
nix build .#hydraJobs.vm-test.all.x86_64-linux.all -L
|
||||
```
|
||||
|
||||
To run a specific distribution listed in the `nix flake show` output:
|
||||
|
||||
```bash
|
||||
nix build .#hydraJobs.vm-test.rhel-v7.x86_64-linux.install-default -L
|
||||
nix build .#hydraJobs.vm-test.rhel-v7.x86_64-linux.all -L
|
||||
```
|
||||
|
||||
For PR review, you can also test arbitrary branches or checkouts like so:
|
||||
|
@ -238,6 +238,120 @@ installer-test-rhel-v7-install-default> Formatting './disk.qcow2', fmt=qcow2 clu
|
|||
|
||||
</details>
|
||||
|
||||
## Container tests
|
||||
|
||||
|
||||
For x86_64 Linux we have some additional container tests. In `nix/tests/container-test` there exists some Nix derivations which we expose in the flake via `hydraJobs`.
|
||||
|
||||
These should be visible in `nix flake show`:
|
||||
|
||||
```
|
||||
❯ nix flake show
|
||||
warning: Git tree '/home/ana/git/determinatesystems/nix-installer' is dirty
|
||||
git+file:///home/ana/git/determinatesystems/nix-installer
|
||||
# ...
|
||||
├───hydraJobs
|
||||
│ ├───container-test
|
||||
│ │ ├───all
|
||||
│ │ │ └───x86_64-linux
|
||||
│ │ │ ├───all: derivation 'all'
|
||||
│ │ │ ├───docker: derivation 'all'
|
||||
│ │ │ └───podman: derivation 'all'
|
||||
│ │ ├───ubuntu-v18_04
|
||||
│ │ │ └───x86_64-linux
|
||||
│ │ │ ├───all: derivation 'all'
|
||||
│ │ │ ├───docker: derivation 'vm-test-run-container-test-ubuntu-v18_04'
|
||||
│ │ │ └───podman: derivation 'vm-test-run-container-test-ubuntu-v18_04'
|
||||
│ │ ├───ubuntu-v20_04
|
||||
│ │ │ └───x86_64-linux
|
||||
│ │ │ ├───all: derivation 'all'
|
||||
│ │ │ ├───docker: derivation 'vm-test-run-container-test-ubuntu-v20_04'
|
||||
│ │ │ └───podman: derivation 'vm-test-run-container-test-ubuntu-v20_04'
|
||||
│ │ └───ubuntu-v22_04
|
||||
│ │ └───x86_64-linux
|
||||
│ │ ├───all: derivation 'all'
|
||||
│ │ ├───docker: derivation 'vm-test-run-container-test-ubuntu-v22_04'
|
||||
│ │ └───podman: derivation 'vm-test-run-container-test-ubuntu-v22_04'
|
||||
```
|
||||
|
||||
To run all of the currently supported tests:
|
||||
|
||||
```bash
|
||||
nix build .#hydraJobs.container-test.all.x86_64-linux.all -L
|
||||
```
|
||||
|
||||
To run a specific distribution listed in the `nix flake show` output:
|
||||
|
||||
```bash
|
||||
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>
|
||||
<summary><strong>Adding a distro?</strong></summary>
|
||||
|
||||
Notice how `ubuntu-v20_02` has a `v20`, not just `20`? That's so the test output shows correctly, as Nix will interpret the first `-\d` (eg `-20`, `-123213`) as a version, and not show it in the output.
|
||||
|
||||
Using `v20` instead turns:
|
||||
|
||||
```
|
||||
# ...
|
||||
vm-test-run-container-test-ubuntu> machine # [ 23.385182] dhcpcd[670]: vethae56f366: deleting address fe80::c036:c8ff:fe04:5832
|
||||
vm-test-run-container-test-ubuntu> machine # this derivation will be built:
|
||||
vm-test-run-container-test-ubuntu> machine # /nix/store/9qb0l9n1gsmcyynfmndnq3qpmlvq8rln-foo.drv
|
||||
vm-test-run-container-test-ubuntu> machine # [ 23.424605] dhcpcd[670]: vethae56f366: removing interface
|
||||
vm-test-run-container-test-ubuntu> machine # building '/nix/store/9qb0l9n1gsmcyynfmndnq3qpmlvq8rln-foo.drv'...
|
||||
vm-test-run-container-test-ubuntu> machine # [ 23.371066] systemd[1]: crun-buildah-buildah1810857047.scope: Deactivated successfully.
|
||||
# ...
|
||||
```
|
||||
|
||||
Into this:
|
||||
|
||||
```
|
||||
# ...
|
||||
vm-test-run-container-test-ubuntu-v18_04> machine # [ 23.385182] dhcpcd[670]: vethae56f366: deleting address fe80::c036:c8ff:fe04:5832
|
||||
vm-test-run-container-test-ubuntu-v20_04> machine # this derivation will be built:
|
||||
vm-test-run-container-test-ubuntu-v20_04> machine # /nix/store/9qb0l9n1gsmcyynfmndnq3qpmlvq8rln-foo.drv
|
||||
vm-test-run-container-test-ubuntu-v18_04> machine # [ 23.424605] dhcpcd[670]: vethae56f366: removing interface
|
||||
vm-test-run-container-test-ubuntu-v20_04> machine # building '/nix/store/9qb0l9n1gsmcyynfmndnq3qpmlvq8rln-foo.drv'...
|
||||
vm-test-run-container-test-ubuntu-v20_04> machine # [ 23.371066] systemd[1]: crun-buildah-buildah1810857047.scope: Deactivated successfully.
|
||||
# ...
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## WSL tests
|
||||
|
||||
On a Windows Machine with WSL2 enabled (and updated to [support systemd](https://ubuntu.com/blog/ubuntu-wsl-enable-systemd)) you can test using WSL the scripts in `tests/windows`:
|
||||
|
||||
```powershell
|
||||
.\tests\windows\test-wsl.ps1
|
||||
.\tests\windows\test-wsl.ps1 -Systemd
|
||||
```
|
||||
|
||||
If something breaks you may need to unregister the test WSL instance. First, look for the distro prefixed with `nix-installer-test`:
|
||||
|
||||
```powershell
|
||||
$ wsl --list
|
||||
Windows Subsystem for Linux Distributions:
|
||||
Ubuntu (Default)
|
||||
nix-installer-test-ubuntu-jammy
|
||||
```
|
||||
|
||||
Then delete it:
|
||||
|
||||
```powershell
|
||||
wsl --unregister nix-installer-test-ubuntu-jammy
|
||||
```
|
||||
|
||||
You can also remove your `$HOME/nix-installer-wsl-tests-temp` folder whenever you wish.
|
||||
|
||||
|
||||
## Testing the `action.yml`
|
||||
|
||||
The `action.yml` is used directly in the CI process, so it is automatically tested for most changes.
|
||||
|
|
121
README.md
121
README.md
|
@ -16,12 +16,11 @@ curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix
|
|||
|
||||
Current and planned support:
|
||||
|
||||
* [x] Multi-user Linux (aarch64 and x86_64) with systemd init, no SELinux
|
||||
* [x] Multi-user MacOS (aarch64 and x86_64)
|
||||
+ Note: User deletion is currently unimplemented, you need to use a user with a secure token and `dscl . -delete /Users/_nixbuild*` where `*` is each user number.
|
||||
* [x] Valve Steam Deck
|
||||
* [ ] Multi-user Linux (aarch64 and x86_64) with systemd init & SELinux
|
||||
* [ ] Single-user Linux (aarch64 and x86_64)
|
||||
* [x] Multi-user Linux (aarch64 and x86_64) with systemd integration, no SELinux
|
||||
* [x] Root-only Linux (aarch64 and x86_64) with no init integration, no SELinux
|
||||
* [x] Multi-user MacOS (aarch64 and x86_64) with launchd integration
|
||||
* [x] SteamOS on the Valve Steam Deck
|
||||
* [ ] Multi-user Linux (aarch64 and x86_64) with systemd integration & SELinux
|
||||
* [ ] Others...
|
||||
|
||||
## Installation Differences
|
||||
|
@ -95,16 +94,16 @@ Usage: nix-installer install linux-multi [OPTIONS]
|
|||
|
||||
Options:
|
||||
# ...
|
||||
--nix-build-user-count <NIX_BUILD_USER_COUNT>
|
||||
Number of build users to create
|
||||
--nix-build-group-name <NIX_BUILD_GROUP_NAME>
|
||||
The Nix build group name
|
||||
|
||||
[env: NIX_INSTALLER_NIX_BUILD_USER_COUNT=]
|
||||
[default: 32]
|
||||
[env: NIX_INSTALLER_NIX_BUILD_GROUP_NAME=]
|
||||
[default: nixbld]
|
||||
|
||||
--nix-build-user-id-base <NIX_BUILD_USER_ID_BASE>
|
||||
The Nix build user base UID (ascending)
|
||||
--nix-build-group-id <NIX_BUILD_GROUP_ID>
|
||||
The Nix build group GID
|
||||
|
||||
[env: NIX_INSTALLER_NIX_BUILD_USER_ID_BASE=]
|
||||
[env: NIX_INSTALLER_NIX_BUILD_GROUP_ID=]
|
||||
[default: 3000]
|
||||
# ...
|
||||
```
|
||||
|
@ -112,9 +111,9 @@ Options:
|
|||
Planners can be configured via environment variable or command arguments:
|
||||
|
||||
```bash
|
||||
$ curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | NIX_BUILD_USER_COUNT=4 sh -s -- install linux-multi --nix-build-user-id-base 4000
|
||||
$ 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
|
||||
# Or...
|
||||
$ NIX_BUILD_USER_COUNT=4 ./nix-installer install linux-multi --nix-build-user-id-base 4000
|
||||
$ NIX_BUILD_GROUP_NAME=nixbuilder ./nix-installer install linux-multi --nix-build-group-id 4000
|
||||
```
|
||||
|
||||
|
||||
|
@ -145,28 +144,102 @@ jobs:
|
|||
- uses: actions/checkout@v3
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
with:
|
||||
# Allow the installed Nix to make authenticated Github requests.
|
||||
# If you skip this, you will likely get rate limited.
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Run `nix build`
|
||||
run: nix build .
|
||||
```
|
||||
|
||||
## In a container
|
||||
|
||||
## Building
|
||||
In Docker/Podman containers or WSL instances where an init (like `systemd`) is not present, pass `--init none`.
|
||||
|
||||
> When `--init none` is used, only `root` or sudoers can run Nix:
|
||||
>
|
||||
> ```bash
|
||||
> sudo -i nix run nixpkgs#hello
|
||||
> ```
|
||||
|
||||
For Docker containers (without an init):
|
||||
|
||||
```dockerfile
|
||||
# Dockerfile
|
||||
FROM ubuntu:latest
|
||||
RUN apt update -y
|
||||
RUN apt install curl -y
|
||||
COPY nix-installer /nix-installer
|
||||
RUN /nix-installer install linux-multi --init none --no-confirm
|
||||
ENV PATH="${PATH}:/nix/var/nix/profiles/default/bin"
|
||||
RUN nix run nixpkgs#hello
|
||||
```
|
||||
|
||||
Podman containers require `sandbox = false` in your `Nix.conf`.
|
||||
|
||||
For podman containers without an init:
|
||||
|
||||
```dockerfile
|
||||
# Dockerfile
|
||||
FROM ubuntu:latest
|
||||
RUN apt update -y
|
||||
RUN apt install curl -y
|
||||
COPY nix-installer /nix-installer
|
||||
RUN /nix-installer install linux-multi --extra-conf "sandbox = false" --init none --no-confirm
|
||||
ENV PATH="${PATH}:/nix/var/nix/profiles/default/bin"
|
||||
RUN nix run nixpkgs#hello
|
||||
```
|
||||
|
||||
For Podman containers with an init:
|
||||
|
||||
```dockerfile
|
||||
# Dockerfile
|
||||
FROM ubuntu:latest
|
||||
RUN apt update -y
|
||||
RUN apt install curl systemd -y
|
||||
COPY nix-installer /nix-installer
|
||||
RUN /nix-installer install linux-multi --extra-conf "sandbox = false" --no-start-daemon --no-confirm
|
||||
ENV PATH="${PATH}:/nix/var/nix/profiles/default/bin"
|
||||
RUN nix run nixpkgs#hello
|
||||
CMD [ "/usr/sbin/init" ]
|
||||
```
|
||||
|
||||
## In WSL
|
||||
|
||||
If [systemd is enabled](https://ubuntu.com/blog/ubuntu-wsl-enable-systemd) it's possible to install Nix as normal using the command at the top of this document:
|
||||
|
||||
```bash
|
||||
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
|
||||
```
|
||||
|
||||
If systemd is not enabled, pass `--init none` at the end of the command:
|
||||
|
||||
> When `--init none` is used, only `root` or sudoers can run Nix:
|
||||
>
|
||||
> ```bash
|
||||
> sudo -i nix run nixpkgs#hello
|
||||
> ```
|
||||
|
||||
|
||||
```bash
|
||||
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install --init none
|
||||
```
|
||||
|
||||
## Building a binary
|
||||
|
||||
Since you'll be using `nix-installer` to install Nix on systems without Nix, the default build is a static binary.
|
||||
|
||||
Build a portable binary on a system with Nix:
|
||||
Build a portable Linux binary on a system with Nix:
|
||||
|
||||
```bash
|
||||
nix build -L github:determinatesystems/nix-installer#nix-installer-static
|
||||
```
|
||||
|
||||
On Mac:
|
||||
|
||||
```bash
|
||||
nix build -L github:determinatesystems/nix-installer#nix-installer
|
||||
```
|
||||
|
||||
Then copy the `result/bin/nix-installer` to the machine you wish to run it on.
|
||||
|
||||
You can also add `nix-installer` to your system without having Nix:
|
||||
You can also add `nix-installer` to a system without Nix via `cargo`:
|
||||
|
||||
```bash
|
||||
RUSTFLAGS="--cfg tokio_unstable" cargo install nix-installer
|
||||
|
@ -188,7 +261,7 @@ cargo add nix-installer
|
|||
|
||||
> **Building a CLI?** Check out the `cli` feature flag for `clap` integration.
|
||||
|
||||
You'll also need to edit your `.cargo/config.toml` to use `tokio_unstable`:
|
||||
You'll also need to edit your `.cargo/config.toml` to use `tokio_unstable` as we utilize [Tokio's process groups](https://docs.rs/tokio/1.24.1/tokio/process/struct.Command.html#method.process_group), which wrap stable `std` APIs, but are unstable due to it requiring an MSRV bump:
|
||||
|
||||
```toml
|
||||
# .cargo/config.toml
|
||||
|
@ -208,3 +281,5 @@ Documentation is also available via `nix` build:
|
|||
nix build github:DeterminateSystems/nix-installer#nix-installer.doc
|
||||
firefox result-doc/nix-installer/index.html
|
||||
```
|
||||
|
||||
|
||||
|
|
|
@ -182,6 +182,10 @@
|
|||
inherit forSystem;
|
||||
inherit (nix.hydraJobs) binaryTarball;
|
||||
};
|
||||
container-test = import ./nix/tests/container-test {
|
||||
inherit forSystem;
|
||||
inherit (nix.hydraJobs) binaryTarball;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -18,8 +18,8 @@ in
|
|||
runtimeInputs = with pkgs; [ git codespell ];
|
||||
text = ''
|
||||
codespell \
|
||||
--ignore-words-list ba,sur,crate,pullrequest,pullrequests,ser \
|
||||
--skip target \
|
||||
--ignore-words-list ba,sur,crate,pullrequest,pullrequests,ser,distroname \
|
||||
--skip target,.git \
|
||||
.
|
||||
'';
|
||||
});
|
||||
|
|
100
nix/tests/container-test/default.nix
Normal file
100
nix/tests/container-test/default.nix
Normal file
|
@ -0,0 +1,100 @@
|
|||
# Largely derived from https://github.com/NixOS/nix/blob/14f7dae3e4eb0c34192d0077383a7f2a2d630129/tests/installer/default.nix
|
||||
{ forSystem, binaryTarball }:
|
||||
|
||||
let
|
||||
images = {
|
||||
|
||||
# Found via https://hub.docker.com/_/ubuntu/ under "How is the rootfs build?"
|
||||
# Jammy
|
||||
"ubuntu-v22_04" = {
|
||||
tarball = import <nix/fetchurl.nix> {
|
||||
url = "https://launchpad.net/~cloud-images-release-managers/+livefs/ubuntu/jammy/ubuntu-oci/+build/408115/+files/livecd.ubuntu-oci.rootfs.tar.gz";
|
||||
hash = "sha256-BirwSM4c+ZV1upU0yV3qa+BW9AvpBUxvZuPTeI9mA8M=";
|
||||
};
|
||||
tester = ./default/Dockerfile;
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
|
||||
# focal
|
||||
"ubuntu-v20_04" = {
|
||||
tarball = import <nix/fetchurl.nix> {
|
||||
url = "https://launchpad.net/~cloud-images-release-managers/+livefs/ubuntu/focal/ubuntu-oci/+build/408120/+files/livecd.ubuntu-oci.rootfs.tar.gz";
|
||||
hash = "sha256-iTJR+DeC5lT4PMqT/xFAFwmlC/qvslDFccDrVFLt/a8=";
|
||||
};
|
||||
tester = ./default/Dockerfile;
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
|
||||
# bionic
|
||||
"ubuntu-v18_04" = {
|
||||
tarball = import <nix/fetchurl.nix> {
|
||||
url = "https://launchpad.net/~cloud-images-release-managers/+livefs/ubuntu/bionic/ubuntu-oci/+build/408103/+files/livecd.ubuntu-oci.rootfs.tar.gz";
|
||||
hash = "sha256-gi48yl5laoKLoVCDIORsseOM6DI58FNpAjSVe7OOs7I=";
|
||||
};
|
||||
tester = ./default/Dockerfile;
|
||||
system = "x86_64-linux";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
makeTest = containerTool: imageName:
|
||||
let image = images.${imageName}; in
|
||||
with (forSystem image.system ({ system, pkgs, lib, ... }: pkgs));
|
||||
testers.nixosTest
|
||||
{
|
||||
name = "container-test-${imageName}";
|
||||
nodes = {
|
||||
machine =
|
||||
{ config, pkgs, ... }: {
|
||||
virtualisation.${containerTool}.enable = true;
|
||||
};
|
||||
};
|
||||
testScript = ''
|
||||
machine.start()
|
||||
machine.copy_from_host("${image.tarball}", "/image")
|
||||
machine.succeed("mkdir -p /test")
|
||||
machine.copy_from_host("${image.tester}", "/test/Dockerfile")
|
||||
machine.copy_from_host("${nix-installer-static}", "/test/nix-installer")
|
||||
machine.copy_from_host("${binaryTarball.${system}}", "/test/binary-tarball")
|
||||
machine.succeed("${containerTool} import /image default")
|
||||
machine.succeed("${containerTool} build -t test /test")
|
||||
'';
|
||||
};
|
||||
|
||||
container-tests = builtins.mapAttrs
|
||||
(imageName: image: (with (forSystem "x86_64-linux" ({ system, pkgs, ... }: pkgs)); {
|
||||
${image.system} = rec {
|
||||
docker = makeTest "docker" imageName;
|
||||
podman = makeTest "podman" imageName;
|
||||
all = pkgs.releaseTools.aggregate {
|
||||
name = "all";
|
||||
constituents = [
|
||||
docker
|
||||
podman
|
||||
];
|
||||
};
|
||||
};
|
||||
}))
|
||||
images;
|
||||
|
||||
in
|
||||
container-tests // {
|
||||
all."x86_64-linux" = rec {
|
||||
all = (with (forSystem "x86_64-linux" ({ system, pkgs, ... }: pkgs)); pkgs.releaseTools.aggregate {
|
||||
name = "all";
|
||||
constituents = [
|
||||
docker
|
||||
podman
|
||||
];
|
||||
});
|
||||
docker = (with (forSystem "x86_64-linux" ({ system, pkgs, ... }: pkgs)); pkgs.releaseTools.aggregate {
|
||||
name = "all";
|
||||
constituents = pkgs.lib.mapAttrsToList (name: value: value."x86_64-linux".docker) container-tests;
|
||||
});
|
||||
podman = (with (forSystem "x86_64-linux" ({ system, pkgs, ... }: pkgs)); pkgs.releaseTools.aggregate {
|
||||
name = "all";
|
||||
constituents = pkgs.lib.mapAttrsToList (name: value: value."x86_64-linux".podman) container-tests;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
8
nix/tests/container-test/default/Dockerfile
Normal file
8
nix/tests/container-test/default/Dockerfile
Normal file
|
@ -0,0 +1,8 @@
|
|||
FROM default
|
||||
COPY nix-installer /nix-installer
|
||||
RUN chmod +x /nix-installer
|
||||
COPY binary-tarball /binary-tarball
|
||||
RUN mv /binary-tarball/nix-*.tar.xz nix.tar.xz
|
||||
RUN /nix-installer/bin/nix-installer install linux-multi --nix-package-url file:///nix.tar.xz --init none --extra-conf "sandbox = false" --channel --no-confirm -vvv
|
||||
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"]; }'
|
|
@ -5,10 +5,61 @@ let
|
|||
|
||||
installScripts = {
|
||||
install-default = {
|
||||
script = ''
|
||||
install = ''
|
||||
NIX_PATH=$(readlink -f nix.tar.xz)
|
||||
RUST_BACKTRACE="full" ./nix-installer install --logger pretty --log-directive nix_installer=trace --channel --nix-package-url "file://$NIX_PATH" --no-confirm
|
||||
'';
|
||||
check = ''
|
||||
set -ex
|
||||
|
||||
nix-env --version
|
||||
nix --extra-experimental-features nix-command store ping
|
||||
|
||||
out=$(nix-build --no-substitute -E 'derivation { name = "foo"; system = "x86_64-linux"; builder = "/bin/sh"; args = ["-c" "echo foobar > $out"]; }')
|
||||
[[ $(cat $out) = foobar ]]
|
||||
'';
|
||||
};
|
||||
install-no-start-daemon = {
|
||||
install = ''
|
||||
NIX_PATH=$(readlink -f nix.tar.xz)
|
||||
RUST_BACKTRACE="full" ./nix-installer install linux-multi --no-start-daemon --logger pretty --log-directive nix_installer=trace --channel --nix-package-url "file://$NIX_PATH" --no-confirm
|
||||
'';
|
||||
check = ''
|
||||
set -ex
|
||||
|
||||
if systemctl is-active nix-daemon.socket; then
|
||||
echo "nix-daemon.socket was running, should not be"
|
||||
exit 1
|
||||
fi
|
||||
if systemctl is-active nix-daemon.service; then
|
||||
echo "nix-daemon.service was running, should not be"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sudo systemctl start nix-daemon.socket
|
||||
|
||||
nix-env --version
|
||||
nix --extra-experimental-features nix-command store ping
|
||||
|
||||
out=$(nix-build --no-substitute -E 'derivation { name = "foo"; system = "x86_64-linux"; builder = "/bin/sh"; args = ["-c" "echo foobar > $out"]; }')
|
||||
[[ $(cat $out) = foobar ]]
|
||||
'';
|
||||
};
|
||||
install-daemonless = {
|
||||
install = ''
|
||||
NIX_PATH=$(readlink -f nix.tar.xz)
|
||||
RUST_BACKTRACE="full" ./nix-installer install linux-multi --init none --logger pretty --log-directive nix_installer=trace --channel --nix-package-url "file://$NIX_PATH" --no-confirm
|
||||
'';
|
||||
check = ''
|
||||
set -ex
|
||||
|
||||
sudo -i nix-env --version
|
||||
sudo -i nix --extra-experimental-features nix-command store ping
|
||||
|
||||
echo 'derivation { name = "foo"; system = "x86_64-linux"; builder = "/bin/sh"; args = ["-c" "echo foobar > $out"]; }' | sudo tee -a /drv
|
||||
out=$(sudo -i nix-build --no-substitute /drv)
|
||||
[[ $(cat $out) = foobar ]]
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -114,7 +165,8 @@ let
|
|||
buildInputs = [ qemu_kvm openssh ];
|
||||
image = image.image;
|
||||
postBoot = image.postBoot or "";
|
||||
installScript = installScripts.${testName}.script;
|
||||
installScript = installScripts.${testName}.install;
|
||||
checkScript = installScripts.${testName}.check;
|
||||
installer = nix-installer-static;
|
||||
binaryTarball = binaryTarball.${system};
|
||||
}
|
||||
|
@ -182,15 +234,7 @@ let
|
|||
$ssh "set -eux; $installScript"
|
||||
|
||||
echo "Testing Nix installation..."
|
||||
$ssh <<EOF
|
||||
set -ex
|
||||
|
||||
nix-env --version
|
||||
nix --extra-experimental-features nix-command store ping
|
||||
|
||||
out=\$(nix-build --no-substitute -E 'derivation { name = "foo"; system = "x86_64-linux"; builder = "/bin/sh"; args = ["-c" "echo foobar > \$out"]; }')
|
||||
[[ \$(cat \$out) = foobar ]]
|
||||
EOF
|
||||
$ssh "set -eux; $checkScript"
|
||||
|
||||
echo "Done!"
|
||||
touch $out
|
||||
|
@ -198,20 +242,47 @@ let
|
|||
|
||||
vm-tests = builtins.mapAttrs
|
||||
(imageName: image:
|
||||
{
|
||||
${image.system} = builtins.mapAttrs
|
||||
rec {
|
||||
${image.system} = (builtins.mapAttrs
|
||||
(testName: test:
|
||||
makeTest imageName testName
|
||||
)
|
||||
installScripts;
|
||||
installScripts) // {
|
||||
all = (with (forSystem "x86_64-linux" ({ system, pkgs, ... }: pkgs)); pkgs.releaseTools.aggregate {
|
||||
name = "all";
|
||||
constituents = (
|
||||
pkgs.lib.mapAttrsToList
|
||||
(testName: test:
|
||||
makeTest imageName testName
|
||||
)
|
||||
installScripts
|
||||
);
|
||||
});
|
||||
};
|
||||
}
|
||||
)
|
||||
images;
|
||||
|
||||
in
|
||||
vm-tests // {
|
||||
vm-tests // rec {
|
||||
all."x86_64-linux".install-default = (with (forSystem "x86_64-linux" ({ system, pkgs, ... }: pkgs)); pkgs.releaseTools.aggregate {
|
||||
name = "all";
|
||||
constituents = pkgs.lib.mapAttrsToList (name: value: value."x86_64-linux".install-default) vm-tests;
|
||||
});
|
||||
all."x86_64-linux".install-no-start-daemon = (with (forSystem "x86_64-linux" ({ system, pkgs, ... }: pkgs)); pkgs.releaseTools.aggregate {
|
||||
name = "all";
|
||||
constituents = pkgs.lib.mapAttrsToList (name: value: value."x86_64-linux".install-default) vm-tests;
|
||||
});
|
||||
all."x86_64-linux".install-daemonless = (with (forSystem "x86_64-linux" ({ system, pkgs, ... }: pkgs)); pkgs.releaseTools.aggregate {
|
||||
name = "all";
|
||||
constituents = pkgs.lib.mapAttrsToList (name: value: value."x86_64-linux".install-daemonless) vm-tests;
|
||||
});
|
||||
all."x86_64-linux".all = (with (forSystem "x86_64-linux" ({ system, pkgs, ... }: pkgs)); pkgs.releaseTools.aggregate {
|
||||
name = "all";
|
||||
constituents = [
|
||||
all."x86_64-linux".install-default
|
||||
all."x86_64-linux".install-no-start-daemon
|
||||
all."x86_64-linux".install-daemonless
|
||||
];
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
use crate::{
|
||||
action::{ActionError, StatefulAction},
|
||||
execute_command, set_env,
|
||||
execute_command, set_env, ChannelValue,
|
||||
};
|
||||
|
||||
use glob::glob;
|
||||
|
@ -17,12 +17,12 @@ Setup the default Nix profile with `nss-cacert` and `nix` itself.
|
|||
*/
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct SetupDefaultProfile {
|
||||
channels: Vec<String>,
|
||||
channels: Vec<ChannelValue>,
|
||||
}
|
||||
|
||||
impl SetupDefaultProfile {
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn plan(channels: Vec<String>) -> Result<StatefulAction<Self>, ActionError> {
|
||||
pub async fn plan(channels: Vec<ChannelValue>) -> Result<StatefulAction<Self>, ActionError> {
|
||||
Ok(Self { channels }.into())
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,12 @@ impl Action for SetupDefaultProfile {
|
|||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"setup_default_profile",
|
||||
channels = self.channels.join(","),
|
||||
channels = self
|
||||
.channels
|
||||
.iter()
|
||||
.map(|ChannelValue(channel, url)| format!("{channel}={url}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(","),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -206,7 +211,7 @@ impl Action for SetupDefaultProfile {
|
|||
command.process_group(0);
|
||||
command.arg("--update");
|
||||
for channel in channels {
|
||||
command.arg(channel);
|
||||
command.arg(channel.0.clone());
|
||||
}
|
||||
command.env(
|
||||
"NIX_SSL_CERT_FILE",
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use target_lexicon::OperatingSystem;
|
||||
use tokio::fs::remove_file;
|
||||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
|
@ -9,48 +7,54 @@ use crate::action::{ActionError, StatefulAction};
|
|||
use crate::execute_command;
|
||||
|
||||
use crate::action::{Action, ActionDescription};
|
||||
use crate::settings::InitSystem;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
const SERVICE_SRC: &str = "/nix/var/nix/profiles/default/lib/systemd/system/nix-daemon.service";
|
||||
#[cfg(target_os = "linux")]
|
||||
const SOCKET_SRC: &str = "/nix/var/nix/profiles/default/lib/systemd/system/nix-daemon.socket";
|
||||
#[cfg(target_os = "linux")]
|
||||
const TMPFILES_SRC: &str = "/nix/var/nix/profiles/default/lib/tmpfiles.d/nix-daemon.conf";
|
||||
#[cfg(target_os = "linux")]
|
||||
const TMPFILES_DEST: &str = "/etc/tmpfiles.d/nix-daemon.conf";
|
||||
#[cfg(target_os = "macos")]
|
||||
const DARWIN_NIX_DAEMON_DEST: &str = "/Library/LaunchDaemons/org.nixos.nix-daemon.plist";
|
||||
#[cfg(target_os = "macos")]
|
||||
const DARWIN_NIX_DAEMON_SOURCE: &str =
|
||||
"/nix/var/nix/profiles/default/Library/LaunchDaemons/org.nixos.nix-daemon.plist";
|
||||
/**
|
||||
Run systemd utilities to configure the Nix daemon
|
||||
Configure the init to run the Nix daemon
|
||||
*/
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct ConfigureNixDaemonService {}
|
||||
pub struct ConfigureInitService {
|
||||
init: InitSystem,
|
||||
start_daemon: bool,
|
||||
}
|
||||
|
||||
impl ConfigureNixDaemonService {
|
||||
impl ConfigureInitService {
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn plan() -> Result<StatefulAction<Self>, ActionError> {
|
||||
match OperatingSystem::host() {
|
||||
OperatingSystem::MacOSX {
|
||||
major: _,
|
||||
minor: _,
|
||||
patch: _,
|
||||
}
|
||||
| OperatingSystem::Darwin => (),
|
||||
_ => {
|
||||
if !Path::new("/run/systemd/system").exists() {
|
||||
return Err(ActionError::Custom(Box::new(
|
||||
ConfigureNixDaemonServiceError::InitNotSupported,
|
||||
)));
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
Ok(Self {}.into())
|
||||
pub async fn plan(
|
||||
init: InitSystem,
|
||||
start_daemon: bool,
|
||||
) -> Result<StatefulAction<Self>, ActionError> {
|
||||
Ok(Self { init, start_daemon }.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
#[typetag::serde(name = "configure_nix_daemon")]
|
||||
impl Action for ConfigureNixDaemonService {
|
||||
impl Action for ConfigureInitService {
|
||||
fn tracing_synopsis(&self) -> String {
|
||||
"Configure Nix daemon related settings with systemd".to_string()
|
||||
match self.init {
|
||||
#[cfg(target_os = "linux")]
|
||||
InitSystem::Systemd => "Configure Nix daemon related settings with systemd".to_string(),
|
||||
#[cfg(target_os = "macos")]
|
||||
InitSystem::Launchd => {
|
||||
"Configure Nix daemon related settings with launchctl".to_string()
|
||||
},
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
InitSystem::None => "Leave the Nix daemon unconfigured".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
|
@ -58,44 +62,45 @@ impl Action for ConfigureNixDaemonService {
|
|||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
match OperatingSystem::host() {
|
||||
OperatingSystem::MacOSX {
|
||||
major: _,
|
||||
minor: _,
|
||||
patch: _,
|
||||
}
|
||||
| OperatingSystem::Darwin => vec![ActionDescription::new(
|
||||
self.tracing_synopsis(),
|
||||
vec![
|
||||
format!("Copy `{DARWIN_NIX_DAEMON_SOURCE}` to `DARWIN_NIX_DAEMON_DEST`"),
|
||||
format!("Run `launchctl load {DARWIN_NIX_DAEMON_DEST}`"),
|
||||
],
|
||||
)],
|
||||
_ => vec![ActionDescription::new(
|
||||
self.tracing_synopsis(),
|
||||
vec![
|
||||
let mut vec = Vec::new();
|
||||
match self.init {
|
||||
#[cfg(target_os = "linux")]
|
||||
InitSystem::Systemd => {
|
||||
let mut explanation = vec![
|
||||
"Run `systemd-tempfiles --create --prefix=/nix/var/nix`".to_string(),
|
||||
format!("Run `systemctl link {SERVICE_SRC}`"),
|
||||
format!("Run `systemctl link {SOCKET_SRC}`"),
|
||||
"Run `systemctl daemon-reload`".to_string(),
|
||||
format!("Run `systemctl enable --now {SOCKET_SRC}`"),
|
||||
],
|
||||
)],
|
||||
];
|
||||
if self.start_daemon {
|
||||
explanation.push(format!("Run `systemctl enable --now {SOCKET_SRC}`"));
|
||||
}
|
||||
vec.push(ActionDescription::new(self.tracing_synopsis(), explanation))
|
||||
},
|
||||
#[cfg(target_os = "macos")]
|
||||
InitSystem::Launchd => {
|
||||
let mut explanation = vec![format!(
|
||||
"Copy `{DARWIN_NIX_DAEMON_SOURCE}` to `DARWIN_NIX_DAEMON_DEST`"
|
||||
)];
|
||||
if self.start_daemon {
|
||||
explanation.push(format!("Run `launchctl load {DARWIN_NIX_DAEMON_DEST}`"));
|
||||
}
|
||||
vec.push(ActionDescription::new(self.tracing_synopsis(), explanation))
|
||||
},
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
InitSystem::None => (),
|
||||
}
|
||||
vec
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self {} = self;
|
||||
let Self { init, start_daemon } = self;
|
||||
|
||||
match OperatingSystem::host() {
|
||||
OperatingSystem::MacOSX {
|
||||
major: _,
|
||||
minor: _,
|
||||
patch: _,
|
||||
}
|
||||
| OperatingSystem::Darwin => {
|
||||
let src = Path::new(DARWIN_NIX_DAEMON_SOURCE);
|
||||
match init {
|
||||
#[cfg(target_os = "macos")]
|
||||
InitSystem::Launchd => {
|
||||
let src = std::path::Path::new(DARWIN_NIX_DAEMON_SOURCE);
|
||||
tokio::fs::copy(src.clone(), DARWIN_NIX_DAEMON_DEST)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
|
@ -115,8 +120,22 @@ impl Action for ConfigureNixDaemonService {
|
|||
)
|
||||
.await
|
||||
.map_err(ActionError::Command)?;
|
||||
|
||||
if *start_daemon {
|
||||
execute_command(
|
||||
Command::new("launchctl")
|
||||
.process_group(0)
|
||||
.arg("kickstart")
|
||||
.arg("-k")
|
||||
.arg("system/org.nixos.nix-daemon")
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await
|
||||
.map_err(ActionError::Command)?;
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
#[cfg(target_os = "linux")]
|
||||
InitSystem::Systemd => {
|
||||
tracing::trace!(src = TMPFILES_SRC, dest = TMPFILES_DEST, "Symlinking");
|
||||
tokio::fs::symlink(TMPFILES_SRC, TMPFILES_DEST)
|
||||
.await
|
||||
|
@ -158,24 +177,30 @@ impl Action for ConfigureNixDaemonService {
|
|||
.await
|
||||
.map_err(ActionError::Command)?;
|
||||
|
||||
execute_command(
|
||||
Command::new("systemctl")
|
||||
.process_group(0)
|
||||
.arg("daemon-reload")
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await
|
||||
.map_err(ActionError::Command)?;
|
||||
if *start_daemon {
|
||||
execute_command(
|
||||
Command::new("systemctl")
|
||||
.process_group(0)
|
||||
.arg("daemon-reload")
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await
|
||||
.map_err(ActionError::Command)?;
|
||||
|
||||
execute_command(
|
||||
Command::new("systemctl")
|
||||
.process_group(0)
|
||||
.arg("enable")
|
||||
.arg("--now")
|
||||
.arg(SOCKET_SRC),
|
||||
)
|
||||
.await
|
||||
.map_err(ActionError::Command)?;
|
||||
execute_command(
|
||||
Command::new("systemctl")
|
||||
.process_group(0)
|
||||
.arg("enable")
|
||||
.arg("--now")
|
||||
.arg(SOCKET_SRC),
|
||||
)
|
||||
.await
|
||||
.map_err(ActionError::Command)?;
|
||||
}
|
||||
},
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
InitSystem::None => {
|
||||
// Nothing here, no init system
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -183,37 +208,36 @@ impl Action for ConfigureNixDaemonService {
|
|||
}
|
||||
|
||||
fn revert_description(&self) -> Vec<ActionDescription> {
|
||||
match OperatingSystem::host() {
|
||||
OperatingSystem::MacOSX {
|
||||
major: _,
|
||||
minor: _,
|
||||
patch: _,
|
||||
}
|
||||
| OperatingSystem::Darwin => vec![ActionDescription::new(
|
||||
"Unconfigure Nix daemon related settings with launchd".to_string(),
|
||||
vec!["Run `launchctl unload {DARWIN_NIX_DAEMON_DEST}`".to_string()],
|
||||
)],
|
||||
_ => vec![ActionDescription::new(
|
||||
"Unconfigure Nix daemon related settings with systemd".to_string(),
|
||||
vec![
|
||||
"Run `systemctl disable {SOCKET_SRC}`".to_string(),
|
||||
"Run `systemctl disable {SERVICE_SRC}`".to_string(),
|
||||
"Run `systemd-tempfiles --remove --prefix=/nix/var/nix`".to_string(),
|
||||
"Run `systemctl daemon-reload`".to_string(),
|
||||
],
|
||||
)],
|
||||
match self.init {
|
||||
#[cfg(target_os = "linux")]
|
||||
InitSystem::Systemd => {
|
||||
vec![ActionDescription::new(
|
||||
"Unconfigure Nix daemon related settings with systemd".to_string(),
|
||||
vec![
|
||||
"Run `systemctl disable {SOCKET_SRC}`".to_string(),
|
||||
"Run `systemctl disable {SERVICE_SRC}`".to_string(),
|
||||
"Run `systemd-tempfiles --remove --prefix=/nix/var/nix`".to_string(),
|
||||
"Run `systemctl daemon-reload`".to_string(),
|
||||
],
|
||||
)]
|
||||
},
|
||||
#[cfg(target_os = "macos")]
|
||||
InitSystem::Launchd => {
|
||||
vec![ActionDescription::new(
|
||||
"Unconfigure Nix daemon related settings with launchctl".to_string(),
|
||||
vec!["Run `launchctl unload {DARWIN_NIX_DAEMON_DEST}`".to_string()],
|
||||
)]
|
||||
},
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
InitSystem::None => Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
match OperatingSystem::host() {
|
||||
OperatingSystem::MacOSX {
|
||||
major: _,
|
||||
minor: _,
|
||||
patch: _,
|
||||
}
|
||||
| OperatingSystem::Darwin => {
|
||||
match self.init {
|
||||
#[cfg(target_os = "macos")]
|
||||
InitSystem::Launchd => {
|
||||
execute_command(
|
||||
Command::new("launchctl")
|
||||
.process_group(0)
|
||||
|
@ -223,7 +247,8 @@ impl Action for ConfigureNixDaemonService {
|
|||
.await
|
||||
.map_err(ActionError::Command)?;
|
||||
},
|
||||
_ => {
|
||||
#[cfg(target_os = "linux")]
|
||||
InitSystem::Systemd => {
|
||||
// We separate stop and disable (instead of using `--now`) to avoid cases where the service isn't started, but is enabled.
|
||||
|
||||
let socket_is_active = is_active("nix-daemon.socket").await?;
|
||||
|
@ -285,7 +310,7 @@ impl Action for ConfigureNixDaemonService {
|
|||
.await
|
||||
.map_err(ActionError::Command)?;
|
||||
|
||||
remove_file(TMPFILES_DEST)
|
||||
tokio::fs::remove_file(TMPFILES_DEST)
|
||||
.await
|
||||
.map_err(|e| ActionError::Remove(PathBuf::from(TMPFILES_DEST), e))?;
|
||||
|
||||
|
@ -298,6 +323,10 @@ impl Action for ConfigureNixDaemonService {
|
|||
.await
|
||||
.map_err(ActionError::Command)?;
|
||||
},
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
InitSystem::None => {
|
||||
// Nothing here, no init
|
||||
},
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
@ -310,6 +339,7 @@ pub enum ConfigureNixDaemonServiceError {
|
|||
InitNotSupported,
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn is_active(unit: &str) -> Result<bool, ActionError> {
|
||||
let output = Command::new("systemctl")
|
||||
.arg("is-active")
|
||||
|
@ -326,6 +356,7 @@ async fn is_active(unit: &str) -> Result<bool, ActionError> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn is_enabled(unit: &str) -> Result<bool, ActionError> {
|
||||
let output = Command::new("systemctl")
|
||||
.arg("is-enabled")
|
|
@ -1,17 +1,12 @@
|
|||
use crate::{
|
||||
action::{
|
||||
base::SetupDefaultProfile,
|
||||
common::{
|
||||
ConfigureNixDaemonService, ConfigureShellProfile, PlaceChannelConfiguration,
|
||||
PlaceNixConfiguration,
|
||||
},
|
||||
common::{ConfigureShellProfile, PlaceChannelConfiguration, PlaceNixConfiguration},
|
||||
Action, ActionDescription, ActionError, StatefulAction,
|
||||
},
|
||||
channel_value::ChannelValue,
|
||||
settings::CommonSettings,
|
||||
};
|
||||
|
||||
use reqwest::Url;
|
||||
use tracing::{span, Instrument, Span};
|
||||
|
||||
/**
|
||||
|
@ -23,20 +18,12 @@ pub struct ConfigureNix {
|
|||
configure_shell_profile: Option<StatefulAction<ConfigureShellProfile>>,
|
||||
place_channel_configuration: StatefulAction<PlaceChannelConfiguration>,
|
||||
place_nix_configuration: StatefulAction<PlaceNixConfiguration>,
|
||||
configure_nix_daemon_service: StatefulAction<ConfigureNixDaemonService>,
|
||||
}
|
||||
|
||||
impl ConfigureNix {
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn plan(settings: &CommonSettings) -> Result<StatefulAction<Self>, ActionError> {
|
||||
let channels: Vec<(String, Url)> = settings
|
||||
.channels
|
||||
.iter()
|
||||
.map(|ChannelValue(channel, url)| (channel.to_string(), url.clone()))
|
||||
.collect();
|
||||
|
||||
let setup_default_profile =
|
||||
SetupDefaultProfile::plan(channels.iter().map(|(v, _k)| v.clone()).collect()).await?;
|
||||
let setup_default_profile = SetupDefaultProfile::plan(settings.channels.clone()).await?;
|
||||
|
||||
let configure_shell_profile = if settings.modify_profile {
|
||||
Some(ConfigureShellProfile::plan().await?)
|
||||
|
@ -44,20 +31,18 @@ impl ConfigureNix {
|
|||
None
|
||||
};
|
||||
let place_channel_configuration =
|
||||
PlaceChannelConfiguration::plan(channels, settings.force).await?;
|
||||
PlaceChannelConfiguration::plan(settings.channels.clone(), settings.force).await?;
|
||||
let place_nix_configuration = PlaceNixConfiguration::plan(
|
||||
settings.nix_build_group_name.clone(),
|
||||
settings.extra_conf.clone(),
|
||||
settings.force,
|
||||
)
|
||||
.await?;
|
||||
let configure_nix_daemon_service = ConfigureNixDaemonService::plan().await?;
|
||||
|
||||
Ok(Self {
|
||||
place_channel_configuration,
|
||||
place_nix_configuration,
|
||||
setup_default_profile,
|
||||
configure_nix_daemon_service,
|
||||
configure_shell_profile,
|
||||
}
|
||||
.into())
|
||||
|
@ -78,14 +63,12 @@ impl Action for ConfigureNix {
|
|||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
let Self {
|
||||
setup_default_profile,
|
||||
configure_nix_daemon_service,
|
||||
place_nix_configuration,
|
||||
place_channel_configuration,
|
||||
configure_shell_profile,
|
||||
} = &self;
|
||||
|
||||
let mut buf = setup_default_profile.describe_execute();
|
||||
buf.append(&mut configure_nix_daemon_service.describe_execute());
|
||||
buf.append(&mut place_nix_configuration.describe_execute());
|
||||
buf.append(&mut place_channel_configuration.describe_execute());
|
||||
if let Some(configure_shell_profile) = configure_shell_profile {
|
||||
|
@ -98,7 +81,6 @@ impl Action for ConfigureNix {
|
|||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
setup_default_profile,
|
||||
configure_nix_daemon_service,
|
||||
place_nix_configuration,
|
||||
place_channel_configuration,
|
||||
configure_shell_profile,
|
||||
|
@ -168,7 +150,6 @@ impl Action for ConfigureNix {
|
|||
},
|
||||
)?;
|
||||
};
|
||||
configure_nix_daemon_service.try_execute().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -176,7 +157,6 @@ impl Action for ConfigureNix {
|
|||
fn revert_description(&self) -> Vec<ActionDescription> {
|
||||
let Self {
|
||||
setup_default_profile,
|
||||
configure_nix_daemon_service,
|
||||
place_nix_configuration,
|
||||
place_channel_configuration,
|
||||
configure_shell_profile,
|
||||
|
@ -188,7 +168,6 @@ impl Action for ConfigureNix {
|
|||
}
|
||||
buf.append(&mut place_channel_configuration.describe_revert());
|
||||
buf.append(&mut place_nix_configuration.describe_revert());
|
||||
buf.append(&mut configure_nix_daemon_service.describe_revert());
|
||||
buf.append(&mut setup_default_profile.describe_revert());
|
||||
|
||||
buf
|
||||
|
@ -198,13 +177,11 @@ impl Action for ConfigureNix {
|
|||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
let Self {
|
||||
setup_default_profile,
|
||||
configure_nix_daemon_service,
|
||||
place_nix_configuration,
|
||||
place_channel_configuration,
|
||||
configure_shell_profile,
|
||||
} = self;
|
||||
|
||||
configure_nix_daemon_service.try_revert().await?;
|
||||
if let Some(configure_shell_profile) = configure_shell_profile {
|
||||
configure_shell_profile.try_revert().await?;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! [`Action`](crate::action::Action)s which only call other base plugins
|
||||
|
||||
pub(crate) mod configure_init_service;
|
||||
pub(crate) mod configure_nix;
|
||||
pub(crate) mod configure_nix_daemon_service;
|
||||
pub(crate) mod configure_shell_profile;
|
||||
pub(crate) mod create_nix_tree;
|
||||
pub(crate) mod create_users_and_groups;
|
||||
|
@ -9,8 +9,8 @@ pub(crate) mod place_channel_configuration;
|
|||
pub(crate) mod place_nix_configuration;
|
||||
pub(crate) mod provision_nix;
|
||||
|
||||
pub use configure_init_service::{ConfigureInitService, ConfigureNixDaemonServiceError};
|
||||
pub use configure_nix::ConfigureNix;
|
||||
pub use configure_nix_daemon_service::{ConfigureNixDaemonService, ConfigureNixDaemonServiceError};
|
||||
pub use configure_shell_profile::ConfigureShellProfile;
|
||||
pub use create_nix_tree::CreateNixTree;
|
||||
pub use create_users_and_groups::CreateUsersAndGroups;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::action::base::CreateFile;
|
||||
use crate::action::ActionError;
|
||||
use crate::action::{Action, ActionDescription, StatefulAction};
|
||||
use reqwest::Url;
|
||||
use crate::ChannelValue;
|
||||
use tracing::{span, Span};
|
||||
|
||||
/**
|
||||
|
@ -9,19 +9,19 @@ Place a channel configuration containing `channels` to the `$ROOT_HOME/.nix-chan
|
|||
*/
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct PlaceChannelConfiguration {
|
||||
channels: Vec<(String, Url)>,
|
||||
channels: Vec<ChannelValue>,
|
||||
create_file: StatefulAction<CreateFile>,
|
||||
}
|
||||
|
||||
impl PlaceChannelConfiguration {
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn plan(
|
||||
channels: Vec<(String, Url)>,
|
||||
channels: Vec<ChannelValue>,
|
||||
force: bool,
|
||||
) -> Result<StatefulAction<Self>, ActionError> {
|
||||
let buf = channels
|
||||
.iter()
|
||||
.map(|(name, url)| format!("{} {}", url, name))
|
||||
.map(|ChannelValue(name, url)| format!("{} {}", url, name))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
let create_file = CreateFile::plan(
|
||||
|
@ -62,7 +62,7 @@ impl Action for PlaceChannelConfiguration {
|
|||
channels = self
|
||||
.channels
|
||||
.iter()
|
||||
.map(|(c, u)| format!("{c}={u}"))
|
||||
.map(|ChannelValue(c, u)| format!("{c}={u}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(", "),
|
||||
)
|
||||
|
|
|
@ -1,19 +1,13 @@
|
|||
use nix::unistd::{chown, Group, User};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
action::{Action, ActionDescription, ActionError, StatefulAction},
|
||||
execute_command,
|
||||
};
|
||||
use rand::Rng;
|
||||
use serde::Deserialize;
|
||||
use std::{
|
||||
io::SeekFrom,
|
||||
path::{Path, PathBuf},
|
||||
str::FromStr,
|
||||
};
|
||||
use std::{io::SeekFrom, path::Path};
|
||||
use tokio::{
|
||||
fs::{remove_file, OpenOptions},
|
||||
fs::OpenOptions,
|
||||
io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt},
|
||||
process::Command,
|
||||
};
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
use tokio::process::Command;
|
||||
use tracing::{span, Span};
|
||||
|
||||
use crate::action::{ActionError, StatefulAction};
|
||||
use crate::execute_command;
|
||||
|
||||
use crate::action::{Action, ActionDescription};
|
||||
|
||||
/**
|
||||
Kickstart a `launchctl` service
|
||||
*/
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct KickstartLaunchctlService {
|
||||
unit: String,
|
||||
}
|
||||
|
||||
impl KickstartLaunchctlService {
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn plan(unit: String) -> Result<StatefulAction<Self>, ActionError> {
|
||||
Ok(Self { unit }.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
#[typetag::serde(name = "kickstart_launchctl_service")]
|
||||
impl Action for KickstartLaunchctlService {
|
||||
fn tracing_synopsis(&self) -> String {
|
||||
let Self { unit, .. } = self;
|
||||
format!("Kickstart the launchctl unit `{unit}`")
|
||||
}
|
||||
|
||||
fn tracing_span(&self) -> Span {
|
||||
span!(
|
||||
tracing::Level::DEBUG,
|
||||
"kickstart_launchctl_service",
|
||||
unit = %self.unit,
|
||||
)
|
||||
}
|
||||
|
||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||
vec![ActionDescription::new(self.tracing_synopsis(), vec![])]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||
let Self { unit } = self;
|
||||
|
||||
execute_command(
|
||||
Command::new("launchctl")
|
||||
.process_group(0)
|
||||
.arg("kickstart")
|
||||
.arg("-k")
|
||||
.arg(unit)
|
||||
.stdin(std::process::Stdio::null()),
|
||||
)
|
||||
.await
|
||||
.map_err(ActionError::Command)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn revert_description(&self) -> Vec<ActionDescription> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||
// noop
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -8,7 +8,6 @@ pub(crate) mod create_nix_volume;
|
|||
pub(crate) mod create_synthetic_objects;
|
||||
pub(crate) mod enable_ownership;
|
||||
pub(crate) mod encrypt_apfs_volume;
|
||||
pub(crate) mod kickstart_launchctl_service;
|
||||
pub(crate) mod unmount_apfs_volume;
|
||||
|
||||
pub use bootstrap_apfs_volume::{BootstrapApfsVolume, BootstrapVolumeError};
|
||||
|
@ -17,5 +16,4 @@ pub use create_nix_volume::{CreateNixVolume, NIX_VOLUME_MOUNTD_DEST};
|
|||
pub use create_synthetic_objects::{CreateSyntheticObjects, CreateSyntheticObjectsError};
|
||||
pub use enable_ownership::{EnableOwnership, EnableOwnershipError};
|
||||
pub use encrypt_apfs_volume::EncryptApfsVolume;
|
||||
pub use kickstart_launchctl_service::KickstartLaunchctlService;
|
||||
pub use unmount_apfs_volume::UnmountApfsVolume;
|
||||
|
|
|
@ -32,7 +32,7 @@ action.try_revert().await.unwrap();
|
|||
```
|
||||
|
||||
A general guidance for what determines how fine-grained an [`Action`] should be is the unit of
|
||||
reversion. The [`ConfigureNixDaemonService`](common::ConfigureNixDaemonService) action is a good
|
||||
reversion. The [`ConfigureInitService`](common::ConfigureInitService) action is a good
|
||||
example of this, it takes several steps, such as running `systemd-tmpfiles`, and calling
|
||||
`systemctl link` on some systemd units.
|
||||
|
||||
|
@ -49,7 +49,7 @@ use tracing::{Span, span};
|
|||
use nix_installer::{
|
||||
InstallPlan,
|
||||
settings::{CommonSettings, InstallSettingsError},
|
||||
planner::{Planner, PlannerError, linux::SteamDeck},
|
||||
planner::{Planner, PlannerError},
|
||||
action::{Action, ActionError, StatefulAction, ActionDescription},
|
||||
};
|
||||
|
||||
|
@ -112,7 +112,7 @@ pub struct MyPlanner {
|
|||
impl Planner for MyPlanner {
|
||||
async fn default() -> Result<Self, PlannerError> {
|
||||
Ok(Self {
|
||||
common: CommonSettings::default()?,
|
||||
common: CommonSettings::default().await?,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -34,14 +34,17 @@ match plan.install(None).await {
|
|||
# }
|
||||
```
|
||||
|
||||
Sometimes choosing a specific plan is desired:
|
||||
Sometimes choosing a specific planner is desired:
|
||||
|
||||
```rust,no_run
|
||||
use std::error::Error;
|
||||
use nix_installer::{InstallPlan, planner::{Planner, linux::SteamDeck}};
|
||||
use nix_installer::{InstallPlan, planner::Planner};
|
||||
|
||||
# async fn chosen_planner_install() -> color_eyre::Result<()> {
|
||||
let planner = SteamDeck::default().await?;
|
||||
#[cfg(target_os = "linux")]
|
||||
let planner = nix_installer::planner::linux::SteamDeck::default().await?;
|
||||
#[cfg(target_os = "macos")]
|
||||
let planner = nix_installer::planner::darwin::DarwinMulti::default().await?;
|
||||
|
||||
// Or call `crate::planner::BuiltinPlanner::default()`
|
||||
// Match on the result to customize.
|
||||
|
|
|
@ -6,15 +6,15 @@ use tokio::process::Command;
|
|||
|
||||
use crate::{
|
||||
action::{
|
||||
common::{ConfigureNix, ProvisionNix},
|
||||
darwin::{CreateNixVolume, KickstartLaunchctlService},
|
||||
common::{ConfigureInitService, ConfigureNix, ProvisionNix},
|
||||
darwin::CreateNixVolume,
|
||||
StatefulAction,
|
||||
},
|
||||
execute_command,
|
||||
os::darwin::DiskUtilOutput,
|
||||
planner::{Planner, PlannerError},
|
||||
settings::CommonSettings,
|
||||
settings::InstallSettingsError,
|
||||
settings::{CommonSettings, InitSystem},
|
||||
Action, BuiltinPlanner,
|
||||
};
|
||||
|
||||
|
@ -24,6 +24,7 @@ use crate::{
|
|||
pub struct DarwinMulti {
|
||||
#[cfg_attr(feature = "cli", clap(flatten))]
|
||||
pub settings: CommonSettings,
|
||||
|
||||
/// Force encryption on the volume
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
|
@ -76,7 +77,7 @@ async fn default_root_disk() -> Result<String, PlannerError> {
|
|||
impl Planner for DarwinMulti {
|
||||
async fn default() -> Result<Self, PlannerError> {
|
||||
Ok(Self {
|
||||
settings: CommonSettings::default()?,
|
||||
settings: CommonSettings::default().await?,
|
||||
root_disk: Some(default_root_disk().await?),
|
||||
case_sensitive: false,
|
||||
encrypt: None,
|
||||
|
@ -140,7 +141,7 @@ impl Planner for DarwinMulti {
|
|||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
KickstartLaunchctlService::plan("system/org.nixos.nix-daemon".into())
|
||||
ConfigureInitService::plan(InitSystem::Launchd, true)
|
||||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::{
|
||||
action::{
|
||||
base::CreateDirectory,
|
||||
common::{ConfigureNix, ProvisionNix},
|
||||
common::{ConfigureInitService, ConfigureNix, ProvisionNix},
|
||||
StatefulAction,
|
||||
},
|
||||
planner::{Planner, PlannerError},
|
||||
settings::CommonSettings,
|
||||
settings::InstallSettingsError,
|
||||
settings::{InitSettings, InstallSettingsError},
|
||||
Action, BuiltinPlanner,
|
||||
};
|
||||
use std::{collections::HashMap, path::Path};
|
||||
|
@ -18,6 +18,8 @@ use tokio::process::Command;
|
|||
pub struct LinuxMulti {
|
||||
#[cfg_attr(feature = "cli", clap(flatten))]
|
||||
pub settings: CommonSettings,
|
||||
#[cfg_attr(feature = "cli", clap(flatten))]
|
||||
pub init: InitSettings,
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
|
@ -25,7 +27,8 @@ pub struct LinuxMulti {
|
|||
impl Planner for LinuxMulti {
|
||||
async fn default() -> Result<Self, PlannerError> {
|
||||
Ok(Self {
|
||||
settings: CommonSettings::default()?,
|
||||
settings: CommonSettings::default().await?,
|
||||
init: InitSettings::default().await?,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -77,14 +80,19 @@ impl Planner for LinuxMulti {
|
|||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
ConfigureInitService::plan(self.init.init, self.init.start_daemon)
|
||||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
])
|
||||
}
|
||||
|
||||
fn settings(&self) -> Result<HashMap<String, serde_json::Value>, InstallSettingsError> {
|
||||
let Self { settings } = self;
|
||||
let Self { settings, init } = self;
|
||||
let mut map = HashMap::default();
|
||||
|
||||
map.extend(settings.settings()?.into_iter());
|
||||
map.extend(init.settings()?.into_iter());
|
||||
|
||||
Ok(map)
|
||||
}
|
||||
|
|
|
@ -64,12 +64,12 @@ use std::{collections::HashMap, path::PathBuf};
|
|||
use crate::{
|
||||
action::{
|
||||
base::{CreateDirectory, CreateFile},
|
||||
common::{ConfigureNix, ProvisionNix},
|
||||
common::{ConfigureInitService, ConfigureNix, ProvisionNix},
|
||||
linux::StartSystemdUnit,
|
||||
Action, StatefulAction,
|
||||
},
|
||||
planner::{Planner, PlannerError},
|
||||
settings::{CommonSettings, InstallSettingsError},
|
||||
settings::{CommonSettings, InitSystem, InstallSettingsError},
|
||||
BuiltinPlanner,
|
||||
};
|
||||
|
||||
|
@ -95,7 +95,7 @@ impl Planner for SteamDeck {
|
|||
async fn default() -> Result<Self, PlannerError> {
|
||||
Ok(Self {
|
||||
persistence: PathBuf::from("/home/nix"),
|
||||
settings: CommonSettings::default()?,
|
||||
settings: CommonSettings::default().await?,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -225,6 +225,11 @@ impl Planner for SteamDeck {
|
|||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
// Init is required for the steam-deck archetype to make the `/nix` mount
|
||||
ConfigureInitService::plan(InitSystem::Systemd, true)
|
||||
.await
|
||||
.map_err(PlannerError::Action)?
|
||||
.boxed(),
|
||||
])
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
/*! [`BuiltinPlanner`]s and traits to create new types which can be used to plan out an [`InstallPlan`]
|
||||
|
||||
It's a [`Planner`]s job to construct (if possible) a valid [`InstallPlan`] for the host. Some planners,
|
||||
like [`LinuxMulti`](linux::LinuxMulti), are operating system specific. Others, like [`SteamDeck`](linux::SteamDeck), are device specific.
|
||||
It's a [`Planner`]s job to construct (if possible) a valid [`InstallPlan`] for the host. Some planners are operating system specific, others are device specific.
|
||||
|
||||
[`Planner`]s contain their planner specific settings, typically alongside a [`CommonSettings`][crate::settings::CommonSettings].
|
||||
|
||||
|
@ -16,8 +15,8 @@ use std::{error::Error, collections::HashMap};
|
|||
use nix_installer::{
|
||||
InstallPlan,
|
||||
settings::{CommonSettings, InstallSettingsError},
|
||||
planner::{Planner, PlannerError, linux::SteamDeck},
|
||||
action::{Action, StatefulAction, linux::StartSystemdUnit},
|
||||
planner::{Planner, PlannerError},
|
||||
action::{Action, StatefulAction, base::CreateFile},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
|
@ -31,7 +30,7 @@ pub struct MyPlanner {
|
|||
impl Planner for MyPlanner {
|
||||
async fn default() -> Result<Self, PlannerError> {
|
||||
Ok(Self {
|
||||
common: CommonSettings::default()?,
|
||||
common: CommonSettings::default().await?,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -39,7 +38,7 @@ impl Planner for MyPlanner {
|
|||
Ok(vec![
|
||||
// ...
|
||||
|
||||
StartSystemdUnit::plan("nix-daemon.socket")
|
||||
CreateFile::plan("/example", None, None, None, "Example".to_string(), false)
|
||||
.await
|
||||
.map_err(PlannerError::Action)?.boxed(),
|
||||
])
|
||||
|
@ -74,7 +73,9 @@ match plan.install(None).await {
|
|||
```
|
||||
|
||||
*/
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod darwin;
|
||||
#[cfg(target_os = "linux")]
|
||||
pub mod linux;
|
||||
|
||||
use std::{collections::HashMap, string::FromUtf8Error};
|
||||
|
@ -113,11 +114,14 @@ dyn_clone::clone_trait_object!(Planner);
|
|||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
#[cfg_attr(feature = "cli", derive(clap::Subcommand))]
|
||||
pub enum BuiltinPlanner {
|
||||
#[cfg(target_os = "linux")]
|
||||
/// A standard Linux multi-user install
|
||||
LinuxMulti(linux::LinuxMulti),
|
||||
/// A standard MacOS (Darwin) multi-user install
|
||||
#[cfg(target_os = "macos")]
|
||||
DarwinMulti(darwin::DarwinMulti),
|
||||
/// A specialized install suitable for the Valve Steam Deck console
|
||||
#[cfg(target_os = "linux")]
|
||||
SteamDeck(linux::SteamDeck),
|
||||
}
|
||||
|
||||
|
@ -126,16 +130,20 @@ impl BuiltinPlanner {
|
|||
pub async fn default() -> Result<Self, PlannerError> {
|
||||
use target_lexicon::{Architecture, OperatingSystem};
|
||||
match (Architecture::host(), OperatingSystem::host()) {
|
||||
#[cfg(target_os = "linux")]
|
||||
(Architecture::X86_64, OperatingSystem::Linux) => {
|
||||
Ok(Self::LinuxMulti(linux::LinuxMulti::default().await?))
|
||||
},
|
||||
#[cfg(target_os = "linux")]
|
||||
(Architecture::Aarch64(_), OperatingSystem::Linux) => {
|
||||
Ok(Self::LinuxMulti(linux::LinuxMulti::default().await?))
|
||||
},
|
||||
#[cfg(target_os = "macos")]
|
||||
(Architecture::X86_64, OperatingSystem::MacOSX { .. })
|
||||
| (Architecture::X86_64, OperatingSystem::Darwin) => {
|
||||
Ok(Self::DarwinMulti(darwin::DarwinMulti::default().await?))
|
||||
},
|
||||
#[cfg(target_os = "macos")]
|
||||
(Architecture::Aarch64(_), OperatingSystem::MacOSX { .. })
|
||||
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => {
|
||||
Ok(Self::DarwinMulti(darwin::DarwinMulti::default().await?))
|
||||
|
@ -147,41 +155,56 @@ impl BuiltinPlanner {
|
|||
pub async fn from_common_settings(settings: CommonSettings) -> Result<Self, PlannerError> {
|
||||
let mut built = Self::default().await?;
|
||||
match &mut built {
|
||||
#[cfg(target_os = "linux")]
|
||||
BuiltinPlanner::LinuxMulti(inner) => inner.settings = settings,
|
||||
BuiltinPlanner::DarwinMulti(inner) => inner.settings = settings,
|
||||
#[cfg(target_os = "linux")]
|
||||
BuiltinPlanner::SteamDeck(inner) => inner.settings = settings,
|
||||
#[cfg(target_os = "macos")]
|
||||
BuiltinPlanner::DarwinMulti(inner) => inner.settings = settings,
|
||||
}
|
||||
Ok(built)
|
||||
}
|
||||
|
||||
pub async fn plan(self) -> Result<InstallPlan, NixInstallerError> {
|
||||
match self {
|
||||
#[cfg(target_os = "linux")]
|
||||
BuiltinPlanner::LinuxMulti(planner) => InstallPlan::plan(planner).await,
|
||||
BuiltinPlanner::DarwinMulti(planner) => InstallPlan::plan(planner).await,
|
||||
#[cfg(target_os = "linux")]
|
||||
BuiltinPlanner::SteamDeck(planner) => InstallPlan::plan(planner).await,
|
||||
#[cfg(target_os = "macos")]
|
||||
BuiltinPlanner::DarwinMulti(planner) => InstallPlan::plan(planner).await,
|
||||
}
|
||||
}
|
||||
pub fn boxed(self) -> Box<dyn Planner> {
|
||||
match self {
|
||||
#[cfg(target_os = "linux")]
|
||||
BuiltinPlanner::LinuxMulti(i) => i.boxed(),
|
||||
BuiltinPlanner::DarwinMulti(i) => i.boxed(),
|
||||
#[cfg(target_os = "linux")]
|
||||
BuiltinPlanner::SteamDeck(i) => i.boxed(),
|
||||
#[cfg(target_os = "macos")]
|
||||
BuiltinPlanner::DarwinMulti(i) => i.boxed(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn typetag_name(&self) -> &'static str {
|
||||
match self {
|
||||
#[cfg(target_os = "linux")]
|
||||
BuiltinPlanner::LinuxMulti(i) => i.typetag_name(),
|
||||
BuiltinPlanner::DarwinMulti(i) => i.typetag_name(),
|
||||
#[cfg(target_os = "linux")]
|
||||
BuiltinPlanner::SteamDeck(i) => i.typetag_name(),
|
||||
#[cfg(target_os = "macos")]
|
||||
BuiltinPlanner::DarwinMulti(i) => i.typetag_name(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn settings(&self) -> Result<HashMap<String, serde_json::Value>, InstallSettingsError> {
|
||||
match self {
|
||||
#[cfg(target_os = "linux")]
|
||||
BuiltinPlanner::LinuxMulti(i) => i.settings(),
|
||||
BuiltinPlanner::DarwinMulti(i) => i.settings(),
|
||||
#[cfg(target_os = "linux")]
|
||||
BuiltinPlanner::SteamDeck(i) => i.settings(),
|
||||
#[cfg(target_os = "macos")]
|
||||
BuiltinPlanner::DarwinMulti(i) => i.settings(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
150
src/settings.rs
150
src/settings.rs
|
@ -21,6 +21,30 @@ pub const NIX_X64_64_DARWIN_URL: &str =
|
|||
pub const NIX_AARCH64_DARWIN_URL: &str =
|
||||
"https://releases.nixos.org/nix/nix-2.12.0/nix-2.12.0-aarch64-darwin.tar.xz";
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, Copy)]
|
||||
#[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
|
||||
pub enum InitSystem {
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
None,
|
||||
#[cfg(target_os = "linux")]
|
||||
Systemd,
|
||||
#[cfg(target_os = "macos")]
|
||||
Launchd,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for InitSystem {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
InitSystem::None => write!(f, "none"),
|
||||
#[cfg(target_os = "linux")]
|
||||
InitSystem::Systemd => write!(f, "systemd"),
|
||||
#[cfg(target_os = "macos")]
|
||||
InitSystem::Launchd => write!(f, "launchd"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Common settings used by all [`BuiltinPlanner`](crate::planner::BuiltinPlanner)s
|
||||
|
||||
Settings which only apply to certain [`Planner`](crate::planner::Planner)s should be located in the planner.
|
||||
|
@ -173,29 +197,33 @@ pub struct CommonSettings {
|
|||
|
||||
impl CommonSettings {
|
||||
/// The default settings for the given Architecture & Operating System
|
||||
pub fn default() -> Result<Self, InstallSettingsError> {
|
||||
pub async fn default() -> Result<Self, InstallSettingsError> {
|
||||
let url;
|
||||
let nix_build_user_prefix;
|
||||
let nix_build_user_id_base;
|
||||
|
||||
use target_lexicon::{Architecture, OperatingSystem};
|
||||
match (Architecture::host(), OperatingSystem::host()) {
|
||||
#[cfg(target_os = "linux")]
|
||||
(Architecture::X86_64, OperatingSystem::Linux) => {
|
||||
url = NIX_X64_64_LINUX_URL;
|
||||
nix_build_user_prefix = "nixbld";
|
||||
nix_build_user_id_base = 3000;
|
||||
},
|
||||
#[cfg(target_os = "linux")]
|
||||
(Architecture::Aarch64(_), OperatingSystem::Linux) => {
|
||||
url = NIX_AARCH64_LINUX_URL;
|
||||
nix_build_user_prefix = "nixbld";
|
||||
nix_build_user_id_base = 3000;
|
||||
},
|
||||
#[cfg(target_os = "macos")]
|
||||
(Architecture::X86_64, OperatingSystem::MacOSX { .. })
|
||||
| (Architecture::X86_64, OperatingSystem::Darwin) => {
|
||||
url = NIX_X64_64_DARWIN_URL;
|
||||
nix_build_user_prefix = "_nixbld";
|
||||
nix_build_user_id_base = 300;
|
||||
},
|
||||
#[cfg(target_os = "macos")]
|
||||
(Architecture::Aarch64(_), OperatingSystem::MacOSX { .. })
|
||||
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => {
|
||||
url = NIX_AARCH64_DARWIN_URL;
|
||||
|
@ -286,6 +314,34 @@ impl CommonSettings {
|
|||
Ok(map)
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
async fn linux_detect_init() -> (InitSystem, bool) {
|
||||
use std::process::Stdio;
|
||||
|
||||
let mut detected = InitSystem::None;
|
||||
let mut started = false;
|
||||
if std::path::Path::new("/run/systemd/system").exists() {
|
||||
detected = InitSystem::Systemd;
|
||||
started = if tokio::process::Command::new("systemctl")
|
||||
.arg("status")
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.status()
|
||||
.await
|
||||
.ok()
|
||||
.map(|exit| exit.success())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Other inits
|
||||
(detected, started)
|
||||
}
|
||||
|
||||
// Builder Pattern
|
||||
impl CommonSettings {
|
||||
|
@ -349,6 +405,96 @@ impl CommonSettings {
|
|||
}
|
||||
}
|
||||
|
||||
#[serde_with::serde_as]
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
#[cfg_attr(feature = "cli", derive(clap::Parser))]
|
||||
pub struct InitSettings {
|
||||
/// Which init system to configure (if `--init none` Nix will be root-only)
|
||||
#[cfg_attr(feature = "cli", clap(value_parser, long, env = "NIX_INSTALLER_INIT",))]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", feature = "cli"),
|
||||
clap(default_value_t = InitSystem::Launchd)
|
||||
)]
|
||||
#[cfg_attr(
|
||||
all(target_os = "linux", feature = "cli"),
|
||||
clap(default_value_t = InitSystem::Systemd)
|
||||
)]
|
||||
pub(crate) init: InitSystem,
|
||||
|
||||
/// Start the daemon (if not `--init none`)
|
||||
#[cfg_attr(
|
||||
feature = "cli",
|
||||
clap(
|
||||
value_parser,
|
||||
long,
|
||||
action(ArgAction::SetFalse),
|
||||
env = "NIX_INSTALLER_START_DAEMON",
|
||||
default_value_t = true,
|
||||
long = "no-start-daemon"
|
||||
)
|
||||
)]
|
||||
pub(crate) start_daemon: bool,
|
||||
}
|
||||
|
||||
impl InitSettings {
|
||||
/// The default settings for the given Architecture & Operating System
|
||||
pub async fn default() -> Result<Self, InstallSettingsError> {
|
||||
let init;
|
||||
let start_daemon;
|
||||
|
||||
use target_lexicon::{Architecture, OperatingSystem};
|
||||
match (Architecture::host(), OperatingSystem::host()) {
|
||||
#[cfg(target_os = "linux")]
|
||||
(Architecture::X86_64, OperatingSystem::Linux) => {
|
||||
(init, start_daemon) = linux_detect_init().await;
|
||||
},
|
||||
#[cfg(target_os = "linux")]
|
||||
(Architecture::Aarch64(_), OperatingSystem::Linux) => {
|
||||
(init, start_daemon) = linux_detect_init().await;
|
||||
},
|
||||
#[cfg(target_os = "macos")]
|
||||
(Architecture::X86_64, OperatingSystem::MacOSX { .. })
|
||||
| (Architecture::X86_64, OperatingSystem::Darwin) => {
|
||||
(init, start_daemon) = (InitSystem::Launchd, true);
|
||||
},
|
||||
#[cfg(target_os = "macos")]
|
||||
(Architecture::Aarch64(_), OperatingSystem::MacOSX { .. })
|
||||
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => {
|
||||
(init, start_daemon) = (InitSystem::Launchd, true);
|
||||
},
|
||||
_ => {
|
||||
return Err(InstallSettingsError::UnsupportedArchitecture(
|
||||
target_lexicon::HOST,
|
||||
))
|
||||
},
|
||||
};
|
||||
|
||||
Ok(Self { init, start_daemon })
|
||||
}
|
||||
|
||||
/// A listing of the settings, suitable for [`Planner::settings`](crate::planner::Planner::settings)
|
||||
pub fn settings(&self) -> Result<HashMap<String, serde_json::Value>, InstallSettingsError> {
|
||||
let Self { init, start_daemon } = self;
|
||||
let mut map = HashMap::default();
|
||||
|
||||
map.insert("init".into(), serde_json::to_value(init)?);
|
||||
map.insert("start_daemon".into(), serde_json::to_value(start_daemon)?);
|
||||
Ok(map)
|
||||
}
|
||||
|
||||
/// Which init system to configure
|
||||
pub fn init(&mut self, init: InitSystem) -> &mut Self {
|
||||
self.init = init;
|
||||
self
|
||||
}
|
||||
|
||||
/// Start the daemon (if one is configured)
|
||||
pub fn start_daemon(&mut self, toggle: bool) -> &mut Self {
|
||||
self.start_daemon = toggle;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// An error originating from a [`Planner::settings`](crate::planner::Planner::settings)
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum InstallSettingsError {
|
||||
|
@ -369,4 +515,6 @@ pub enum InstallSettingsError {
|
|||
#[from]
|
||||
serde_json::Error,
|
||||
),
|
||||
#[error("No supported init system found")]
|
||||
InitNotSupported,
|
||||
}
|
||||
|
|
16
tests/fixtures/darwin/darwin-multi.json
vendored
16
tests/fixtures/darwin/darwin-multi.json
vendored
|
@ -546,7 +546,10 @@
|
|||
"setup_default_profile": {
|
||||
"action": {
|
||||
"channels": [
|
||||
"nixpkgs"
|
||||
[
|
||||
"nixpkgs",
|
||||
"https://nixos.org/channels/nixpkgs-unstable"
|
||||
]
|
||||
]
|
||||
},
|
||||
"state": "Uncompleted"
|
||||
|
@ -632,25 +635,22 @@
|
|||
"user": null,
|
||||
"group": null,
|
||||
"mode": 436,
|
||||
"buf": "\n\nbuild-users-group = nixbld\n\nexperimental-features = nix-command flakes\n\nauto-optimise-store = true\n",
|
||||
"buf": "# Generated by https://github.com/DeterminateSystems/nix-installer, version 0.1.0-unreleased.\n\n\n\nbuild-users-group = nixbld\n\nexperimental-features = nix-command flakes\n\nauto-optimise-store = true\n\nbash-prompt-prefix = (nix:$name)\\040\n",
|
||||
"force": false
|
||||
},
|
||||
"state": "Uncompleted"
|
||||
}
|
||||
},
|
||||
"state": "Uncompleted"
|
||||
},
|
||||
"configure_nix_daemon_service": {
|
||||
"action": {},
|
||||
"state": "Uncompleted"
|
||||
}
|
||||
},
|
||||
"state": "Uncompleted"
|
||||
},
|
||||
{
|
||||
"action": {
|
||||
"action": "kickstart_launchctl_service",
|
||||
"unit": "system/org.nixos.nix-daemon"
|
||||
"action": "configure_nix_daemon",
|
||||
"init": "Launchd",
|
||||
"start_daemon": true
|
||||
},
|
||||
"state": "Uncompleted"
|
||||
}
|
||||
|
|
1185
tests/fixtures/linux/linux-multi.json
vendored
1185
tests/fixtures/linux/linux-multi.json
vendored
File diff suppressed because it is too large
Load diff
1269
tests/fixtures/linux/steam-deck.json
vendored
1269
tests/fixtures/linux/steam-deck.json
vendored
File diff suppressed because it is too large
Load diff
|
@ -1,11 +1,15 @@
|
|||
use nix_installer::InstallPlan;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
const LINUX_MULTI: &str = include_str!("./fixtures/linux/linux-multi.json");
|
||||
#[cfg(target_os = "linux")]
|
||||
const STEAM_DECK: &str = include_str!("./fixtures/linux/steam-deck.json");
|
||||
#[cfg(target_os = "macos")]
|
||||
const DARWIN_MULTI: &str = include_str!("./fixtures/darwin/darwin-multi.json");
|
||||
|
||||
// Ensure existing plans still parse
|
||||
// If this breaks and you need to update the fixture, disable these tests, bump `nix_installer` to a new version, and update the plans.
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn plan_compat_linux_multi() -> eyre::Result<()> {
|
||||
let _: InstallPlan = serde_json::from_str(LINUX_MULTI)?;
|
||||
|
@ -14,6 +18,7 @@ fn plan_compat_linux_multi() -> eyre::Result<()> {
|
|||
|
||||
// Ensure existing plans still parse
|
||||
// If this breaks and you need to update the fixture, disable these tests, bump `nix_installer` to a new version, and update the plans.
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn plan_compat_steam_deck() -> eyre::Result<()> {
|
||||
let _: InstallPlan = serde_json::from_str(STEAM_DECK)?;
|
||||
|
@ -22,6 +27,7 @@ fn plan_compat_steam_deck() -> eyre::Result<()> {
|
|||
|
||||
// Ensure existing plans still parse
|
||||
// If this breaks and you need to update the fixture, disable these tests, bump `nix_installer` to a new version, and update the plans.
|
||||
#[cfg(target_os = "macos")]
|
||||
#[test]
|
||||
fn plan_compat_darwin_multi() -> eyre::Result<()> {
|
||||
let _: InstallPlan = serde_json::from_str(DARWIN_MULTI)?;
|
||||
|
|
75
tests/windows/test-wsl.ps1
Normal file
75
tests/windows/test-wsl.ps1
Normal file
|
@ -0,0 +1,75 @@
|
|||
param([switch]$Systemd = $false)
|
||||
Set-StrictMode -Version Latest
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
|
||||
# 22.04 https://cloud-images.ubuntu.com/wsl/jammy/current/
|
||||
$url = "https://cloud-images.ubuntu.com/wsl/jammy/current/ubuntu-jammy-wsl-amd64-wsl.rootfs.tar.gz"
|
||||
$File = "ubuntu-jammy-wsl-amd64-wsl.rootfs.tar.gz"
|
||||
$Name = "ubuntu-jammy"
|
||||
|
||||
|
||||
$TemporaryDirectory = "$HOME/nix-installer-wsl-tests-temp"
|
||||
$Image = "$TemporaryDirectory\$File"
|
||||
if (!(Test-Path -Path $Image)) {
|
||||
Write-Output "Fetching $File to $Image..."
|
||||
New-Item $TemporaryDirectory -ItemType Directory | Out-Null
|
||||
Invoke-WebRequest -Uri "https://cloud-images.ubuntu.com/wsl/jammy/current/ubuntu-jammy-wsl-amd64-wsl.rootfs.tar.gz" -OutFile $Image
|
||||
} else {
|
||||
Write-Output "Found existing $Image..."
|
||||
}
|
||||
|
||||
$DistroName = "nix-installer-test-$Name"
|
||||
$InstallRoot = "$TemporaryDirectory\wsl-$Name"
|
||||
Write-Output "Creating WSL distribution $DistroName from $Image at $InstallRoot..."
|
||||
wsl --import $DistroName $InstallRoot $Image
|
||||
if ($LastExitCode -ne 0) {
|
||||
exit $LastExitCode
|
||||
}
|
||||
|
||||
Write-Output "Preparing $DistroName for nix-installer..."
|
||||
wsl --distribution $DistroName bash --login -c "apt update --quiet"
|
||||
if ($LastExitCode -ne 0) {
|
||||
exit $LastExitCode
|
||||
}
|
||||
wsl --distribution $DistroName bash --login -c "apt install --quiet --yes curl build-essential"
|
||||
if ($LastExitCode -ne 0) {
|
||||
exit $LastExitCode
|
||||
}
|
||||
wsl --distribution $DistroName bash --login -c "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --quiet"
|
||||
if ($LastExitCode -ne 0) {
|
||||
exit $LastExitCode
|
||||
}
|
||||
|
||||
if ($Systemd) {
|
||||
$wslConf = "[boot]`nsystemd=true"
|
||||
New-Item -Path "\\wsl$\$DistroName\etc\wsl.conf" -ItemType "file" -Value $wslConf
|
||||
wsl --shutdown
|
||||
if ($LastExitCode -ne 0) {
|
||||
exit $LastExitCode
|
||||
}
|
||||
}
|
||||
|
||||
Write-Output "Building and runnings nix-installer in $DistroName..."
|
||||
Copy-Item -Recurse "$PSScriptRoot\..\.." -Destination "\\wsl$\$DistroName\nix-installer"
|
||||
$MaybeInitChoice = switch ($Systemd) {
|
||||
$true { "" }
|
||||
$false { "--init none" }
|
||||
}
|
||||
wsl --distribution $DistroName bash --login -c "/root/.cargo/bin/cargo run --quiet --manifest-path /nix-installer/Cargo.toml -- install linux-multi --no-confirm $MaybeInitChoice"
|
||||
if ($LastExitCode -ne 0) {
|
||||
exit $LastExitCode
|
||||
}
|
||||
|
||||
Write-Output "Testing installed Nix on $DistroName..."
|
||||
wsl --distribution $DistroName bash --login -c "nix run nixpkgs#hello"
|
||||
if ($LastExitCode -ne 0) {
|
||||
exit $LastExitCode
|
||||
}
|
||||
|
||||
Write-Output "Unregistering $DistroName and removing $InstallRoot..."
|
||||
wsl --unregister $DistroName
|
||||
if ($LastExitCode -ne 0) {
|
||||
exit $LastExitCode
|
||||
}
|
||||
Remove-Item $InstallRoot
|
Loading…
Reference in a new issue