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:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Cache lint store (x86_64-linux)
|
- name: Cache lint store (x86_64-linux)
|
||||||
|
@ -36,7 +36,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Cache build store (x86_64-linux)
|
- name: Cache build store (x86_64-linux)
|
||||||
|
@ -67,7 +67,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Cache build store (x86_64-linux)
|
- name: Cache build store (x86_64-linux)
|
||||||
|
@ -100,7 +100,7 @@ jobs:
|
||||||
cp nix-installer.sh install-root/nix-installer.sh
|
cp nix-installer.sh install-root/nix-installer.sh
|
||||||
mv nix-installer install-root/nix-installer-x86_64-linux
|
mv nix-installer install-root/nix-installer-x86_64-linux
|
||||||
- name: Initial install
|
- name: Initial install
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||||
with:
|
with:
|
||||||
local-root: install-root/
|
local-root: install-root/
|
||||||
logger: pretty
|
logger: pretty
|
||||||
|
@ -129,7 +129,7 @@ jobs:
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- name: Repeated install
|
- name: Repeated install
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||||
with:
|
with:
|
||||||
local-root: install-root/
|
local-root: install-root/
|
||||||
logger: pretty
|
logger: pretty
|
||||||
|
@ -184,6 +184,113 @@ jobs:
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
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:
|
run-steam-deck:
|
||||||
name: Run Steam Deck (mock)
|
name: Run Steam Deck (mock)
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
@ -207,7 +314,7 @@ jobs:
|
||||||
sudo chmod +x /bin/steamos-readonly
|
sudo chmod +x /bin/steamos-readonly
|
||||||
sudo useradd -m deck
|
sudo useradd -m deck
|
||||||
- name: Initial install
|
- name: Initial install
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||||
with:
|
with:
|
||||||
local-root: install-root/
|
local-root: install-root/
|
||||||
logger: pretty
|
logger: pretty
|
||||||
|
@ -242,7 +349,7 @@ jobs:
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
- name: Repeated install
|
- name: Repeated install
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||||
with:
|
with:
|
||||||
local-root: install-root/
|
local-root: install-root/
|
||||||
logger: pretty
|
logger: pretty
|
||||||
|
@ -309,7 +416,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
# Runs clippy as part of the preBuild.
|
# Runs clippy as part of the preBuild.
|
||||||
|
@ -339,7 +446,7 @@ jobs:
|
||||||
cp nix-installer.sh install-root/nix-installer.sh
|
cp nix-installer.sh install-root/nix-installer.sh
|
||||||
mv nix-installer install-root/nix-installer-x86_64-darwin
|
mv nix-installer install-root/nix-installer-x86_64-darwin
|
||||||
- name: Initial install
|
- name: Initial install
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||||
with:
|
with:
|
||||||
local-root: install-root/
|
local-root: install-root/
|
||||||
logger: pretty
|
logger: pretty
|
||||||
|
@ -356,7 +463,7 @@ jobs:
|
||||||
NIX_INSTALLER_LOG_DIRECTIVES: nix_installer=trace
|
NIX_INSTALLER_LOG_DIRECTIVES: nix_installer=trace
|
||||||
RUST_BACKTRACE: full
|
RUST_BACKTRACE: full
|
||||||
- name: Repeated install
|
- name: Repeated install
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@start-daemon-and-init
|
||||||
with:
|
with:
|
||||||
local-root: install-root/
|
local-root: install-root/
|
||||||
logger: pretty
|
logger: pretty
|
||||||
|
@ -397,4 +504,3 @@ jobs:
|
||||||
NIX_INSTALLER_LOGGER: pretty
|
NIX_INSTALLER_LOGGER: pretty
|
||||||
NIX_INSTALLER_LOG_DIRECTIVES: nix_installer=trace
|
NIX_INSTALLER_LOG_DIRECTIVES: nix_installer=trace
|
||||||
RUST_BACKTRACE: full
|
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
|
## `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`:
|
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:
|
To run all of the currently supported tests:
|
||||||
|
|
||||||
```bash
|
```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:
|
To run a specific distribution listed in the `nix flake show` output:
|
||||||
|
|
||||||
```bash
|
```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:
|
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>
|
</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`
|
## Testing the `action.yml`
|
||||||
|
|
||||||
The `action.yml` is used directly in the CI process, so it is automatically tested for most changes.
|
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:
|
Current and planned support:
|
||||||
|
|
||||||
* [x] Multi-user Linux (aarch64 and x86_64) with systemd init, no SELinux
|
* [x] Multi-user Linux (aarch64 and x86_64) with systemd integration, no SELinux
|
||||||
* [x] Multi-user MacOS (aarch64 and x86_64)
|
* [x] Root-only Linux (aarch64 and x86_64) with no init integration, no SELinux
|
||||||
+ 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] Multi-user MacOS (aarch64 and x86_64) with launchd integration
|
||||||
* [x] Valve Steam Deck
|
* [x] SteamOS on the Valve Steam Deck
|
||||||
* [ ] Multi-user Linux (aarch64 and x86_64) with systemd init & SELinux
|
* [ ] Multi-user Linux (aarch64 and x86_64) with systemd integration & SELinux
|
||||||
* [ ] Single-user Linux (aarch64 and x86_64)
|
|
||||||
* [ ] Others...
|
* [ ] Others...
|
||||||
|
|
||||||
## Installation Differences
|
## Installation Differences
|
||||||
|
@ -95,16 +94,16 @@ Usage: nix-installer install linux-multi [OPTIONS]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
# ...
|
# ...
|
||||||
--nix-build-user-count <NIX_BUILD_USER_COUNT>
|
--nix-build-group-name <NIX_BUILD_GROUP_NAME>
|
||||||
Number of build users to create
|
The Nix build group name
|
||||||
|
|
||||||
[env: NIX_INSTALLER_NIX_BUILD_USER_COUNT=]
|
[env: NIX_INSTALLER_NIX_BUILD_GROUP_NAME=]
|
||||||
[default: 32]
|
[default: nixbld]
|
||||||
|
|
||||||
--nix-build-user-id-base <NIX_BUILD_USER_ID_BASE>
|
--nix-build-group-id <NIX_BUILD_GROUP_ID>
|
||||||
The Nix build user base UID (ascending)
|
The Nix build group GID
|
||||||
|
|
||||||
[env: NIX_INSTALLER_NIX_BUILD_USER_ID_BASE=]
|
[env: NIX_INSTALLER_NIX_BUILD_GROUP_ID=]
|
||||||
[default: 3000]
|
[default: 3000]
|
||||||
# ...
|
# ...
|
||||||
```
|
```
|
||||||
|
@ -112,9 +111,9 @@ 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_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...
|
# 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
|
- uses: actions/checkout@v3
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
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`
|
- name: Run `nix build`
|
||||||
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.
|
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
|
```bash
|
||||||
nix build -L github:determinatesystems/nix-installer#nix-installer-static
|
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.
|
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
|
```bash
|
||||||
RUSTFLAGS="--cfg tokio_unstable" cargo install nix-installer
|
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.
|
> **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
|
```toml
|
||||||
# .cargo/config.toml
|
# .cargo/config.toml
|
||||||
|
@ -208,3 +281,5 @@ Documentation is also available via `nix` build:
|
||||||
nix build github:DeterminateSystems/nix-installer#nix-installer.doc
|
nix build github:DeterminateSystems/nix-installer#nix-installer.doc
|
||||||
firefox result-doc/nix-installer/index.html
|
firefox result-doc/nix-installer/index.html
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -182,6 +182,10 @@
|
||||||
inherit forSystem;
|
inherit forSystem;
|
||||||
inherit (nix.hydraJobs) binaryTarball;
|
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 ];
|
runtimeInputs = with pkgs; [ git codespell ];
|
||||||
text = ''
|
text = ''
|
||||||
codespell \
|
codespell \
|
||||||
--ignore-words-list ba,sur,crate,pullrequest,pullrequests,ser \
|
--ignore-words-list ba,sur,crate,pullrequest,pullrequests,ser,distroname \
|
||||||
--skip target \
|
--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 = {
|
installScripts = {
|
||||||
install-default = {
|
install-default = {
|
||||||
script = ''
|
install = ''
|
||||||
NIX_PATH=$(readlink -f nix.tar.xz)
|
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
|
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 ];
|
buildInputs = [ qemu_kvm openssh ];
|
||||||
image = image.image;
|
image = image.image;
|
||||||
postBoot = image.postBoot or "";
|
postBoot = image.postBoot or "";
|
||||||
installScript = installScripts.${testName}.script;
|
installScript = installScripts.${testName}.install;
|
||||||
|
checkScript = installScripts.${testName}.check;
|
||||||
installer = nix-installer-static;
|
installer = nix-installer-static;
|
||||||
binaryTarball = binaryTarball.${system};
|
binaryTarball = binaryTarball.${system};
|
||||||
}
|
}
|
||||||
|
@ -182,15 +234,7 @@ let
|
||||||
$ssh "set -eux; $installScript"
|
$ssh "set -eux; $installScript"
|
||||||
|
|
||||||
echo "Testing Nix installation..."
|
echo "Testing Nix installation..."
|
||||||
$ssh <<EOF
|
$ssh "set -eux; $checkScript"
|
||||||
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
|
|
||||||
|
|
||||||
echo "Done!"
|
echo "Done!"
|
||||||
touch $out
|
touch $out
|
||||||
|
@ -198,20 +242,47 @@ let
|
||||||
|
|
||||||
vm-tests = builtins.mapAttrs
|
vm-tests = builtins.mapAttrs
|
||||||
(imageName: image:
|
(imageName: image:
|
||||||
{
|
rec {
|
||||||
${image.system} = builtins.mapAttrs
|
${image.system} = (builtins.mapAttrs
|
||||||
(testName: test:
|
(testName: test:
|
||||||
makeTest imageName testName
|
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;
|
images;
|
||||||
|
|
||||||
in
|
in
|
||||||
vm-tests // {
|
vm-tests // rec {
|
||||||
all."x86_64-linux".install-default = (with (forSystem "x86_64-linux" ({ system, pkgs, ... }: pkgs)); pkgs.releaseTools.aggregate {
|
all."x86_64-linux".install-default = (with (forSystem "x86_64-linux" ({ system, pkgs, ... }: pkgs)); pkgs.releaseTools.aggregate {
|
||||||
name = "all";
|
name = "all";
|
||||||
constituents = pkgs.lib.mapAttrsToList (name: value: value."x86_64-linux".install-default) vm-tests;
|
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::{
|
use crate::{
|
||||||
action::{ActionError, StatefulAction},
|
action::{ActionError, StatefulAction},
|
||||||
execute_command, set_env,
|
execute_command, set_env, ChannelValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
use glob::glob;
|
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)]
|
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||||
pub struct SetupDefaultProfile {
|
pub struct SetupDefaultProfile {
|
||||||
channels: Vec<String>,
|
channels: Vec<ChannelValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SetupDefaultProfile {
|
impl SetupDefaultProfile {
|
||||||
#[tracing::instrument(level = "debug", skip_all)]
|
#[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())
|
Ok(Self { channels }.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,12 @@ impl Action for SetupDefaultProfile {
|
||||||
span!(
|
span!(
|
||||||
tracing::Level::DEBUG,
|
tracing::Level::DEBUG,
|
||||||
"setup_default_profile",
|
"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.process_group(0);
|
||||||
command.arg("--update");
|
command.arg("--update");
|
||||||
for channel in channels {
|
for channel in channels {
|
||||||
command.arg(channel);
|
command.arg(channel.0.clone());
|
||||||
}
|
}
|
||||||
command.env(
|
command.env(
|
||||||
"NIX_SSL_CERT_FILE",
|
"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 tokio::process::Command;
|
||||||
use tracing::{span, Span};
|
use tracing::{span, Span};
|
||||||
|
|
||||||
|
@ -9,48 +7,54 @@ use crate::action::{ActionError, StatefulAction};
|
||||||
use crate::execute_command;
|
use crate::execute_command;
|
||||||
|
|
||||||
use crate::action::{Action, ActionDescription};
|
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";
|
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";
|
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";
|
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";
|
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";
|
const DARWIN_NIX_DAEMON_DEST: &str = "/Library/LaunchDaemons/org.nixos.nix-daemon.plist";
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
const DARWIN_NIX_DAEMON_SOURCE: &str =
|
const DARWIN_NIX_DAEMON_SOURCE: &str =
|
||||||
"/nix/var/nix/profiles/default/Library/LaunchDaemons/org.nixos.nix-daemon.plist";
|
"/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)]
|
#[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)]
|
#[tracing::instrument(level = "debug", skip_all)]
|
||||||
pub async fn plan() -> Result<StatefulAction<Self>, ActionError> {
|
pub async fn plan(
|
||||||
match OperatingSystem::host() {
|
init: InitSystem,
|
||||||
OperatingSystem::MacOSX {
|
start_daemon: bool,
|
||||||
major: _,
|
) -> Result<StatefulAction<Self>, ActionError> {
|
||||||
minor: _,
|
Ok(Self { init, start_daemon }.into())
|
||||||
patch: _,
|
|
||||||
}
|
|
||||||
| OperatingSystem::Darwin => (),
|
|
||||||
_ => {
|
|
||||||
if !Path::new("/run/systemd/system").exists() {
|
|
||||||
return Err(ActionError::Custom(Box::new(
|
|
||||||
ConfigureNixDaemonServiceError::InitNotSupported,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Self {}.into())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
#[typetag::serde(name = "configure_nix_daemon")]
|
#[typetag::serde(name = "configure_nix_daemon")]
|
||||||
impl Action for ConfigureNixDaemonService {
|
impl Action for ConfigureInitService {
|
||||||
fn tracing_synopsis(&self) -> String {
|
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 {
|
fn tracing_span(&self) -> Span {
|
||||||
|
@ -58,44 +62,45 @@ impl Action for ConfigureNixDaemonService {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||||
match OperatingSystem::host() {
|
let mut vec = Vec::new();
|
||||||
OperatingSystem::MacOSX {
|
match self.init {
|
||||||
major: _,
|
#[cfg(target_os = "linux")]
|
||||||
minor: _,
|
InitSystem::Systemd => {
|
||||||
patch: _,
|
let mut explanation = vec![
|
||||||
}
|
|
||||||
| 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![
|
|
||||||
"Run `systemd-tempfiles --create --prefix=/nix/var/nix`".to_string(),
|
"Run `systemd-tempfiles --create --prefix=/nix/var/nix`".to_string(),
|
||||||
format!("Run `systemctl link {SERVICE_SRC}`"),
|
format!("Run `systemctl link {SERVICE_SRC}`"),
|
||||||
format!("Run `systemctl link {SOCKET_SRC}`"),
|
format!("Run `systemctl link {SOCKET_SRC}`"),
|
||||||
"Run `systemctl daemon-reload`".to_string(),
|
"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)]
|
#[tracing::instrument(level = "debug", skip_all)]
|
||||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||||
let Self {} = self;
|
let Self { init, start_daemon } = self;
|
||||||
|
|
||||||
match OperatingSystem::host() {
|
match init {
|
||||||
OperatingSystem::MacOSX {
|
#[cfg(target_os = "macos")]
|
||||||
major: _,
|
InitSystem::Launchd => {
|
||||||
minor: _,
|
let src = std::path::Path::new(DARWIN_NIX_DAEMON_SOURCE);
|
||||||
patch: _,
|
|
||||||
}
|
|
||||||
| OperatingSystem::Darwin => {
|
|
||||||
let src = Path::new(DARWIN_NIX_DAEMON_SOURCE);
|
|
||||||
tokio::fs::copy(src.clone(), DARWIN_NIX_DAEMON_DEST)
|
tokio::fs::copy(src.clone(), DARWIN_NIX_DAEMON_DEST)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
|
@ -115,8 +120,22 @@ impl Action for ConfigureNixDaemonService {
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(ActionError::Command)?;
|
.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");
|
tracing::trace!(src = TMPFILES_SRC, dest = TMPFILES_DEST, "Symlinking");
|
||||||
tokio::fs::symlink(TMPFILES_SRC, TMPFILES_DEST)
|
tokio::fs::symlink(TMPFILES_SRC, TMPFILES_DEST)
|
||||||
.await
|
.await
|
||||||
|
@ -158,24 +177,30 @@ impl Action for ConfigureNixDaemonService {
|
||||||
.await
|
.await
|
||||||
.map_err(ActionError::Command)?;
|
.map_err(ActionError::Command)?;
|
||||||
|
|
||||||
execute_command(
|
if *start_daemon {
|
||||||
Command::new("systemctl")
|
execute_command(
|
||||||
.process_group(0)
|
Command::new("systemctl")
|
||||||
.arg("daemon-reload")
|
.process_group(0)
|
||||||
.stdin(std::process::Stdio::null()),
|
.arg("daemon-reload")
|
||||||
)
|
.stdin(std::process::Stdio::null()),
|
||||||
.await
|
)
|
||||||
.map_err(ActionError::Command)?;
|
.await
|
||||||
|
.map_err(ActionError::Command)?;
|
||||||
|
|
||||||
execute_command(
|
execute_command(
|
||||||
Command::new("systemctl")
|
Command::new("systemctl")
|
||||||
.process_group(0)
|
.process_group(0)
|
||||||
.arg("enable")
|
.arg("enable")
|
||||||
.arg("--now")
|
.arg("--now")
|
||||||
.arg(SOCKET_SRC),
|
.arg(SOCKET_SRC),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(ActionError::Command)?;
|
.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> {
|
fn revert_description(&self) -> Vec<ActionDescription> {
|
||||||
match OperatingSystem::host() {
|
match self.init {
|
||||||
OperatingSystem::MacOSX {
|
#[cfg(target_os = "linux")]
|
||||||
major: _,
|
InitSystem::Systemd => {
|
||||||
minor: _,
|
vec![ActionDescription::new(
|
||||||
patch: _,
|
"Unconfigure Nix daemon related settings with systemd".to_string(),
|
||||||
}
|
vec![
|
||||||
| OperatingSystem::Darwin => vec![ActionDescription::new(
|
"Run `systemctl disable {SOCKET_SRC}`".to_string(),
|
||||||
"Unconfigure Nix daemon related settings with launchd".to_string(),
|
"Run `systemctl disable {SERVICE_SRC}`".to_string(),
|
||||||
vec!["Run `launchctl unload {DARWIN_NIX_DAEMON_DEST}`".to_string()],
|
"Run `systemd-tempfiles --remove --prefix=/nix/var/nix`".to_string(),
|
||||||
)],
|
"Run `systemctl daemon-reload`".to_string(),
|
||||||
_ => vec![ActionDescription::new(
|
],
|
||||||
"Unconfigure Nix daemon related settings with systemd".to_string(),
|
)]
|
||||||
vec![
|
},
|
||||||
"Run `systemctl disable {SOCKET_SRC}`".to_string(),
|
#[cfg(target_os = "macos")]
|
||||||
"Run `systemctl disable {SERVICE_SRC}`".to_string(),
|
InitSystem::Launchd => {
|
||||||
"Run `systemd-tempfiles --remove --prefix=/nix/var/nix`".to_string(),
|
vec![ActionDescription::new(
|
||||||
"Run `systemctl daemon-reload`".to_string(),
|
"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)]
|
#[tracing::instrument(level = "debug", skip_all)]
|
||||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||||
match OperatingSystem::host() {
|
match self.init {
|
||||||
OperatingSystem::MacOSX {
|
#[cfg(target_os = "macos")]
|
||||||
major: _,
|
InitSystem::Launchd => {
|
||||||
minor: _,
|
|
||||||
patch: _,
|
|
||||||
}
|
|
||||||
| OperatingSystem::Darwin => {
|
|
||||||
execute_command(
|
execute_command(
|
||||||
Command::new("launchctl")
|
Command::new("launchctl")
|
||||||
.process_group(0)
|
.process_group(0)
|
||||||
|
@ -223,7 +247,8 @@ impl Action for ConfigureNixDaemonService {
|
||||||
.await
|
.await
|
||||||
.map_err(ActionError::Command)?;
|
.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.
|
// 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?;
|
let socket_is_active = is_active("nix-daemon.socket").await?;
|
||||||
|
@ -285,7 +310,7 @@ impl Action for ConfigureNixDaemonService {
|
||||||
.await
|
.await
|
||||||
.map_err(ActionError::Command)?;
|
.map_err(ActionError::Command)?;
|
||||||
|
|
||||||
remove_file(TMPFILES_DEST)
|
tokio::fs::remove_file(TMPFILES_DEST)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ActionError::Remove(PathBuf::from(TMPFILES_DEST), e))?;
|
.map_err(|e| ActionError::Remove(PathBuf::from(TMPFILES_DEST), e))?;
|
||||||
|
|
||||||
|
@ -298,6 +323,10 @@ impl Action for ConfigureNixDaemonService {
|
||||||
.await
|
.await
|
||||||
.map_err(ActionError::Command)?;
|
.map_err(ActionError::Command)?;
|
||||||
},
|
},
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
InitSystem::None => {
|
||||||
|
// Nothing here, no init
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -310,6 +339,7 @@ pub enum ConfigureNixDaemonServiceError {
|
||||||
InitNotSupported,
|
InitNotSupported,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
async fn is_active(unit: &str) -> Result<bool, ActionError> {
|
async fn is_active(unit: &str) -> Result<bool, ActionError> {
|
||||||
let output = Command::new("systemctl")
|
let output = Command::new("systemctl")
|
||||||
.arg("is-active")
|
.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> {
|
async fn is_enabled(unit: &str) -> Result<bool, ActionError> {
|
||||||
let output = Command::new("systemctl")
|
let output = Command::new("systemctl")
|
||||||
.arg("is-enabled")
|
.arg("is-enabled")
|
|
@ -1,17 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
action::{
|
action::{
|
||||||
base::SetupDefaultProfile,
|
base::SetupDefaultProfile,
|
||||||
common::{
|
common::{ConfigureShellProfile, PlaceChannelConfiguration, PlaceNixConfiguration},
|
||||||
ConfigureNixDaemonService, ConfigureShellProfile, PlaceChannelConfiguration,
|
|
||||||
PlaceNixConfiguration,
|
|
||||||
},
|
|
||||||
Action, ActionDescription, ActionError, StatefulAction,
|
Action, ActionDescription, ActionError, StatefulAction,
|
||||||
},
|
},
|
||||||
channel_value::ChannelValue,
|
|
||||||
settings::CommonSettings,
|
settings::CommonSettings,
|
||||||
};
|
};
|
||||||
|
|
||||||
use reqwest::Url;
|
|
||||||
use tracing::{span, Instrument, Span};
|
use tracing::{span, Instrument, Span};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,20 +18,12 @@ pub struct ConfigureNix {
|
||||||
configure_shell_profile: Option<StatefulAction<ConfigureShellProfile>>,
|
configure_shell_profile: Option<StatefulAction<ConfigureShellProfile>>,
|
||||||
place_channel_configuration: StatefulAction<PlaceChannelConfiguration>,
|
place_channel_configuration: StatefulAction<PlaceChannelConfiguration>,
|
||||||
place_nix_configuration: StatefulAction<PlaceNixConfiguration>,
|
place_nix_configuration: StatefulAction<PlaceNixConfiguration>,
|
||||||
configure_nix_daemon_service: StatefulAction<ConfigureNixDaemonService>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigureNix {
|
impl ConfigureNix {
|
||||||
#[tracing::instrument(level = "debug", skip_all)]
|
#[tracing::instrument(level = "debug", skip_all)]
|
||||||
pub async fn plan(settings: &CommonSettings) -> Result<StatefulAction<Self>, ActionError> {
|
pub async fn plan(settings: &CommonSettings) -> Result<StatefulAction<Self>, ActionError> {
|
||||||
let channels: Vec<(String, Url)> = settings
|
let setup_default_profile = SetupDefaultProfile::plan(settings.channels.clone()).await?;
|
||||||
.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 configure_shell_profile = if settings.modify_profile {
|
let configure_shell_profile = if settings.modify_profile {
|
||||||
Some(ConfigureShellProfile::plan().await?)
|
Some(ConfigureShellProfile::plan().await?)
|
||||||
|
@ -44,20 +31,18 @@ impl ConfigureNix {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let place_channel_configuration =
|
let place_channel_configuration =
|
||||||
PlaceChannelConfiguration::plan(channels, settings.force).await?;
|
PlaceChannelConfiguration::plan(settings.channels.clone(), settings.force).await?;
|
||||||
let place_nix_configuration = PlaceNixConfiguration::plan(
|
let place_nix_configuration = PlaceNixConfiguration::plan(
|
||||||
settings.nix_build_group_name.clone(),
|
settings.nix_build_group_name.clone(),
|
||||||
settings.extra_conf.clone(),
|
settings.extra_conf.clone(),
|
||||||
settings.force,
|
settings.force,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let configure_nix_daemon_service = ConfigureNixDaemonService::plan().await?;
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
place_channel_configuration,
|
place_channel_configuration,
|
||||||
place_nix_configuration,
|
place_nix_configuration,
|
||||||
setup_default_profile,
|
setup_default_profile,
|
||||||
configure_nix_daemon_service,
|
|
||||||
configure_shell_profile,
|
configure_shell_profile,
|
||||||
}
|
}
|
||||||
.into())
|
.into())
|
||||||
|
@ -78,14 +63,12 @@ impl Action for ConfigureNix {
|
||||||
fn execute_description(&self) -> Vec<ActionDescription> {
|
fn execute_description(&self) -> Vec<ActionDescription> {
|
||||||
let Self {
|
let Self {
|
||||||
setup_default_profile,
|
setup_default_profile,
|
||||||
configure_nix_daemon_service,
|
|
||||||
place_nix_configuration,
|
place_nix_configuration,
|
||||||
place_channel_configuration,
|
place_channel_configuration,
|
||||||
configure_shell_profile,
|
configure_shell_profile,
|
||||||
} = &self;
|
} = &self;
|
||||||
|
|
||||||
let mut buf = setup_default_profile.describe_execute();
|
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_nix_configuration.describe_execute());
|
||||||
buf.append(&mut place_channel_configuration.describe_execute());
|
buf.append(&mut place_channel_configuration.describe_execute());
|
||||||
if let Some(configure_shell_profile) = configure_shell_profile {
|
if let Some(configure_shell_profile) = configure_shell_profile {
|
||||||
|
@ -98,7 +81,6 @@ impl Action for ConfigureNix {
|
||||||
async fn execute(&mut self) -> Result<(), ActionError> {
|
async fn execute(&mut self) -> Result<(), ActionError> {
|
||||||
let Self {
|
let Self {
|
||||||
setup_default_profile,
|
setup_default_profile,
|
||||||
configure_nix_daemon_service,
|
|
||||||
place_nix_configuration,
|
place_nix_configuration,
|
||||||
place_channel_configuration,
|
place_channel_configuration,
|
||||||
configure_shell_profile,
|
configure_shell_profile,
|
||||||
|
@ -168,7 +150,6 @@ impl Action for ConfigureNix {
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
};
|
};
|
||||||
configure_nix_daemon_service.try_execute().await?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -176,7 +157,6 @@ impl Action for ConfigureNix {
|
||||||
fn revert_description(&self) -> Vec<ActionDescription> {
|
fn revert_description(&self) -> Vec<ActionDescription> {
|
||||||
let Self {
|
let Self {
|
||||||
setup_default_profile,
|
setup_default_profile,
|
||||||
configure_nix_daemon_service,
|
|
||||||
place_nix_configuration,
|
place_nix_configuration,
|
||||||
place_channel_configuration,
|
place_channel_configuration,
|
||||||
configure_shell_profile,
|
configure_shell_profile,
|
||||||
|
@ -188,7 +168,6 @@ impl Action for ConfigureNix {
|
||||||
}
|
}
|
||||||
buf.append(&mut place_channel_configuration.describe_revert());
|
buf.append(&mut place_channel_configuration.describe_revert());
|
||||||
buf.append(&mut place_nix_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.append(&mut setup_default_profile.describe_revert());
|
||||||
|
|
||||||
buf
|
buf
|
||||||
|
@ -198,13 +177,11 @@ impl Action for ConfigureNix {
|
||||||
async fn revert(&mut self) -> Result<(), ActionError> {
|
async fn revert(&mut self) -> Result<(), ActionError> {
|
||||||
let Self {
|
let Self {
|
||||||
setup_default_profile,
|
setup_default_profile,
|
||||||
configure_nix_daemon_service,
|
|
||||||
place_nix_configuration,
|
place_nix_configuration,
|
||||||
place_channel_configuration,
|
place_channel_configuration,
|
||||||
configure_shell_profile,
|
configure_shell_profile,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
configure_nix_daemon_service.try_revert().await?;
|
|
||||||
if let Some(configure_shell_profile) = configure_shell_profile {
|
if let Some(configure_shell_profile) = configure_shell_profile {
|
||||||
configure_shell_profile.try_revert().await?;
|
configure_shell_profile.try_revert().await?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! [`Action`](crate::action::Action)s which only call other base plugins
|
//! [`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;
|
||||||
pub(crate) mod configure_nix_daemon_service;
|
|
||||||
pub(crate) mod configure_shell_profile;
|
pub(crate) mod configure_shell_profile;
|
||||||
pub(crate) mod create_nix_tree;
|
pub(crate) mod create_nix_tree;
|
||||||
pub(crate) mod create_users_and_groups;
|
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 place_nix_configuration;
|
||||||
pub(crate) mod provision_nix;
|
pub(crate) mod provision_nix;
|
||||||
|
|
||||||
|
pub use configure_init_service::{ConfigureInitService, ConfigureNixDaemonServiceError};
|
||||||
pub use configure_nix::ConfigureNix;
|
pub use configure_nix::ConfigureNix;
|
||||||
pub use configure_nix_daemon_service::{ConfigureNixDaemonService, ConfigureNixDaemonServiceError};
|
|
||||||
pub use configure_shell_profile::ConfigureShellProfile;
|
pub use configure_shell_profile::ConfigureShellProfile;
|
||||||
pub use create_nix_tree::CreateNixTree;
|
pub use create_nix_tree::CreateNixTree;
|
||||||
pub use create_users_and_groups::CreateUsersAndGroups;
|
pub use create_users_and_groups::CreateUsersAndGroups;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::action::base::CreateFile;
|
use crate::action::base::CreateFile;
|
||||||
use crate::action::ActionError;
|
use crate::action::ActionError;
|
||||||
use crate::action::{Action, ActionDescription, StatefulAction};
|
use crate::action::{Action, ActionDescription, StatefulAction};
|
||||||
use reqwest::Url;
|
use crate::ChannelValue;
|
||||||
use tracing::{span, Span};
|
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)]
|
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||||
pub struct PlaceChannelConfiguration {
|
pub struct PlaceChannelConfiguration {
|
||||||
channels: Vec<(String, Url)>,
|
channels: Vec<ChannelValue>,
|
||||||
create_file: StatefulAction<CreateFile>,
|
create_file: StatefulAction<CreateFile>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlaceChannelConfiguration {
|
impl PlaceChannelConfiguration {
|
||||||
#[tracing::instrument(level = "debug", skip_all)]
|
#[tracing::instrument(level = "debug", skip_all)]
|
||||||
pub async fn plan(
|
pub async fn plan(
|
||||||
channels: Vec<(String, Url)>,
|
channels: Vec<ChannelValue>,
|
||||||
force: bool,
|
force: bool,
|
||||||
) -> Result<StatefulAction<Self>, ActionError> {
|
) -> Result<StatefulAction<Self>, ActionError> {
|
||||||
let buf = channels
|
let buf = channels
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, url)| format!("{} {}", url, name))
|
.map(|ChannelValue(name, url)| format!("{} {}", url, name))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n");
|
.join("\n");
|
||||||
let create_file = CreateFile::plan(
|
let create_file = CreateFile::plan(
|
||||||
|
@ -62,7 +62,7 @@ impl Action for PlaceChannelConfiguration {
|
||||||
channels = self
|
channels = self
|
||||||
.channels
|
.channels
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(c, u)| format!("{c}={u}"))
|
.map(|ChannelValue(c, u)| format!("{c}={u}"))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", "),
|
.join(", "),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,19 +1,13 @@
|
||||||
use nix::unistd::{chown, Group, User};
|
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
action::{Action, ActionDescription, ActionError, StatefulAction},
|
action::{Action, ActionDescription, ActionError, StatefulAction},
|
||||||
execute_command,
|
execute_command,
|
||||||
};
|
};
|
||||||
use rand::Rng;
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{
|
use std::{io::SeekFrom, path::Path};
|
||||||
io::SeekFrom,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
str::FromStr,
|
|
||||||
};
|
|
||||||
use tokio::{
|
use tokio::{
|
||||||
fs::{remove_file, OpenOptions},
|
fs::OpenOptions,
|
||||||
io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt},
|
io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt},
|
||||||
process::Command,
|
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 create_synthetic_objects;
|
||||||
pub(crate) mod enable_ownership;
|
pub(crate) mod enable_ownership;
|
||||||
pub(crate) mod encrypt_apfs_volume;
|
pub(crate) mod encrypt_apfs_volume;
|
||||||
pub(crate) mod kickstart_launchctl_service;
|
|
||||||
pub(crate) mod unmount_apfs_volume;
|
pub(crate) mod unmount_apfs_volume;
|
||||||
|
|
||||||
pub use bootstrap_apfs_volume::{BootstrapApfsVolume, BootstrapVolumeError};
|
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 create_synthetic_objects::{CreateSyntheticObjects, CreateSyntheticObjectsError};
|
||||||
pub use enable_ownership::{EnableOwnership, EnableOwnershipError};
|
pub use enable_ownership::{EnableOwnership, EnableOwnershipError};
|
||||||
pub use encrypt_apfs_volume::EncryptApfsVolume;
|
pub use encrypt_apfs_volume::EncryptApfsVolume;
|
||||||
pub use kickstart_launchctl_service::KickstartLaunchctlService;
|
|
||||||
pub use unmount_apfs_volume::UnmountApfsVolume;
|
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
|
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
|
example of this, it takes several steps, such as running `systemd-tmpfiles`, and calling
|
||||||
`systemctl link` on some systemd units.
|
`systemctl link` on some systemd units.
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ use tracing::{Span, span};
|
||||||
use nix_installer::{
|
use nix_installer::{
|
||||||
InstallPlan,
|
InstallPlan,
|
||||||
settings::{CommonSettings, InstallSettingsError},
|
settings::{CommonSettings, InstallSettingsError},
|
||||||
planner::{Planner, PlannerError, linux::SteamDeck},
|
planner::{Planner, PlannerError},
|
||||||
action::{Action, ActionError, StatefulAction, ActionDescription},
|
action::{Action, ActionError, StatefulAction, ActionDescription},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ pub struct MyPlanner {
|
||||||
impl Planner for MyPlanner {
|
impl Planner for MyPlanner {
|
||||||
async fn default() -> Result<Self, PlannerError> {
|
async fn default() -> Result<Self, PlannerError> {
|
||||||
Ok(Self {
|
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
|
```rust,no_run
|
||||||
use std::error::Error;
|
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<()> {
|
# 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()`
|
// Or call `crate::planner::BuiltinPlanner::default()`
|
||||||
// Match on the result to customize.
|
// Match on the result to customize.
|
||||||
|
|
|
@ -6,15 +6,15 @@ use tokio::process::Command;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
action::{
|
action::{
|
||||||
common::{ConfigureNix, ProvisionNix},
|
common::{ConfigureInitService, ConfigureNix, ProvisionNix},
|
||||||
darwin::{CreateNixVolume, KickstartLaunchctlService},
|
darwin::CreateNixVolume,
|
||||||
StatefulAction,
|
StatefulAction,
|
||||||
},
|
},
|
||||||
execute_command,
|
execute_command,
|
||||||
os::darwin::DiskUtilOutput,
|
os::darwin::DiskUtilOutput,
|
||||||
planner::{Planner, PlannerError},
|
planner::{Planner, PlannerError},
|
||||||
settings::CommonSettings,
|
|
||||||
settings::InstallSettingsError,
|
settings::InstallSettingsError,
|
||||||
|
settings::{CommonSettings, InitSystem},
|
||||||
Action, BuiltinPlanner,
|
Action, BuiltinPlanner,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ use crate::{
|
||||||
pub struct DarwinMulti {
|
pub struct DarwinMulti {
|
||||||
#[cfg_attr(feature = "cli", clap(flatten))]
|
#[cfg_attr(feature = "cli", clap(flatten))]
|
||||||
pub settings: CommonSettings,
|
pub settings: CommonSettings,
|
||||||
|
|
||||||
/// Force encryption on the volume
|
/// Force encryption on the volume
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "cli",
|
feature = "cli",
|
||||||
|
@ -76,7 +77,7 @@ async fn default_root_disk() -> Result<String, PlannerError> {
|
||||||
impl Planner for DarwinMulti {
|
impl Planner for DarwinMulti {
|
||||||
async fn default() -> Result<Self, PlannerError> {
|
async fn default() -> Result<Self, PlannerError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
settings: CommonSettings::default()?,
|
settings: CommonSettings::default().await?,
|
||||||
root_disk: Some(default_root_disk().await?),
|
root_disk: Some(default_root_disk().await?),
|
||||||
case_sensitive: false,
|
case_sensitive: false,
|
||||||
encrypt: None,
|
encrypt: None,
|
||||||
|
@ -140,7 +141,7 @@ impl Planner for DarwinMulti {
|
||||||
.await
|
.await
|
||||||
.map_err(PlannerError::Action)?
|
.map_err(PlannerError::Action)?
|
||||||
.boxed(),
|
.boxed(),
|
||||||
KickstartLaunchctlService::plan("system/org.nixos.nix-daemon".into())
|
ConfigureInitService::plan(InitSystem::Launchd, true)
|
||||||
.await
|
.await
|
||||||
.map_err(PlannerError::Action)?
|
.map_err(PlannerError::Action)?
|
||||||
.boxed(),
|
.boxed(),
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
action::{
|
action::{
|
||||||
base::CreateDirectory,
|
base::CreateDirectory,
|
||||||
common::{ConfigureNix, ProvisionNix},
|
common::{ConfigureInitService, ConfigureNix, ProvisionNix},
|
||||||
StatefulAction,
|
StatefulAction,
|
||||||
},
|
},
|
||||||
planner::{Planner, PlannerError},
|
planner::{Planner, PlannerError},
|
||||||
settings::CommonSettings,
|
settings::CommonSettings,
|
||||||
settings::InstallSettingsError,
|
settings::{InitSettings, InstallSettingsError},
|
||||||
Action, BuiltinPlanner,
|
Action, BuiltinPlanner,
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, path::Path};
|
use std::{collections::HashMap, path::Path};
|
||||||
|
@ -18,6 +18,8 @@ use tokio::process::Command;
|
||||||
pub struct LinuxMulti {
|
pub struct LinuxMulti {
|
||||||
#[cfg_attr(feature = "cli", clap(flatten))]
|
#[cfg_attr(feature = "cli", clap(flatten))]
|
||||||
pub settings: CommonSettings,
|
pub settings: CommonSettings,
|
||||||
|
#[cfg_attr(feature = "cli", clap(flatten))]
|
||||||
|
pub init: InitSettings,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
|
@ -25,7 +27,8 @@ pub struct LinuxMulti {
|
||||||
impl Planner for LinuxMulti {
|
impl Planner for LinuxMulti {
|
||||||
async fn default() -> Result<Self, PlannerError> {
|
async fn default() -> Result<Self, PlannerError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
settings: CommonSettings::default()?,
|
settings: CommonSettings::default().await?,
|
||||||
|
init: InitSettings::default().await?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,14 +80,19 @@ impl Planner for LinuxMulti {
|
||||||
.await
|
.await
|
||||||
.map_err(PlannerError::Action)?
|
.map_err(PlannerError::Action)?
|
||||||
.boxed(),
|
.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> {
|
fn settings(&self) -> Result<HashMap<String, serde_json::Value>, InstallSettingsError> {
|
||||||
let Self { settings } = self;
|
let Self { settings, init } = self;
|
||||||
let mut map = HashMap::default();
|
let mut map = HashMap::default();
|
||||||
|
|
||||||
map.extend(settings.settings()?.into_iter());
|
map.extend(settings.settings()?.into_iter());
|
||||||
|
map.extend(init.settings()?.into_iter());
|
||||||
|
|
||||||
Ok(map)
|
Ok(map)
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,12 +64,12 @@ use std::{collections::HashMap, path::PathBuf};
|
||||||
use crate::{
|
use crate::{
|
||||||
action::{
|
action::{
|
||||||
base::{CreateDirectory, CreateFile},
|
base::{CreateDirectory, CreateFile},
|
||||||
common::{ConfigureNix, ProvisionNix},
|
common::{ConfigureInitService, ConfigureNix, ProvisionNix},
|
||||||
linux::StartSystemdUnit,
|
linux::StartSystemdUnit,
|
||||||
Action, StatefulAction,
|
Action, StatefulAction,
|
||||||
},
|
},
|
||||||
planner::{Planner, PlannerError},
|
planner::{Planner, PlannerError},
|
||||||
settings::{CommonSettings, InstallSettingsError},
|
settings::{CommonSettings, InitSystem, InstallSettingsError},
|
||||||
BuiltinPlanner,
|
BuiltinPlanner,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ impl Planner for SteamDeck {
|
||||||
async fn default() -> Result<Self, PlannerError> {
|
async fn default() -> Result<Self, PlannerError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
persistence: PathBuf::from("/home/nix"),
|
persistence: PathBuf::from("/home/nix"),
|
||||||
settings: CommonSettings::default()?,
|
settings: CommonSettings::default().await?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,6 +225,11 @@ impl Planner for SteamDeck {
|
||||||
.await
|
.await
|
||||||
.map_err(PlannerError::Action)?
|
.map_err(PlannerError::Action)?
|
||||||
.boxed(),
|
.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`]
|
/*! [`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,
|
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.
|
||||||
like [`LinuxMulti`](linux::LinuxMulti), are operating system specific. Others, like [`SteamDeck`](linux::SteamDeck), are device specific.
|
|
||||||
|
|
||||||
[`Planner`]s contain their planner specific settings, typically alongside a [`CommonSettings`][crate::settings::CommonSettings].
|
[`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::{
|
use nix_installer::{
|
||||||
InstallPlan,
|
InstallPlan,
|
||||||
settings::{CommonSettings, InstallSettingsError},
|
settings::{CommonSettings, InstallSettingsError},
|
||||||
planner::{Planner, PlannerError, linux::SteamDeck},
|
planner::{Planner, PlannerError},
|
||||||
action::{Action, StatefulAction, linux::StartSystemdUnit},
|
action::{Action, StatefulAction, base::CreateFile},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
@ -31,7 +30,7 @@ pub struct MyPlanner {
|
||||||
impl Planner for MyPlanner {
|
impl Planner for MyPlanner {
|
||||||
async fn default() -> Result<Self, PlannerError> {
|
async fn default() -> Result<Self, PlannerError> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
common: CommonSettings::default()?,
|
common: CommonSettings::default().await?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +38,7 @@ impl Planner for MyPlanner {
|
||||||
Ok(vec![
|
Ok(vec![
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
StartSystemdUnit::plan("nix-daemon.socket")
|
CreateFile::plan("/example", None, None, None, "Example".to_string(), false)
|
||||||
.await
|
.await
|
||||||
.map_err(PlannerError::Action)?.boxed(),
|
.map_err(PlannerError::Action)?.boxed(),
|
||||||
])
|
])
|
||||||
|
@ -74,7 +73,9 @@ match plan.install(None).await {
|
||||||
```
|
```
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
pub mod darwin;
|
pub mod darwin;
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
pub mod linux;
|
pub mod linux;
|
||||||
|
|
||||||
use std::{collections::HashMap, string::FromUtf8Error};
|
use std::{collections::HashMap, string::FromUtf8Error};
|
||||||
|
@ -113,11 +114,14 @@ dyn_clone::clone_trait_object!(Planner);
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
#[cfg_attr(feature = "cli", derive(clap::Subcommand))]
|
#[cfg_attr(feature = "cli", derive(clap::Subcommand))]
|
||||||
pub enum BuiltinPlanner {
|
pub enum BuiltinPlanner {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
/// A standard Linux multi-user install
|
/// A standard Linux multi-user install
|
||||||
LinuxMulti(linux::LinuxMulti),
|
LinuxMulti(linux::LinuxMulti),
|
||||||
/// A standard MacOS (Darwin) multi-user install
|
/// A standard MacOS (Darwin) multi-user install
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
DarwinMulti(darwin::DarwinMulti),
|
DarwinMulti(darwin::DarwinMulti),
|
||||||
/// A specialized install suitable for the Valve Steam Deck console
|
/// A specialized install suitable for the Valve Steam Deck console
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
SteamDeck(linux::SteamDeck),
|
SteamDeck(linux::SteamDeck),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,16 +130,20 @@ impl BuiltinPlanner {
|
||||||
pub async fn default() -> Result<Self, PlannerError> {
|
pub async fn default() -> Result<Self, PlannerError> {
|
||||||
use target_lexicon::{Architecture, OperatingSystem};
|
use target_lexicon::{Architecture, OperatingSystem};
|
||||||
match (Architecture::host(), OperatingSystem::host()) {
|
match (Architecture::host(), OperatingSystem::host()) {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
(Architecture::X86_64, OperatingSystem::Linux) => {
|
(Architecture::X86_64, OperatingSystem::Linux) => {
|
||||||
Ok(Self::LinuxMulti(linux::LinuxMulti::default().await?))
|
Ok(Self::LinuxMulti(linux::LinuxMulti::default().await?))
|
||||||
},
|
},
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
(Architecture::Aarch64(_), OperatingSystem::Linux) => {
|
(Architecture::Aarch64(_), OperatingSystem::Linux) => {
|
||||||
Ok(Self::LinuxMulti(linux::LinuxMulti::default().await?))
|
Ok(Self::LinuxMulti(linux::LinuxMulti::default().await?))
|
||||||
},
|
},
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
(Architecture::X86_64, OperatingSystem::MacOSX { .. })
|
(Architecture::X86_64, OperatingSystem::MacOSX { .. })
|
||||||
| (Architecture::X86_64, OperatingSystem::Darwin) => {
|
| (Architecture::X86_64, OperatingSystem::Darwin) => {
|
||||||
Ok(Self::DarwinMulti(darwin::DarwinMulti::default().await?))
|
Ok(Self::DarwinMulti(darwin::DarwinMulti::default().await?))
|
||||||
},
|
},
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
(Architecture::Aarch64(_), OperatingSystem::MacOSX { .. })
|
(Architecture::Aarch64(_), OperatingSystem::MacOSX { .. })
|
||||||
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => {
|
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => {
|
||||||
Ok(Self::DarwinMulti(darwin::DarwinMulti::default().await?))
|
Ok(Self::DarwinMulti(darwin::DarwinMulti::default().await?))
|
||||||
|
@ -147,41 +155,56 @@ impl BuiltinPlanner {
|
||||||
pub async fn from_common_settings(settings: CommonSettings) -> Result<Self, PlannerError> {
|
pub async fn from_common_settings(settings: CommonSettings) -> Result<Self, PlannerError> {
|
||||||
let mut built = Self::default().await?;
|
let mut built = Self::default().await?;
|
||||||
match &mut built {
|
match &mut built {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
BuiltinPlanner::LinuxMulti(inner) => inner.settings = settings,
|
BuiltinPlanner::LinuxMulti(inner) => inner.settings = settings,
|
||||||
BuiltinPlanner::DarwinMulti(inner) => inner.settings = settings,
|
#[cfg(target_os = "linux")]
|
||||||
BuiltinPlanner::SteamDeck(inner) => inner.settings = settings,
|
BuiltinPlanner::SteamDeck(inner) => inner.settings = settings,
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
BuiltinPlanner::DarwinMulti(inner) => inner.settings = settings,
|
||||||
}
|
}
|
||||||
Ok(built)
|
Ok(built)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn plan(self) -> Result<InstallPlan, NixInstallerError> {
|
pub async fn plan(self) -> Result<InstallPlan, NixInstallerError> {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
BuiltinPlanner::LinuxMulti(planner) => InstallPlan::plan(planner).await,
|
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,
|
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> {
|
pub fn boxed(self) -> Box<dyn Planner> {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
BuiltinPlanner::LinuxMulti(i) => i.boxed(),
|
BuiltinPlanner::LinuxMulti(i) => i.boxed(),
|
||||||
BuiltinPlanner::DarwinMulti(i) => i.boxed(),
|
#[cfg(target_os = "linux")]
|
||||||
BuiltinPlanner::SteamDeck(i) => i.boxed(),
|
BuiltinPlanner::SteamDeck(i) => i.boxed(),
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
BuiltinPlanner::DarwinMulti(i) => i.boxed(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn typetag_name(&self) -> &'static str {
|
pub fn typetag_name(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
BuiltinPlanner::LinuxMulti(i) => i.typetag_name(),
|
BuiltinPlanner::LinuxMulti(i) => i.typetag_name(),
|
||||||
BuiltinPlanner::DarwinMulti(i) => i.typetag_name(),
|
#[cfg(target_os = "linux")]
|
||||||
BuiltinPlanner::SteamDeck(i) => i.typetag_name(),
|
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> {
|
pub fn settings(&self) -> Result<HashMap<String, serde_json::Value>, InstallSettingsError> {
|
||||||
match self {
|
match self {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
BuiltinPlanner::LinuxMulti(i) => i.settings(),
|
BuiltinPlanner::LinuxMulti(i) => i.settings(),
|
||||||
BuiltinPlanner::DarwinMulti(i) => i.settings(),
|
#[cfg(target_os = "linux")]
|
||||||
BuiltinPlanner::SteamDeck(i) => i.settings(),
|
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 =
|
pub const NIX_AARCH64_DARWIN_URL: &str =
|
||||||
"https://releases.nixos.org/nix/nix-2.12.0/nix-2.12.0-aarch64-darwin.tar.xz";
|
"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
|
/** 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.
|
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 {
|
impl CommonSettings {
|
||||||
/// The default settings for the given Architecture & Operating System
|
/// 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 url;
|
||||||
let nix_build_user_prefix;
|
let nix_build_user_prefix;
|
||||||
let nix_build_user_id_base;
|
let nix_build_user_id_base;
|
||||||
|
|
||||||
use target_lexicon::{Architecture, OperatingSystem};
|
use target_lexicon::{Architecture, OperatingSystem};
|
||||||
match (Architecture::host(), OperatingSystem::host()) {
|
match (Architecture::host(), OperatingSystem::host()) {
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
(Architecture::X86_64, OperatingSystem::Linux) => {
|
(Architecture::X86_64, OperatingSystem::Linux) => {
|
||||||
url = NIX_X64_64_LINUX_URL;
|
url = NIX_X64_64_LINUX_URL;
|
||||||
nix_build_user_prefix = "nixbld";
|
nix_build_user_prefix = "nixbld";
|
||||||
nix_build_user_id_base = 3000;
|
nix_build_user_id_base = 3000;
|
||||||
},
|
},
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
(Architecture::Aarch64(_), OperatingSystem::Linux) => {
|
(Architecture::Aarch64(_), OperatingSystem::Linux) => {
|
||||||
url = NIX_AARCH64_LINUX_URL;
|
url = NIX_AARCH64_LINUX_URL;
|
||||||
nix_build_user_prefix = "nixbld";
|
nix_build_user_prefix = "nixbld";
|
||||||
nix_build_user_id_base = 3000;
|
nix_build_user_id_base = 3000;
|
||||||
},
|
},
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
(Architecture::X86_64, OperatingSystem::MacOSX { .. })
|
(Architecture::X86_64, OperatingSystem::MacOSX { .. })
|
||||||
| (Architecture::X86_64, OperatingSystem::Darwin) => {
|
| (Architecture::X86_64, OperatingSystem::Darwin) => {
|
||||||
url = NIX_X64_64_DARWIN_URL;
|
url = NIX_X64_64_DARWIN_URL;
|
||||||
nix_build_user_prefix = "_nixbld";
|
nix_build_user_prefix = "_nixbld";
|
||||||
nix_build_user_id_base = 300;
|
nix_build_user_id_base = 300;
|
||||||
},
|
},
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
(Architecture::Aarch64(_), OperatingSystem::MacOSX { .. })
|
(Architecture::Aarch64(_), OperatingSystem::MacOSX { .. })
|
||||||
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => {
|
| (Architecture::Aarch64(_), OperatingSystem::Darwin) => {
|
||||||
url = NIX_AARCH64_DARWIN_URL;
|
url = NIX_AARCH64_DARWIN_URL;
|
||||||
|
@ -286,6 +314,34 @@ impl CommonSettings {
|
||||||
Ok(map)
|
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
|
// Builder Pattern
|
||||||
impl CommonSettings {
|
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)
|
/// An error originating from a [`Planner::settings`](crate::planner::Planner::settings)
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
pub enum InstallSettingsError {
|
pub enum InstallSettingsError {
|
||||||
|
@ -369,4 +515,6 @@ pub enum InstallSettingsError {
|
||||||
#[from]
|
#[from]
|
||||||
serde_json::Error,
|
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": {
|
"setup_default_profile": {
|
||||||
"action": {
|
"action": {
|
||||||
"channels": [
|
"channels": [
|
||||||
"nixpkgs"
|
[
|
||||||
|
"nixpkgs",
|
||||||
|
"https://nixos.org/channels/nixpkgs-unstable"
|
||||||
|
]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"state": "Uncompleted"
|
"state": "Uncompleted"
|
||||||
|
@ -632,25 +635,22 @@
|
||||||
"user": null,
|
"user": null,
|
||||||
"group": null,
|
"group": null,
|
||||||
"mode": 436,
|
"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
|
"force": false
|
||||||
},
|
},
|
||||||
"state": "Uncompleted"
|
"state": "Uncompleted"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"state": "Uncompleted"
|
"state": "Uncompleted"
|
||||||
},
|
|
||||||
"configure_nix_daemon_service": {
|
|
||||||
"action": {},
|
|
||||||
"state": "Uncompleted"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"state": "Uncompleted"
|
"state": "Uncompleted"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"action": {
|
"action": {
|
||||||
"action": "kickstart_launchctl_service",
|
"action": "configure_nix_daemon",
|
||||||
"unit": "system/org.nixos.nix-daemon"
|
"init": "Launchd",
|
||||||
|
"start_daemon": true
|
||||||
},
|
},
|
||||||
"state": "Uncompleted"
|
"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;
|
use nix_installer::InstallPlan;
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
const LINUX_MULTI: &str = include_str!("./fixtures/linux/linux-multi.json");
|
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");
|
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");
|
const DARWIN_MULTI: &str = include_str!("./fixtures/darwin/darwin-multi.json");
|
||||||
|
|
||||||
// Ensure existing plans still parse
|
// 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.
|
// 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]
|
#[test]
|
||||||
fn plan_compat_linux_multi() -> eyre::Result<()> {
|
fn plan_compat_linux_multi() -> eyre::Result<()> {
|
||||||
let _: InstallPlan = serde_json::from_str(LINUX_MULTI)?;
|
let _: InstallPlan = serde_json::from_str(LINUX_MULTI)?;
|
||||||
|
@ -14,6 +18,7 @@ fn plan_compat_linux_multi() -> eyre::Result<()> {
|
||||||
|
|
||||||
// Ensure existing plans still parse
|
// 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.
|
// 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]
|
#[test]
|
||||||
fn plan_compat_steam_deck() -> eyre::Result<()> {
|
fn plan_compat_steam_deck() -> eyre::Result<()> {
|
||||||
let _: InstallPlan = serde_json::from_str(STEAM_DECK)?;
|
let _: InstallPlan = serde_json::from_str(STEAM_DECK)?;
|
||||||
|
@ -22,6 +27,7 @@ fn plan_compat_steam_deck() -> eyre::Result<()> {
|
||||||
|
|
||||||
// Ensure existing plans still parse
|
// 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.
|
// 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]
|
#[test]
|
||||||
fn plan_compat_darwin_multi() -> eyre::Result<()> {
|
fn plan_compat_darwin_multi() -> eyre::Result<()> {
|
||||||
let _: InstallPlan = serde_json::from_str(DARWIN_MULTI)?;
|
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