Compare commits

...

10 commits

Author SHA1 Message Date
Artemis Tosini e8a1fcf537
Support downloading nix from substituters
Currently lix-installer requires a lix distribution tarball
downloaded over HTTP or on the system, meaning releases
require manual effort to place files in the correct place.

Add an option to download lix instead from standard nix substituters,
such as cache.nixos.org and cache.lix.systems.
Priority and nar parsing code do not exactly match lix,
but are sufficient to securely download and install nars.

Co-authored-by: Skye <me@skye-c.at>
Change-Id: Ia8a771ad2a99ac461cf5839a52e45f9dca65f3c8
2024-07-19 20:19:58 +00:00
jade 9b02b774bb Update version to 2.90.0
Change-Id: I7019ce4188061e9481add774938f5b20c785a416
2024-07-10 19:10:49 +02:00
jade 8d04ca8d3d Fix the contributing documentation for Lix, some
Some. There's still a bunch of stuff that's busted and we need to fix it
up.

Change-Id: Id9fe1fc054616df34045340ec3b02dda723f1d9c
2024-06-15 20:07:34 -07:00
jade 0256e915e7 Fix various bugs in the tests such that Lix works now
- We were looking for a top-level tarball path that looked like nix-*.
  This was invalid, since our tarballs have lix-*.
- We were looking for a store path that looked like nix-*.*.*. This was
  invalid, since ours is lix-*.*.*.

  This change accepts both.
- We also added a symlink for nix-installer and nix-installer.sh, which
  deals with the test suite being pretty tightly coupled to that path.
- We fixed a bug exposed in the tests where --no-substitute is not
  passed while self-testing builds. This seems to have been relying on
  offline detection and while it eventually passed, it was busted and
  took ages.

Change-Id: I2f497bd647ecf1db5963a4bb245279db582d2af3
2024-06-15 20:03:03 -07:00
jade 4a4f16676d Update version to 2.90.0-rc1
Change-Id: I05f3efd6663bec418ce93fb2dca53977d3523f7d
2024-06-14 21:12:44 -07:00
Artemis Tosini f1a45806c7
flake: test using lix
Previously we used a nix install tarball built from nix 2.20.5,
download with flakehub.

That does not make sense for a lix installer, use Lix 2.90 beta 1
instead.

Also use this opportunity to remove the unused flake-compat input.

Change-Id: I622bb9fedb45f3a03c1e5f43757afbd0222c6b90
2024-06-02 01:41:14 +00:00
Artemis Tosini 9705a12ec0
tests: Fix container and VM tests
The `nix-installer-static` package is now named `lix-installer-static`.
However, the uninstall binary is still called `nix-installer`

Change-Id: I60fd2ab84867beaa8cf527e88c953298ec703881
2024-06-02 00:51:12 +00:00
Artemis Tosini 85bbfe3d7c
lix-installer.sh: rename
The flake build relies on the name lix-installer.sh.
Rename nix-installer.sh to lix-installer.sh and, AFAICT,
all references

Change-Id: I4f2594e9a38d5489de6be092ce97dcb247627aca
2024-06-02 00:51:02 +00:00
Artemis Tosini f6ee8eeda8
treewide: s/nix_installer/lix_installer/ where needed
Not all references to the crate name were caught when it was changed.
Some tests rely on importing from `lix_installer` and filter directives
for the logs vary based on crate name.

Change-Id: I29acde8b96c823332a740dc69ef1847fdd89d967
2024-06-02 00:50:53 +00:00
Artemis Tosini cc9f65a03a
tests: fix json syntax error
When detsys-specific items were removed, some lines of JSON were
removed. This caused syntax errors due to the trailing commas.

Also use this opportunity to add `enable_flakes`, which is required
in new lix-installer plan files

Change-Id: I7874b3b19cb2e15f82b0733894c52b3a23c0cbe5
2024-06-02 00:50:39 +00:00
28 changed files with 1864 additions and 369 deletions

View file

@ -1,14 +1,14 @@
# Contributing to `nix-installer` # Contributing to `lix-installer`
We're excited to see what you'd like to contribute to `nix-installer`! We're excited to see what you'd like to contribute to `lix-installer`!
Regardless of what (or how much) you contribute to `nix-installer`, we value your time Regardless of what (or how much) you contribute to `lix-installer`, we value your time
and energy trying to improve the tool. and energy trying to improve the tool.
In order to ensure we all have a good experience, please review this document In order to ensure we all have a good experience, please review this document
if you have any questions about the process. if you have any questions about the process.
**Regular Rust committer?** Contributing to `nix-installer` should feel similar to **Regular Rust committer?** Contributing to `lix-installer` should feel similar to
contributing to other serious Rust ecosystem projects. You may already know contributing to other serious Rust ecosystem projects. You may already know
the process and expectations of you, this document shouldn't contain any the process and expectations of you, this document shouldn't contain any
surprises. surprises.
@ -16,7 +16,7 @@ surprises.
# What kinds of contributions are needed? # What kinds of contributions are needed?
`nix-installer` can benefit from all kinds of contributions: `lix-installer` can benefit from all kinds of contributions:
* Bug reports * Bug reports
* Code improvements * Code improvements
@ -27,33 +27,29 @@ surprises.
* Graphical/visual asset improvement * Graphical/visual asset improvement
* Kind words or recommendation on your own site, repo, stream, or social media * Kind words or recommendation on your own site, repo, stream, or social media
account account
* Onboarding others to using `nix-installer` * Onboarding others to using `lix-installer`
# What are the expectations you can have of the maintainers? # What are the expectations you can have of the maintainers?
You can expect us to: You can expect us to:
* Follow the [Contributor Covenant](CODE_OF_CONDUCT.md), just like you * Follow the [Lix community standards], just like you
* Help diagnose bug reports (for supported platforms using supported * Help diagnose bug reports (for supported platforms using supported
languages) languages)
* Give constructive feedback on pull requests * Give constructive feedback on changes
* Merge pull requests which: * Merge changes which:
+ Have been approved of by at least 1 maintainer + Have been approved of by at least 1 maintainer
+ Pass all tests + Pass all tests
+ Have no complex conflicts with in-flight high priority work + Have no complex conflicts with in-flight high priority work
The maintainers of this project use a separate issue tracker for some internal [Lix community standards]: https://lix.systems/community-standards/
tasks. Unfortunately, the contents of this tracker is not publicly visible as
it may contain sensitive or confidential data. Our maintainers will endeavor to
ensure you are not 'left out' of the discussion about your contributions.
# What kind of expectations do the maintainers have from you? # What kind of expectations do the maintainers have from you?
We expect you to: We expect you to:
* Follow the [Contributor Covenant](CODE_OF_CONDUCT.md), just like them * Follow the [Lix community standards], just like them
* Make an earnest attempt to follow the contribution process described in this * Make an earnest attempt to follow the contribution process described in this
document document
* Update bug reports with a solution, if you find one before we do * Update bug reports with a solution, if you find one before we do
@ -74,8 +70,8 @@ Create an issue on [the issue page](https://git.lix.systems/lix-project/lix-inst
It should contain: It should contain:
1. Your OS (Linux, Mac) and architecture (x86_64, aarch64) 1. Your OS (Linux, Mac) and architecture (x86_64, aarch64)
2. Your `nix-installer` version (`/nix/nix-installer --version`) 2. Your `lix-installer` version (`/nix/lix-installer --version`)
3. The thing you tried to run (eg `nix-installer`) 3. The thing you tried to run (eg `lix-installer`)
4. What happened (the output of the command, please) 4. What happened (the output of the command, please)
5. What you expected to happen 5. What you expected to happen
6. If you tried to fix it, what did you try? 6. If you tried to fix it, what did you try?
@ -364,6 +360,9 @@ To cut a release:
+ `nix flake check -L` + `nix flake check -L`
+ `nix build .#hydraJobs.container-test.all.x86_64-linux.all -L -j 6` + `nix build .#hydraJobs.container-test.all.x86_64-linux.all -L -j 6`
+ `nix build .#hydraJobs.vm-test.all.x86_64-linux.all -L -j 6` + `nix build .#hydraJobs.vm-test.all.x86_64-linux.all -L -j 6`
FIXME: the following is outdated for Lix and needs rewriting:
* Push the branch, create a PR ("Release v0.0.1") * Push the branch, create a PR ("Release v0.0.1")
* Once the PR tests pass and it has been reviewed, merge it * Once the PR tests pass and it has been reviewed, merge it
* `git pull` on the `main` branch * `git pull` on the `main` branch

575
Cargo.lock generated
View file

@ -90,6 +90,20 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "async-compression"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd066d0b4ef8ecb03a55319dc13aa6910616d0f44008a045bb1835af830abff5"
dependencies = [
"futures-core",
"memchr",
"pin-project-lite",
"tokio",
"zstd",
"zstd-safe",
]
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.80" version = "0.1.80"
@ -134,6 +148,12 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "base64ct"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -146,6 +166,15 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.16.0" version = "3.16.0"
@ -177,11 +206,22 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "camino"
version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.96" version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd"
dependencies = [
"jobserver",
"libc",
"once_cell",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -282,6 +322,12 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
[[package]]
name = "const-oid"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.9.4" version = "0.9.4"
@ -298,6 +344,52 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
name = "cpufeatures"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "curve25519-dalek"
version = "4.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
dependencies = [
"cfg-if",
"cpufeatures",
"curve25519-dalek-derive",
"digest",
"fiat-crypto",
"rustc_version",
"subtle",
"zeroize",
]
[[package]]
name = "curve25519-dalek-derive"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "darling" name = "darling"
version = "0.20.8" version = "0.20.8"
@ -333,6 +425,16 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "der"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0"
dependencies = [
"const-oid",
"zeroize",
]
[[package]] [[package]]
name = "deranged" name = "deranged"
version = "0.3.11" version = "0.3.11"
@ -343,6 +445,16 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]] [[package]]
name = "dirs" name = "dirs"
version = "5.0.1" version = "5.0.1"
@ -391,21 +503,37 @@ version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125"
[[package]]
name = "ed25519"
version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
dependencies = [
"pkcs8",
"serde",
"signature",
]
[[package]]
name = "ed25519-dalek"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871"
dependencies = [
"curve25519-dalek",
"ed25519",
"serde",
"sha2",
"subtle",
"zeroize",
]
[[package]] [[package]]
name = "either" name = "either"
version = "1.11.0" version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2"
[[package]]
name = "encoding_rs"
version = "0.8.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "enum-as-inner" name = "enum-as-inner"
version = "0.6.0" version = "0.6.0"
@ -459,6 +587,12 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
[[package]]
name = "fiat-crypto"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]] [[package]]
name = "filetime" name = "filetime"
version = "0.2.23" version = "0.2.23"
@ -553,6 +687,16 @@ dependencies = [
"slab", "slab",
] ]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.14" version = "0.2.14"
@ -576,25 +720,6 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "h2"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8"
dependencies = [
"bytes 1.6.0",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap 2.2.6",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.3" version = "0.12.3"
@ -642,9 +767,9 @@ dependencies = [
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.12" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
dependencies = [ dependencies = [
"bytes 1.6.0", "bytes 1.6.0",
"fnv", "fnv",
@ -653,12 +778,24 @@ dependencies = [
[[package]] [[package]]
name = "http-body" name = "http-body"
version = "0.4.6" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [ dependencies = [
"bytes 1.6.0", "bytes 1.6.0",
"http", "http",
]
[[package]]
name = "http-body-util"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f"
dependencies = [
"bytes 1.6.0",
"futures-util",
"http",
"http-body",
"pin-project-lite", "pin-project-lite",
] ]
@ -668,48 +805,61 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.14.28" version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05"
dependencies = [ dependencies = [
"bytes 1.6.0", "bytes 1.6.0",
"futures-channel", "futures-channel",
"futures-core",
"futures-util", "futures-util",
"h2",
"http", "http",
"http-body", "http-body",
"httparse", "httparse",
"httpdate",
"itoa", "itoa",
"pin-project-lite", "pin-project-lite",
"socket2", "smallvec",
"tokio", "tokio",
"tower-service",
"tracing",
"want", "want",
] ]
[[package]] [[package]]
name = "hyper-rustls" name = "hyper-rustls"
version = "0.24.2" version = "0.27.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"http", "http",
"hyper", "hyper",
"hyper-util",
"rustls", "rustls",
"rustls-native-certs",
"rustls-pki-types",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls",
"tower-service",
]
[[package]]
name = "hyper-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956"
dependencies = [
"bytes 1.6.0",
"futures-channel",
"futures-util",
"http",
"http-body",
"hyper",
"pin-project-lite",
"socket2",
"tokio",
"tower",
"tower-service",
"tracing",
] ]
[[package]] [[package]]
@ -817,6 +967,15 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
[[package]]
name = "is_executable"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa9acdc6d67b75e626ad644734e8bc6df893d9cd2a834129065d3dd6158ea9c8"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "is_terminal_polyfill" name = "is_terminal_polyfill"
version = "1.70.0" version = "1.70.0"
@ -829,6 +988,15 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "jobserver"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.69" version = "0.3.69"
@ -877,17 +1045,20 @@ name = "lix-installer"
version = "0.17.1" version = "0.17.1"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"base64 0.22.1",
"bytes 1.6.0", "bytes 1.6.0",
"clap", "clap",
"color-eyre", "color-eyre",
"dirs", "dirs",
"dyn-clone", "dyn-clone",
"ed25519-dalek",
"eyre", "eyre",
"glob", "glob",
"indexmap 2.2.6", "indexmap 2.2.6",
"is_ci", "is_ci",
"nix", "nix",
"nix-config-parser", "nix-config-parser",
"nix-nar",
"os-release", "os-release",
"owo-colors 4.0.0", "owo-colors 4.0.0",
"plist", "plist",
@ -897,6 +1068,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"serde_with", "serde_with",
"sha2",
"strum", "strum",
"sysctl", "sysctl",
"tar", "tar",
@ -914,6 +1086,7 @@ dependencies = [
"walkdir", "walkdir",
"which", "which",
"xz2", "xz2",
"zstd",
] ]
[[package]] [[package]]
@ -1007,6 +1180,18 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "nix-nar"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5549158a8b179c4fcd06a19f4bcc557db60c9cbd6771add9563f46c8d0325b5"
dependencies = [
"camino",
"is_executable",
"symlink",
"thiserror",
]
[[package]] [[package]]
name = "nu-ansi-term" name = "nu-ansi-term"
version = "0.46.0" version = "0.46.0"
@ -1128,6 +1313,26 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.14" version = "0.2.14"
@ -1140,6 +1345,16 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkcs8"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
dependencies = [
"der",
"spki",
]
[[package]] [[package]]
name = "pkg-config" name = "pkg-config"
version = "0.3.30" version = "0.3.30"
@ -1190,6 +1405,53 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "quinn"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad"
dependencies = [
"bytes 1.6.0",
"pin-project-lite",
"quinn-proto",
"quinn-udp",
"rustc-hash",
"rustls",
"thiserror",
"tokio",
"tracing",
]
[[package]]
name = "quinn-proto"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe"
dependencies = [
"bytes 1.6.0",
"rand",
"ring",
"rustc-hash",
"rustls",
"slab",
"thiserror",
"tinyvec",
"tracing",
]
[[package]]
name = "quinn-udp"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46"
dependencies = [
"libc",
"once_cell",
"socket2",
"tracing",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.36" version = "1.0.36"
@ -1304,20 +1566,21 @@ checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.11.27" version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37"
dependencies = [ dependencies = [
"base64 0.21.7", "async-compression",
"base64 0.22.1",
"bytes 1.6.0", "bytes 1.6.0",
"encoding_rs",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2",
"http", "http",
"http-body", "http-body",
"http-body-util",
"hyper", "hyper",
"hyper-rustls", "hyper-rustls",
"hyper-util",
"ipnet", "ipnet",
"js-sys", "js-sys",
"log", "log",
@ -1325,14 +1588,15 @@ dependencies = [
"once_cell", "once_cell",
"percent-encoding", "percent-encoding",
"pin-project-lite", "pin-project-lite",
"quinn",
"rustls", "rustls",
"rustls-native-certs", "rustls-native-certs",
"rustls-pemfile", "rustls-pemfile",
"rustls-pki-types",
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"sync_wrapper", "sync_wrapper",
"system-configuration",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls",
"tokio-socks", "tokio-socks",
@ -1367,6 +1631,21 @@ version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
]
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.34" version = "0.38.34"
@ -1382,44 +1661,55 @@ dependencies = [
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.21.12" version = "0.23.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0"
dependencies = [ dependencies = [
"log", "once_cell",
"ring", "ring",
"rustls-pki-types",
"rustls-webpki", "rustls-webpki",
"sct", "subtle",
"zeroize",
] ]
[[package]] [[package]]
name = "rustls-native-certs" name = "rustls-native-certs"
version = "0.6.3" version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba"
dependencies = [ dependencies = [
"openssl-probe", "openssl-probe",
"rustls-pemfile", "rustls-pemfile",
"rustls-pki-types",
"schannel", "schannel",
"security-framework", "security-framework",
] ]
[[package]] [[package]]
name = "rustls-pemfile" name = "rustls-pemfile"
version = "1.0.4" version = "2.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d"
dependencies = [ dependencies = [
"base64 0.21.7", "base64 0.22.1",
"rustls-pki-types",
] ]
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-pki-types"
version = "0.101.7" version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d"
[[package]]
name = "rustls-webpki"
version = "0.102.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78"
dependencies = [ dependencies = [
"ring", "ring",
"rustls-pki-types",
"untrusted", "untrusted",
] ]
@ -1459,16 +1749,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "sct"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
dependencies = [
"ring",
"untrusted",
]
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "2.11.0" version = "2.11.0"
@ -1574,6 +1854,17 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]] [[package]]
name = "sharded-slab" name = "sharded-slab"
version = "0.1.7" version = "0.1.7"
@ -1592,6 +1883,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "signature"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
dependencies = [
"rand_core",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.9" version = "0.4.9"
@ -1623,6 +1923,16 @@ version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "spki"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
dependencies = [
"base64ct",
"der",
]
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.10.0" version = "0.10.0"
@ -1657,6 +1967,12 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]] [[package]]
name = "supports-color" name = "supports-color"
version = "2.1.0" version = "2.1.0"
@ -1667,6 +1983,12 @@ dependencies = [
"is_ci", "is_ci",
] ]
[[package]]
name = "symlink"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.60" version = "2.0.60"
@ -1680,9 +2002,9 @@ dependencies = [
[[package]] [[package]]
name = "sync_wrapper" name = "sync_wrapper"
version = "0.1.2" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
[[package]] [[package]]
name = "sysctl" name = "sysctl"
@ -1698,27 +2020,6 @@ dependencies = [
"walkdir", "walkdir",
] ]
[[package]]
name = "system-configuration"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
dependencies = [
"bitflags 1.3.2",
"core-foundation",
"system-configuration-sys",
]
[[package]]
name = "system-configuration-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]] [[package]]
name = "tar" name = "tar"
version = "0.4.40" version = "0.4.40"
@ -1879,11 +2180,12 @@ dependencies = [
[[package]] [[package]]
name = "tokio-rustls" name = "tokio-rustls"
version = "0.24.1" version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
dependencies = [ dependencies = [
"rustls", "rustls",
"rustls-pki-types",
"tokio", "tokio",
] ]
@ -1912,6 +2214,27 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"pin-project",
"pin-project-lite",
"tokio",
"tower-layer",
"tower-service",
]
[[package]]
name = "tower-layer"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
[[package]] [[package]]
name = "tower-service" name = "tower-service"
version = "0.3.2" version = "0.3.2"
@ -1995,6 +2318,12 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "typenum"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]] [[package]]
name = "typetag" name = "typetag"
version = "0.2.16" version = "0.2.16"
@ -2079,6 +2408,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "walkdir" name = "walkdir"
version = "2.5.0" version = "2.5.0"
@ -2386,9 +2721,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]] [[package]]
name = "winreg" name = "winreg"
version = "0.50.0" version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"windows-sys 0.48.0", "windows-sys 0.48.0",
@ -2421,3 +2756,37 @@ dependencies = [
"lzma-sys", "lzma-sys",
"tokio-io", "tokio-io",
] ]
[[package]]
name = "zeroize"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
[[package]]
name = "zstd"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "7.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa556e971e7b568dc775c136fc9de8c779b1c2fc3a63defaafadffdbd3181afa"
dependencies = [
"zstd-sys",
]
[[package]]
name = "zstd-sys"
version = "2.0.12+zstd.1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13"
dependencies = [
"cc",
"pkg-config",
]

View file

@ -31,7 +31,7 @@ eyre = { version = "0.6.8", default-features = false, features = [ "track-caller
glob = { version = "0.3.0", default-features = false } glob = { version = "0.3.0", default-features = false }
nix = { version = "0.28.0", default-features = false, features = ["user", "fs", "process", "term"] } nix = { version = "0.28.0", default-features = false, features = ["user", "fs", "process", "term"] }
owo-colors = { version = "4.0.0", default-features = false, features = [ "supports-colors" ] } owo-colors = { version = "4.0.0", default-features = false, features = [ "supports-colors" ] }
reqwest = { version = "0.11.11", default-features = false, features = ["rustls-tls-native-roots", "stream", "socks"] } reqwest = { version = "0.12.5", default-features = false, features = ["rustls-tls-native-roots", "stream", "socks", "zstd"] }
serde = { version = "1.0.144", default-features = false, features = [ "std", "derive" ] } serde = { version = "1.0.144", default-features = false, features = [ "std", "derive" ] }
serde_json = { version = "1.0.85", default-features = false, features = [ "std" ] } serde_json = { version = "1.0.85", default-features = false, features = [ "std" ] }
serde_with = { version = "3", default-features = false, features = [ "std", "macros" ] } serde_with = { version = "3", default-features = false, features = [ "std", "macros" ] }
@ -60,6 +60,11 @@ which = "6.0.0"
sysctl = "0.5.4" sysctl = "0.5.4"
walkdir = "2.3.3" walkdir = "2.3.3"
indexmap = { version = "2.0.2", features = ["serde"] } indexmap = { version = "2.0.2", features = ["serde"] }
nix-nar = "0.3.0"
zstd = { version = "0.13.2", default-features = false }
sha2 = "0.10.8"
ed25519-dalek = { version = "2.1.1", features = ["serde"] }
base64 = "0.22.1"
[dev-dependencies] [dev-dependencies]
eyre = { version = "0.6.8", default-features = false, features = [ "track-caller" ] } eyre = { version = "0.6.8", default-features = false, features = [ "track-caller" ] }

View file

@ -338,13 +338,14 @@ Here are some example `nix` package URLs including nix version, OS and architect
## Installation Differences ## Installation Differences
Differing from the upstream [Nix](https://github.com/NixOS/nix) installer scripts: Differing from the [CppNix](https://github.com/NixOS/nix) installer scripts:
* In `nix.conf`: * In `nix.conf`:
+ the `nix-command` and `flakes` features are enabled + the `nix-command` and `flakes` features are optionally enabled
+ `bash-prompt-prefix` is set + `bash-prompt-prefix` is set
+ `auto-optimise-store` is set to `true` (On Linux only) + `auto-optimise-store` is set to `true` (On Linux only)
* `extra-nix-path` is set to `nixpkgs=flake:nixpkgs` * `extra-nix-path` is set to `nixpkgs=flake:nixpkgs` if flakes are enabled
when installing
* `max-jobs` is set to `auto` * `max-jobs` is set to `auto`
* an installation receipt (for uninstalling) is stored at `/nix/receipt.json` as well as a copy of the install binary at `/nix/lix-installer` * an installation receipt (for uninstalling) is stored at `/nix/receipt.json` as well as a copy of the install binary at `/nix/lix-installer`
* `nix-channel --update` is not run, `~/.nix-channels` is not provisioned * `nix-channel --update` is not run, `~/.nix-channels` is not provisioned

View file

@ -22,27 +22,13 @@
} }
}, },
"flake-compat": { "flake-compat": {
"flake": false,
"locked": { "locked": {
"lastModified": 1696426674, "lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"revCount": 57,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://flakehub.com/f/edolstra/flake-compat/1.0.0.tar.gz"
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -51,20 +37,24 @@
"type": "github" "type": "github"
} }
}, },
"libgit2": { "lix": {
"flake": false, "inputs": {
"flake-compat": "flake-compat",
"nix2container": "nix2container",
"nixpkgs": "nixpkgs",
"nixpkgs-regression": "nixpkgs-regression",
"pre-commit-hooks": "pre-commit-hooks"
},
"locked": { "locked": {
"lastModified": 1697646580, "lastModified": 1720626042,
"narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", "narHash": "sha256-f8k+BezKdJfmE+k7zgBJiohtS3VkkriycdXYsKOm3sc=",
"owner": "libgit2", "rev": "2a4376be20d70feaa2b0e640c5041fb66ddc67ed",
"repo": "libgit2", "type": "tarball",
"rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", "url": "https://git.lix.systems/api/v1/repos/lix-project/lix/archive/2a4376be20d70feaa2b0e640c5041fb66ddc67ed.tar.gz"
"type": "github"
}, },
"original": { "original": {
"owner": "libgit2", "type": "tarball",
"repo": "libgit2", "url": "https://git.lix.systems/lix-project/lix/archive/2.90.0.tar.gz"
"type": "github"
} }
}, },
"naersk": { "naersk": {
@ -87,38 +77,34 @@
"type": "github" "type": "github"
} }
}, },
"nix": { "nix2container": {
"inputs": { "flake": false,
"flake-compat": "flake-compat_2",
"libgit2": "libgit2",
"nixpkgs": "nixpkgs",
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": { "locked": {
"lastModified": 1709808984, "lastModified": 1712990762,
"narHash": "sha256-bfFe38BkoQws7om4gBtBWoNTLkt9piMXdLLoHYl+vBQ=", "narHash": "sha256-hO9W3w7NcnYeX8u8cleHiSpK2YJo7ecarFTUlbybl7k=",
"rev": "f8170ce9f119e5e6724eb81ff1b5a2d4c0024000", "owner": "nlewo",
"revCount": 16143, "repo": "nix2container",
"type": "tarball", "rev": "20aad300c925639d5d6cbe30013c8357ce9f2a2e",
"url": "https://api.flakehub.com/f/pinned/NixOS/nix/2.20.5/018e199b-ae2c-703d-ab99-4c648be473b2/source.tar.gz" "type": "github"
}, },
"original": { "original": {
"type": "tarball", "owner": "nlewo",
"url": "https://flakehub.com/f/NixOS/nix/%3D2.20.5.tar.gz" "repo": "nix2container",
"type": "github"
} }
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1705033721, "lastModified": 1718379166,
"narHash": "sha256-K5eJHmL1/kev6WuqyqqbS1cdNnSidIZ3jeqJ7GbrYnQ=", "narHash": "sha256-B/Q/Pf4kD+yWk3fGh5H0fUpwxmLgEKt9KBon+bZ3d9U=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "a1982c92d8980a0114372973cbdfe0a307f1bdea", "rev": "93fbfcd45e966ea1cff043d48bd45d1285082770",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixos-23.05-small", "ref": "nixos-24.05-small",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@ -141,26 +127,41 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1714763106, "lastModified": 1718379166,
"narHash": "sha256-DrDHo74uTycfpAF+/qxZAMlP/Cpe04BVioJb6fdI0YY=", "narHash": "sha256-B/Q/Pf4kD+yWk3fGh5H0fUpwxmLgEKt9KBon+bZ3d9U=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "e9be42459999a253a9f92559b1f5b72e1b44c13d", "rev": "93fbfcd45e966ea1cff043d48bd45d1285082770",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixos-unstable", "ref": "nixos-24.05-small",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
}, },
"pre-commit-hooks": {
"flake": false,
"locked": {
"lastModified": 1712055707,
"narHash": "sha256-4XLvuSIDZJGS17xEwSrNuJLL7UjDYKGJSbK1WWX2AK8=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "e35aed5fda3cc79f88ed7f1795021e559582093a",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"fenix": "fenix", "fenix": "fenix",
"flake-compat": "flake-compat", "lix": "lix",
"naersk": "naersk", "naersk": "naersk",
"nix": "nix",
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs_2"
} }
}, },

View file

@ -2,7 +2,7 @@
description = "The Lix Installer"; description = "The Lix Installer";
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05-small";
fenix = { fenix = {
url = "github:nix-community/fenix"; url = "github:nix-community/fenix";
@ -14,12 +14,13 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
nix = { lix = {
url = "https://flakehub.com/f/NixOS/nix/=2.20.5.tar.gz"; # See set_version.py
# BEGIN GENERATE-URLS
url = "https://git.lix.systems/lix-project/lix/archive/2.90.0.tar.gz";
# END GENERATE-URLS
# Omitting `inputs.nixpkgs.follows = "nixpkgs";` on purpose # Omitting `inputs.nixpkgs.follows = "nixpkgs";` on purpose
}; };
flake-compat.url = "https://flakehub.com/f/edolstra/flake-compat/1.0.0.tar.gz";
}; };
outputs = outputs =
@ -27,7 +28,7 @@
, nixpkgs , nixpkgs
, fenix , fenix
, naersk , naersk
, nix , lix
, ... , ...
} @ inputs: } @ inputs:
let let
@ -94,6 +95,8 @@
}; };
postInstall = '' postInstall = ''
cp lix-installer.sh $out/bin/lix-installer.sh cp lix-installer.sh $out/bin/lix-installer.sh
ln -s lix-installer $out/bin/nix-installer
ln -s lix-installer.sh $out/bin/nix-installer.sh
''; '';
}; };
in in
@ -124,6 +127,13 @@
let let
toolchain = fenixToolchain system; toolchain = fenixToolchain system;
check = import ./nix/check.nix { inherit pkgs toolchain; }; check = import ./nix/check.nix { inherit pkgs toolchain; };
inherit (pkgs) lib;
pythonEnv = pkgs.python3.withPackages (p: [
(p.toPythonModule pkgs.xonsh-unwrapped)
p.requests
]);
in in
{ {
default = pkgs.mkShell { default = pkgs.mkShell {
@ -131,10 +141,21 @@
RUST_SRC_PATH = "${toolchain}/lib/rustlib/src/rust/library"; RUST_SRC_PATH = "${toolchain}/lib/rustlib/src/rust/library";
nativeBuildInputs = with pkgs; [ ]; buildInputs = lib.optionals (pkgs.stdenv.isDarwin)
buildInputs = with pkgs; [ (with pkgs; [
libiconv
darwin.apple_sdk.frameworks.Security
darwin.apple_sdk.frameworks.SystemConfiguration
])
++ lib.optionals (pkgs.stdenv.isLinux) (with pkgs; [
checkpolicy
semodule-utils
/* users are expected to have a system docker, too */
]);
nativeBuildInputs = with pkgs; [
zig zig
xonsh pythonEnv
awscli2 awscli2
toolchain toolchain
rust-analyzer rust-analyzer
@ -150,17 +171,7 @@
check.check-editorconfig check.check-editorconfig
check.check-semver check.check-semver
check.check-clippy check.check-clippy
] ];
++ lib.optionals (pkgs.stdenv.isDarwin) (with pkgs; [
libiconv
darwin.apple_sdk.frameworks.Security
darwin.apple_sdk.frameworks.SystemConfiguration
])
++ lib.optionals (pkgs.stdenv.isLinux) (with pkgs; [
checkpolicy
semodule-utils
/* users are expected to have a system docker, too */
]);
}; };
}); });
@ -211,12 +222,12 @@
hydraJobs = { hydraJobs = {
vm-test = import ./nix/tests/vm-test { vm-test = import ./nix/tests/vm-test {
inherit forSystem; inherit forSystem;
inherit (nix.hydraJobs) binaryTarball; inherit (lix.hydraJobs) binaryTarball;
inherit (nixpkgs) lib; inherit (nixpkgs) lib;
}; };
container-test = import ./nix/tests/container-test { container-test = import ./nix/tests/container-test {
inherit forSystem; inherit forSystem;
inherit (nix.hydraJobs) binaryTarball; inherit (lix.hydraJobs) binaryTarball;
}; };
}; };
}; };

17
nix/eval-versions.nix Normal file
View file

@ -0,0 +1,17 @@
let
args = builtins.fromJSON (builtins.getEnv "LIX_EVAL_VERSIONS_ARGS");
flake = builtins.getFlake args.flakeUrl;
nixpkgs = flake.inputs.nixpkgs;
lix = system: flake.outputs.packages.${system}.nix.outPath;
cacert = system: nixpkgs.outputs.legacyPackages.${system}.cacert.outPath;
targets = system: [
(lix system)
(cacert system)
];
in
builtins.listToAttrs (
builtins.map (system: {
name = system;
value = targets system;
}) args.systems
)

View file

@ -54,7 +54,7 @@ let
machine.copy_from_host("${image.tarball}", "/image") machine.copy_from_host("${image.tarball}", "/image")
machine.succeed("mkdir -p /test") machine.succeed("mkdir -p /test")
machine.copy_from_host("${image.tester}", "/test/Dockerfile") machine.copy_from_host("${image.tester}", "/test/Dockerfile")
machine.copy_from_host("${nix-installer-static}", "/test/nix-installer") machine.copy_from_host("${lix-installer-static}", "/test/lix-installer")
machine.copy_from_host("${binaryTarball.${system}}", "/test/binary-tarball") machine.copy_from_host("${binaryTarball.${system}}", "/test/binary-tarball")
machine.succeed("${containerTool} import /image default") machine.succeed("${containerTool} import /image default")
machine.succeed("${containerTool} build -t test /test") machine.succeed("${containerTool} build -t test /test")

View file

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

View file

@ -4,7 +4,7 @@
let let
nix-installer-install = '' nix-installer-install = ''
NIX_PATH=$(readlink -f nix.tar.xz) NIX_PATH=$(readlink -f nix.tar.xz)
RUST_BACKTRACE="full" ./nix-installer install --nix-package-url "file://$NIX_PATH" --no-confirm --logger pretty --log-directive nix_installer=info RUST_BACKTRACE="full" ./nix-installer install --nix-package-url "file://$NIX_PATH" --no-confirm --logger pretty --log-directive lix_installer=info
''; '';
nix-installer-install-quiet = '' nix-installer-install-quiet = ''
NIX_PATH=$(readlink -f nix.tar.xz) NIX_PATH=$(readlink -f nix.tar.xz)
@ -132,10 +132,41 @@ let
fi fi
''; '';
}; };
install-substituter = pkgs: let
rootPaths = binaryTarball.${pkgs.system}.passthru.rootPaths;
binaryCache = pkgs.mkBinaryCache { inherit rootPaths; };
targetArg = pkg: "--substitution-targets ${pkg.outPath}";
targetArgs = lib.concatMapStringsSep " " targetArg rootPaths;
in {
# We need -O for the old scp protocol because RHEL 8 has old SSH with broken SFTP
# Might be deprecated soon, so remove when we remove RHEL 8
copyTarball = ''
scp -O -P 20022 $ssh_opts -r ${binaryCache} vagrant@localhost:binaryCache
'';
install = ''
pushd binaryCache
python3 -m http.server 8000 &
server_pid=$!
trap "kill $server_pid" EXIT
popd
sleep 1
RUST_BACKTRACE="full" ./nix-installer install \
--use-substituters \
--substituters http://127.0.0.1:8000 \
--no-require-sigs \
${targetArgs} \
--no-confirm \
--logger pretty \
--log-directive lix_installer=info
'';
check = installCases.install-default.check;
uninstall = installCases.install-default.uninstall;
uninstallCheck = installCases.install-default.uninstallCheck;
};
install-no-start-daemon = { install-no-start-daemon = {
install = '' install = ''
NIX_PATH=$(readlink -f nix.tar.xz) NIX_PATH=$(readlink -f nix.tar.xz)
RUST_BACKTRACE="full" ./nix-installer install linux --nix-package-url "file://$NIX_PATH" --no-confirm --logger pretty --log-directive nix_installer=info --no-start-daemon RUST_BACKTRACE="full" ./nix-installer install linux --nix-package-url "file://$NIX_PATH" --no-confirm --logger pretty --log-directive lix_installer=info --no-start-daemon
''; '';
check = '' check = ''
set -ex set -ex
@ -162,7 +193,7 @@ let
install-daemonless = { install-daemonless = {
install = '' install = ''
NIX_PATH=$(readlink -f nix.tar.xz) NIX_PATH=$(readlink -f nix.tar.xz)
RUST_BACKTRACE="full" ./nix-installer install linux --nix-package-url "file://$NIX_PATH" --no-confirm --logger pretty --log-directive nix_installer=info --init none RUST_BACKTRACE="full" ./nix-installer install linux --nix-package-url "file://$NIX_PATH" --no-confirm --logger pretty --log-directive lix_installer=info --init none
''; '';
check = '' check = ''
set -ex set -ex
@ -400,25 +431,10 @@ let
disableSELinux = "sudo setenforce 0"; disableSELinux = "sudo setenforce 0";
images = { images = {
"ubuntu-v20_04" = {
# End of standard support https://wiki.ubuntu.com/Releases
# No systemd
/*
"ubuntu-v14_04" = {
image = import <nix/fetchurl.nix> { image = import <nix/fetchurl.nix> {
url = "https://app.vagrantup.com/ubuntu/boxes/trusty64/versions/20190514.0.0/providers/virtualbox.box"; url = "https://app.vagrantup.com/generic/boxes/ubuntu2004/versions/4.3.12/providers/libvirt.box";
hash = "sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="; hash = "sha256-lo6fkz6N/Q9mdD+RWoUssak9TVod0F7QSgZvxnMj9IQ=";
};
rootDisk = "box-disk1.vmdk";
system = "x86_64-linux";
};
*/
# End of standard support https://wiki.ubuntu.com/Releases
"ubuntu-v16_04" = {
image = import <nix/fetchurl.nix> {
url = "https://app.vagrantup.com/generic/boxes/ubuntu1604/versions/4.1.12/providers/libvirt.box";
hash = "sha256-lO4oYQR2tCh5auxAYe6bPOgEqOgv3Y3GC1QM1tEEEU8=";
}; };
rootDisk = "box.img"; rootDisk = "box.img";
system = "x86_64-linux"; system = "x86_64-linux";
@ -433,50 +449,16 @@ let
system = "x86_64-linux"; system = "x86_64-linux";
}; };
"fedora-v36" = { "fedora-v39" = {
image = import <nix/fetchurl.nix> { image = import <nix/fetchurl.nix> {
url = "https://app.vagrantup.com/generic/boxes/fedora36/versions/4.1.12/providers/libvirt.box"; url = "https://app.vagrantup.com/generic/boxes/fedora39/versions/4.3.12/providers/libvirt.box";
hash = "sha256-rxPgnDnFkTDwvdqn2CV3ZUo3re9AdPtSZ9SvOHNvaks="; hash = "sha256-VJbWmcy3XiEm7cUAXtod8VlFwsIwnVYlZ/LYTuoj9WI=";
}; };
rootDisk = "box.img"; rootDisk = "box.img";
system = "x86_64-linux"; system = "x86_64-linux";
upstreamScriptsWork = false; # SELinux! upstreamScriptsWork = false; # SELinux!
}; };
"fedora-v37" = {
image = import <nix/fetchurl.nix> {
url = "https://app.vagrantup.com/generic/boxes/fedora37/versions/4.2.14/providers/libvirt.box";
hash = "sha256-rxPgnDnFkTDwvdqn2CV3ZUo3re9AdPtSZ9SvOHNvaks=";
};
rootDisk = "box.img";
system = "x86_64-linux";
upstreamScriptsWork = false; # SELinux!
};
# Currently fails with 'error while loading shared libraries:
# libsodium.so.23: cannot stat shared object: Invalid argument'.
/*
"rhel-v6" = {
image = import <nix/fetchurl.nix> {
url = "https://app.vagrantup.com/generic/boxes/rhel6/versions/4.1.12/providers/libvirt.box";
hash = "sha256-QwzbvRoRRGqUCQptM7X/InRWFSP2sqwRt2HaaO6zBGM=";
};
rootDisk = "box.img";
upstreamScriptsWork = false; # SELinux!
system = "x86_64-linux";
};
*/
"rhel-v7" = {
image = import <nix/fetchurl.nix> {
url = "https://app.vagrantup.com/generic/boxes/rhel7/versions/4.1.12/providers/libvirt.box";
hash = "sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U=";
};
rootDisk = "box.img";
upstreamScriptsWork = false; # SELinux!
system = "x86_64-linux";
};
"rhel-v8" = { "rhel-v8" = {
image = import <nix/fetchurl.nix> { image = import <nix/fetchurl.nix> {
url = "https://app.vagrantup.com/generic/boxes/rhel8/versions/4.1.12/providers/libvirt.box"; url = "https://app.vagrantup.com/generic/boxes/rhel8/versions/4.1.12/providers/libvirt.box";
@ -500,9 +482,13 @@ let
}; };
makeTest = imageName: testName: test: makeTest = imageName: testName: testFunc:
let image = images.${imageName}; in let
with (forSystem image.system ({ system, pkgs, ... }: pkgs)); image = images.${imageName};
pkgs = (forSystem image.system ({ system, pkgs, ... }: pkgs));
test = if builtins.isFunction testFunc then (testFunc pkgs) else testFunc;
in
with pkgs;
runCommand runCommand
"installer-test-${imageName}-${testName}" "installer-test-${imageName}-${testName}"
{ {
@ -515,8 +501,10 @@ let
uninstallScript = test.uninstall; uninstallScript = test.uninstall;
preuninstallScript = test.preuninstall or "echo \"Not Applicable\""; preuninstallScript = test.preuninstall or "echo \"Not Applicable\"";
uninstallCheckScript = test.uninstallCheck; uninstallCheckScript = test.uninstallCheck;
installer = nix-installer-static; installer = lix-installer-static;
binaryTarball = binaryTarball.${system}; binaryTarball = binaryTarball.${system};
copyTarball = test.copyTarball
or "scp -P 20022 $ssh_opts $binaryTarball/lix-*.tar.xz vagrant@localhost:nix.tar.xz";
} }
'' ''
shopt -s nullglob shopt -s nullglob
@ -573,10 +561,11 @@ let
fi fi
echo "Copying installer..." echo "Copying installer..."
scp -P 20022 $ssh_opts $installer/bin/nix-installer vagrant@localhost:nix-installer scp -P 20022 $ssh_opts $installer/bin/lix-installer vagrant@localhost:nix-installer
ls $binaryTarball
echo "Copying nix tarball..." echo "Copying nix tarball..."
scp -P 20022 $ssh_opts $binaryTarball/nix-*.tar.xz vagrant@localhost:nix.tar.xz eval "$copyTarball"
echo "Running preinstall..." echo "Running preinstall..."
$ssh "set -eux; $preinstallScript" $ssh "set -eux; $preinstallScript"

147
set_version.py Executable file
View file

@ -0,0 +1,147 @@
#!/usr/bin/env python
from pathlib import Path
import textwrap
import dataclasses
import requests
import os
import json
import subprocess
SYSTEMS = ['x86_64-linux', 'x86_64-darwin', 'aarch64-linux', 'aarch64-darwin']
@dataclasses.dataclass
class Package:
system: str
version: str
def url(self):
return f"https://releases.lix.systems/lix/lix-{self.version}/lix-{self.version}-{self.system}.tar.xz";
def variable_name(self):
system = self.system.replace('-', '_').upper()
return f'LIX_{system}_URL'
def make_urls_section(packages: list[Package]):
def one_item(package: Package):
return textwrap.dedent("""\
/// Default [`nix_package_url`](CommonSettings::nix_package_url) for {system}.
pub const {variable_name}: &str =
"{url}";
""").format(system=package.system, variable_name=package.variable_name(), url=package.url())
return '\n'.join(one_item(package) for package in packages)
@dataclasses.dataclass
class SubstitutionTargets:
system: str
targets: list[str]
def variable_name(self):
system = self.system.replace('-', '_').upper()
return f'LIX_{system}_SUBSTITUTION_TARGETS'
def make_substitution_targets_section(packages: list[SubstitutionTargets]):
def one_item(package: SubstitutionTargets):
targets = "\n".join([f' "{target}",' for target in package.targets])
return textwrap.dedent("""\
/// Default [`substitution_targets`](CommonSettings::substitution_targets) for {system}.
pub const {variable_name}: &[&str; {target_len}] = &[
{targets}
];
""").format(
system=package.system,
variable_name=package.variable_name(),
target_len=len(package.targets),
targets=targets
)
return '\n'.join(one_item(package) for package in packages)
def eval_substitution_targets(version: str) -> list[SubstitutionTargets]:
options = {
"systems": SYSTEMS,
"flakeUrl": lix_flake_url(version)
}
env = os.environb | {
b"LIX_EVAL_VERSIONS_ARGS": json.dumps(options)
}
completed = subprocess.run([
"nix",
"--extra-experimental-features",
"nix-command flakes",
"eval",
"--impure",
"--json",
"--file",
Path("nix/eval-versions.nix")
], env=env, check=True, capture_output=True)
result = json.loads(completed.stdout)
return [SubstitutionTargets(system, targets) for (system, targets) in result.items()]
def replace_section(old: str, section: str) -> str:
lines = []
eat = False
for line in old.splitlines():
next_eat = eat
if 'BEGIN GENERATE-URLS' in line.strip():
next_eat = True
elif 'END GENERATE-URLS' in line.strip():
lines.append(section)
eat = False
next_eat = False
if not eat:
lines.append(line)
eat = next_eat
return '\n'.join(lines)
def replace_in_file(file: Path, section: str):
new_file = replace_section(file.read_text(), section)
file.write_text(new_file)
def lix_flake_url(version: str) -> str:
return f"https://git.lix.systems/lix-project/lix/archive/{version}.tar.gz"
def make_flake_url_section(version: str) -> str:
return f' url = "{lix_flake_url(version)}";'
def main():
import argparse
ap = argparse.ArgumentParser(description='Update the version of lix-installer')
ap.add_argument('new_version', help='The new version')
args = ap.parse_args()
settings_rs = Path('src/settings.rs')
packages = [Package(system, args.new_version) for system in SYSTEMS]
substitution_targets = eval_substitution_targets(args.new_version)
for package in packages:
resp = requests.head(package.url())
if resp.status_code != 200:
print(f'Warning: broken URL {package.url()} returns HTTP {resp.status_code}')
replace_in_file(settings_rs,
make_urls_section(packages) +
"\n" +
make_substitution_targets_section(substitution_targets)
)
flake_nix = Path('flake.nix')
replace_in_file(flake_nix, make_flake_url_section(args.new_version))
if __name__ == '__main__':
main()

View file

@ -0,0 +1,709 @@
use std::{
collections::{HashMap, HashSet},
fmt::Write,
io::{BufRead, Read},
path::{Path, PathBuf},
};
use base64::Engine;
use bytes::Buf;
use ed25519_dalek::VerifyingKey;
use reqwest::Url;
use serde::{Deserialize, Serialize};
use sha2::Digest;
use tokio::io::AsyncWriteExt;
use tracing::{span, Span};
use crate::{
action::{Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction},
parse_ssl_cert,
settings::UrlOrPathError,
};
/// Fetch an output and its dependencies from a set of substituters,
/// given an output path, subsititer URLs, and trusted keys.
/// Also generates a ".reginfo" compatible with `nix-store --load-db`
/// Only implements a subset of nix substitution features:
/// * Substituter priorites are highest to lowest as given to [`plan`],
/// instead of priority from nix-cache-info
/// * narinfo signatures are always required
/// * ca-derivations are not supported
/// * NarHash must be sha256
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct FetchAndUnpackNixSubstituter {
/// Whether to require valid signatures when checking narinfo
require_sigs: bool,
/// Map from key name (e.g. cache.nixos.org-1) to parsed ed25519 key
trusted_keys: HashMap<String, VerifyingKey>,
/// Base URLs for substituters, e.g. https://cache.nixos.org/
substituters: Vec<Url>,
/// Desired derivation output, e.g.
/// `/nix/store/n50jk09x9hshwx1lh6k3qaiygc7yxbv9-lix-2.90.0-rc1`
targets: Vec<StorePath>,
/// Destination directory, normally temporary.
/// For compatibility with tarballs, files will be placed in
/// the nix-/store subdirectory of the destination
dest: PathBuf,
/// Proxy used for all requests from substituters
proxy: Option<Url>,
/// Extra SSL certificates trusted for all requests
ssl_cert_file: Option<PathBuf>,
}
/// Root directory of the nix store.
/// Technically this could be something other than /nix/store,
/// but that is rarely done in production
const STORE_DIR: &str = "/nix/store/";
impl FetchAndUnpackNixSubstituter {
#[tracing::instrument(level = "debug", skip_all)]
pub async fn plan(
targets: Vec<PathBuf>,
dest: PathBuf,
trusted_keys: Vec<String>,
require_sigs: bool,
substituters: Vec<Url>,
proxy: Option<Url>,
ssl_cert_file: Option<PathBuf>,
) -> Result<StatefulAction<Self>, ActionError> {
let trusted_keys_parsed = trusted_keys
.iter()
.map(|key| parse_key(key))
.collect::<Result<HashMap<_, _>, _>>()
.map_err(Self::error)?;
if let Some(proxy) = &proxy {
match proxy.scheme() {
"https" | "http" | "socks5" => (),
_ => return Err(Self::error(SubstitutionError::UnknownProxyScheme)),
};
}
if let Some(ssl_cert_file) = &ssl_cert_file {
parse_ssl_cert(ssl_cert_file).await.map_err(Self::error)?;
}
let targets = targets
.iter()
.map(|p| StorePath::from_path(p))
.collect::<Result<Vec<_>, _>>()
.map_err(Self::error)?;
if !require_sigs {
tracing::warn!("Signatures are not required during substitution. This is insecure.");
}
Ok(Self {
require_sigs,
targets,
trusted_keys: trusted_keys_parsed,
dest,
proxy,
substituters,
ssl_cert_file,
}
.into())
}
#[tracing::instrument(level = "trace", skip(self, client))]
async fn fetch_narinfo(
&self,
client: &reqwest::Client,
output: &StorePath,
) -> Result<NarInfo, ActionError> {
for substituter in &self.substituters {
let narinfo_url = substituter
.join(&format!("{}.narinfo", &output.digest()))
.map_err(|err| UrlOrPathError::Url("".to_string(), err))
.map_err(ActionErrorKind::UrlOrPathError)
.map_err(Self::error)?;
let response = client
.get(narinfo_url)
.send()
.await
.map_err(ActionErrorKind::Reqwest)
.map_err(Self::error)?;
if !response.status().is_success() {
continue;
}
let narinfo = NarInfo::parse_and_verify(
self.require_sigs,
&self.trusted_keys,
substituter,
output,
&response
.bytes()
.await
.map_err(ActionErrorKind::Reqwest)
.map_err(Self::error)?,
)
.map_err(Self::error)?;
return Ok(narinfo);
}
Err(Self::error(SubstitutionError::NonexistantNarInfo(
output.full_path().clone(),
)))
}
}
#[async_trait::async_trait]
#[typetag::serde(name = "fetch_and_unpack_nix")]
impl Action for FetchAndUnpackNixSubstituter {
fn action_tag() -> ActionTag {
ActionTag("fetch_and_unpack_nix_substituter")
}
fn tracing_synopsis(&self) -> String {
format!(
"Fetch {} from substituters to `{}`",
self.targets
.iter()
.map(|t| format!("`{}`", t.full_path()))
.collect::<Vec<String>>()
.join(", "),
self.dest.display()
)
}
fn tracing_span(&self) -> Span {
let span = span!(
tracing::Level::DEBUG,
"fetch_and_unpack_nix_substituter",
targets = tracing::field::debug(&self.targets),
proxy = tracing::field::Empty,
ssl_cert_file = tracing::field::Empty,
dest = tracing::field::display(self.dest.display()),
);
if let Some(proxy) = &self.proxy {
span.record("proxy", tracing::field::display(&proxy));
}
if let Some(ssl_cert_file) = &self.ssl_cert_file {
span.record(
"ssl_cert_file",
tracing::field::display(&ssl_cert_file.display()),
);
}
span
}
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 mut client_builder = reqwest::Client::builder();
if let Some(proxy) = &self.proxy {
client_builder = client_builder.proxy(
reqwest::Proxy::all(proxy.clone())
.map_err(ActionErrorKind::Reqwest)
.map_err(Self::error)?,
)
}
if let Some(ssl_cert_file) = &self.ssl_cert_file {
let ssl_cert = parse_ssl_cert(ssl_cert_file).await.map_err(Self::error)?;
client_builder = client_builder.add_root_certificate(ssl_cert);
}
let client = client_builder
.build()
.map_err(ActionErrorKind::Reqwest)
.map_err(Self::error)?;
let nix_store_dir = self.dest.join("nix-/store");
tokio::fs::create_dir_all(&nix_store_dir)
.await
.map_err(|e| ActionErrorKind::CreateDirectory(nix_store_dir.clone(), e))
.map_err(Self::error)?;
let mut outputs_remaining = self.targets.clone();
let mut outputs_done = HashSet::new();
let mut reginfo = String::new();
loop {
let Some(output) = outputs_remaining.pop() else {
break;
};
// Make sure we don't download the same output twice
if !outputs_done.insert(output.clone()) {
continue;
}
let narinfo = self.fetch_narinfo(&client, &output).await?;
for reference in &narinfo.references {
outputs_remaining.push(reference.clone());
}
let compressed_nar = client
.get(narinfo.url.clone())
.send()
.await
.map_err(ActionErrorKind::Reqwest)
.map_err(Self::error)?
.error_for_status()
.map_err(ActionErrorKind::Reqwest)
.map_err(Self::error)?
.bytes()
.await
.map_err(ActionErrorKind::Reqwest)
.map_err(Self::error)?;
let nar_size: usize = narinfo
.nar_size
.try_into()
.map_err(|_| Self::error(SubstitutionError::BadNarInfo))?;
// Decompress to a vec since we need to go through the data twice
// (once for hashing, one for unpacking).
// Otherwise we'd need to decompress twice
let decompressed_nar = match narinfo.compression {
NarCompression::Zstd => zstd::bulk::decompress(&compressed_nar, nar_size)
.map_err(|e| SubstitutionError::Decompress(narinfo.url.clone(), e))
.map_err(Self::error)?,
NarCompression::Xz => {
let mut decompressor = xz2::read::XzDecoder::new(compressed_nar.reader());
let mut result = Vec::with_capacity(nar_size);
decompressor
.read_to_end(&mut result)
.map_err(|e| SubstitutionError::Decompress(narinfo.url.clone(), e))
.map_err(Self::error)?;
result
},
};
if decompressed_nar.len() != nar_size {
return Err(Self::error(SubstitutionError::BadNar(narinfo.url.clone())));
}
let found_hash = {
let mut hasher = sha2::Sha256::new();
hasher.update(&decompressed_nar);
hasher.finalize()
};
if encode_nix32(&found_hash) != narinfo.nar_hash {
return Err(Self::error(SubstitutionError::BadNar(narinfo.url.clone())));
}
let out_dir = self.dest.join("nix-/store").join(output.full_name());
let decoder = nix_nar::Decoder::new(decompressed_nar.reader())
.map_err(|e| SubstitutionError::Unpack(narinfo.url.clone(), e))
.map_err(Self::error)?;
decoder
.unpack(out_dir)
.map_err(|e| SubstitutionError::Unpack(narinfo.url.clone(), e))
.map_err(Self::error)?;
// File format isn't documented anywhere but implementation is simple:
// https://git.lix.systems/lix-project/lix/src/commit/d461cc1d7b2f489c3886f147166ba5b5e0e37541/src/libstore/store-api.cc#L846
// Unwrapping because string can't fail methods in std::fmt::Write
writeln!(reginfo, "{}", output.full_path()).unwrap();
writeln!(reginfo, "sha256:{}", narinfo.nar_hash).unwrap();
writeln!(reginfo, "{}", narinfo.nar_size).unwrap();
// Leave deriver empty, same as lix binary tarballs
reginfo.push('\n');
writeln!(reginfo, "{}", narinfo.references.len()).unwrap();
for reference in &narinfo.references {
writeln!(reginfo, "{}", reference.full_path()).unwrap();
}
}
let reginfo_path = self.dest.join("nix-/.reginfo");
let mut reginfo_file = tokio::fs::File::create(&reginfo_path)
.await
.map_err(|e| ActionErrorKind::Write(reginfo_path.clone(), e))
.map_err(Self::error)?;
reginfo_file
.write_all(reginfo.as_bytes())
.await
.map_err(|e| ActionErrorKind::Write(reginfo_path.clone(), e))
.map_err(Self::error)?;
Ok(())
}
fn revert_description(&self) -> Vec<ActionDescription> {
vec![/* Deliberately empty -- this is a noop */]
}
#[tracing::instrument(level = "debug", skip_all)]
async fn revert(&mut self) -> Result<(), ActionError> {
Ok(())
}
}
/// Parse a nix trusted key into name and ed25519
fn parse_key(key: &str) -> Result<(String, VerifyingKey), SubstitutionError> {
let (name, key_base64) = key
.split_once(':')
.ok_or_else(|| SubstitutionError::PublicKey)?;
// seems to be the best way to handle keys both with and without padding
let key_bytes = base64::engine::general_purpose::STANDARD_NO_PAD
.decode(key_base64.trim_end_matches('=').as_bytes())
.map_err(|_| SubstitutionError::PublicKey)?;
let key_array: [u8; ed25519_dalek::PUBLIC_KEY_LENGTH] = key_bytes
.try_into()
.map_err(|_| SubstitutionError::PublicKey)?;
let verifying_key = ed25519_dalek::VerifyingKey::from_bytes(&key_array)
.map_err(|_| SubstitutionError::PublicKey)?;
Ok((name.to_string(), verifying_key))
}
/// Utility struct representing a store path
#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
#[serde(transparent)]
struct StorePath(String);
impl StorePath {
/// The full name of a path, not including STORE_DIR,
/// e.g. `n50jk09x9hshwx1lh6k3qaiygc7yxbv9-lix-2.90.0-rc1`
pub fn full_name(&self) -> &str {
&self.0
}
/// The base32 hash part of a store path,
/// e.g. `n50jk09x9hshwx1lh6k3qaiygc7yxbv9`
pub fn digest(&self) -> &str {
self.0.split_once('-').unwrap().0
}
/// Full path of the output including STORE_DIR,
/// as seen in StorePath in narinfo
/// e.g. `/nix/store/n50jk09x9hshwx1lh6k3qaiygc7yxbv9-lix-2.90.0-rc1`
pub fn full_path(&self) -> String {
format!("{}{}", STORE_DIR, &self.0)
}
pub fn from_full_path(full_path: &str) -> Option<Self> {
if !full_path.starts_with(STORE_DIR) {
return None;
}
let (_, full_name) = full_path.split_at(STORE_DIR.len());
Self::from_full_name(full_name)
}
pub fn from_path(path: &Path) -> Result<Self, SubstitutionError> {
let path_str = path
.to_str()
.ok_or_else(|| SubstitutionError::InvalidStorePath(path.to_owned()))?;
Self::from_full_path(path_str)
.ok_or_else(|| SubstitutionError::InvalidStorePath(path.to_owned()))
}
pub fn from_full_name(full_name: &str) -> Option<Self> {
let (digest, name) = full_name.split_once('-')?;
if digest.len() != 32
|| digest.contains(|c: char| !c.is_ascii_lowercase() && !c.is_ascii_digit())
{
return None;
}
if name.contains(|c: char| {
!c.is_ascii_alphanumeric()
&& c != '+'
&& c != '-'
&& c != '.'
&& c != '_'
&& c != '?'
&& c != '='
}) {
return None;
}
Some(Self(full_name.to_string()))
}
}
/// Compression types for nar files.
/// Not exhaustive, this is just what
/// I've seen in the real world
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum NarCompression {
Zstd,
Xz,
}
impl NarCompression {
pub fn from_name(name: &str) -> Option<Self> {
match name {
"zstd" => Some(Self::Zstd),
"xz" => Some(Self::Xz),
_ => None,
}
}
}
/// Extracted data from a narinfo.
/// May only be constructed by verifying signature
/// Missing some fields, like Deriver and FileHash because they aren't signed
#[derive(Debug, Clone, PartialEq, Eq)]
struct NarInfo {
/// Store path represented by the nar
pub store_path: StorePath,
/// Full URL to download the nar
pub url: Url,
/// Method used to compress the nar
pub compression: NarCompression,
/// sha256 hash of the nar after decompression
/// encoded in nix base32 format
pub nar_hash: String,
/// Size of the decompressed nar in bytes
pub nar_size: u64,
/// Other store paths referenced by the nar
pub references: Vec<StorePath>,
/// Signature of the nar, used to sign other items
pub sig: Option<(String, Vec<u8>)>,
}
impl NarInfo {
fn parse(substituter_url: &Url, contents: &bytes::Bytes) -> Result<Self, SubstitutionError> {
fn assign_unique_or_error<T>(
field: &mut Option<T>,
value: Result<T, SubstitutionError>,
) -> Result<(), SubstitutionError> {
if field.replace(value?).is_some() {
Err(SubstitutionError::BadNarInfo)
} else {
Ok(())
}
}
let mut store_path = None;
let mut url = None;
let mut compression = None;
let mut nar_hash = None;
let mut nar_size = None;
let mut references = None;
let mut sig = None;
for maybe_line in contents.lines() {
// Error if contents cannot be split into a list of line strings, probably if the NAR isn't valid utf-8
let line = maybe_line.map_err(SubstitutionError::UndecodableNarInfo)?;
let (tag, rest) = line
.split_once(':')
.ok_or_else(|| SubstitutionError::BadNarInfo)?;
let value = rest.trim_start_matches(' ');
match tag {
"StorePath" => {
let path = StorePath::from_full_path(value)
.ok_or_else(|| SubstitutionError::InvalidStorePath(value.into()));
assign_unique_or_error(&mut store_path, path)?
},
"URL" => assign_unique_or_error(
&mut url,
substituter_url
.join(value)
.map_err(SubstitutionError::UrlParseError),
)?,
"Compression" => assign_unique_or_error(
&mut compression,
NarCompression::from_name(value).ok_or(SubstitutionError::BadNarInfo),
)?,
"NarHash" => {
let (algorithm, digest) = value
.split_once(':')
.ok_or_else(|| SubstitutionError::BadNarInfo)?;
if algorithm != "sha256" {
Err(SubstitutionError::BadNarInfo)?
}
assign_unique_or_error(&mut nar_hash, Ok(digest.to_string()))?
},
"NarSize" => assign_unique_or_error(
&mut nar_size,
value.parse().map_err(|_| SubstitutionError::BadNarInfo),
)?,
"References" => {
let refs = if value.is_empty() {
// split on empty strings still returns one value
Ok(Vec::new())
} else {
value
.split(' ')
.map(StorePath::from_full_name)
.map(|value| value.ok_or_else(|| SubstitutionError::BadNarInfo))
.collect::<Result<Vec<_>, _>>()
};
assign_unique_or_error(&mut references, refs)?
},
"Sig" => {
let (signer, base64_signature) = value
.split_once(':')
.ok_or_else(|| SubstitutionError::BadNarInfo)?;
let signature = base64::engine::general_purpose::STANDARD
.decode(base64_signature)
.map_err(|_| SubstitutionError::BadNarInfo)?;
assign_unique_or_error(&mut sig, Ok((signer.to_string(), signature)))?
},
// Ignore any unmatched tags instead of erroring because there are some valid tags we are not parsing
_ => {},
}
}
Ok(Self {
store_path: store_path.ok_or_else(|| SubstitutionError::BadNarInfo)?,
url: url.ok_or_else(|| SubstitutionError::BadNarInfo)?,
compression: compression.ok_or_else(|| SubstitutionError::BadNarInfo)?,
nar_hash: nar_hash.ok_or_else(|| SubstitutionError::BadNarInfo)?,
nar_size: nar_size.ok_or_else(|| SubstitutionError::BadNarInfo)?,
references: references.ok_or_else(|| SubstitutionError::BadNarInfo)?,
sig,
})
}
fn verify(
&self,
trusted_keys: &HashMap<String, VerifyingKey>,
) -> Result<(), SubstitutionError> {
let Some(sig) = &self.sig else {
return Err(SubstitutionError::BadSignature);
};
let Some(key) = trusted_keys.get(&sig.0) else {
return Err(SubstitutionError::BadSignature);
};
// Fingerprint format not documented, but implemented in lix:
// https://git.lix.systems/lix-project/lix/src/commit/d461cc1d7b2f489c3886f147166ba5b5e0e37541/src/libstore/path-info.cc#L25
let fingerprint = format!(
"1;{};sha256:{};{};{}",
self.store_path.full_path(),
self.nar_hash,
self.nar_size,
self.references
.iter()
.map(|reference| reference.full_path())
.collect::<Vec<String>>()
.join(",")
);
key.verify_strict(
fingerprint.as_bytes(),
&ed25519_dalek::Signature::from_bytes(
sig.1
.as_slice()
.try_into()
.map_err(|_| SubstitutionError::BadSignature)?,
),
)
.map_err(|_| SubstitutionError::BadSignature)
}
pub fn parse_and_verify(
require_sigs: bool,
trusted_keys: &HashMap<String, VerifyingKey>,
substituter_url: &Url,
expected_store_path: &StorePath,
contents: &bytes::Bytes,
) -> Result<Self, SubstitutionError> {
let parsed = Self::parse(substituter_url, contents)?;
if &parsed.store_path != expected_store_path {
return Err(SubstitutionError::BadSignature);
}
if require_sigs {
parsed.verify(trusted_keys)?;
}
Ok(parsed)
}
}
static NIX32_CHARS: &[u8; 32] = b"0123456789abcdfghijklmnpqrsvwxyz";
fn encode_nix32(input: &[u8]) -> String {
// ceil(input.len() * 8 / 5)
let length = (input.len() * 8 + 4) / 5;
let mut output = String::with_capacity(length);
// nix32 hashes feel like they're a bug that stuck
// The output is backwards and bits are grouped
// from the least significant bit in each byte
// instead of the most significant bit.
// e.g. for a 4-byte input, bits are mapped from input to output like this:
// Out No.: 5 5 5 6 6 6 6 6 | 3 4 4 4 4 4 5 5 | 2 2 2 2 3 3 3 3 | 0 0 1 1 1 1 1 2
// Out Bit: 2 1 0 4 3 2 1 0 | 0 4 3 2 1 0 4 3 | 3 2 1 0 4 3 2 1 | 1 0 4 3 2 1 0 4
//
// where "Out No." is the index of the output charater responsible for a given bit;
// and "Out Bit" is the value of a given bit within the output character,
// with 4 being most significant and 0 being least significant.
//
// for "Meow" we'd get:
// Char: M (0x4d) e (0x65) o (0x6f) w (0x77)
// Value: 0 1 0 0 1 1 0 1 | 0 1 1 0 0 1 0 1 | 0 1 1 0 1 1 1 1 | 0 1 1 1 0 1 1 1
// Out No.: 5 5 5 6 6 6 6 6 | 3 4 4 4 4 4 5 5 | 2 2 2 2 3 3 3 3 | 0 0 1 1 1 1 1 2
// Out Bit: 2 1 0 4 3 2 1 0 | 0 4 3 2 1 0 4 3 | 3 2 1 0 4 3 2 1 | 1 0 4 3 2 1 0 4
// 6: 01101 (0x0d)
// 5: 01010 (0x0a)
// 4: 11001 (0x19)
// 3: 11110 (0x1e)
// 2: 10110 (0x16)
// 1: 11011 (0x1b)
// 0: 00001 (0x01)
// Indexing into the alphabet gives us "1vnyrad"
for char_no in 0..length {
let bit_no = (length - char_no - 1) * 5;
let byte_no = bit_no / 8;
let bit_offset = bit_no % 8;
let higher_order_byte = *input.get(byte_no + 1).unwrap_or(&0);
let lower_order_byte = input[byte_no];
let window = ((higher_order_byte as u16) << 8) | (lower_order_byte as u16);
let value = (window >> bit_offset) & 0b11111;
output.push(NIX32_CHARS[value as usize] as char);
}
output
}
#[non_exhaustive]
#[derive(Debug, thiserror::Error)]
pub enum SubstitutionError {
#[error("Decompression error for nar from {0}")]
Decompress(Url, #[source] std::io::Error),
#[error("Unpacking error for nar from {0}")]
Unpack(Url, #[source] nix_nar::NarError),
#[error("Unknown proxy scheme, `https://`, `socks5://`, and `http://` supported")]
UnknownProxyScheme,
#[error("Invalid public key")]
/// Normally an ed25519_dalek::SignatureError,
/// but that comes with no extra information so no need to include it
PublicKey,
#[error("Undecodable narinfo")]
UndecodableNarInfo(#[source] std::io::Error),
#[error("Bad narinfo contents")]
BadNarInfo,
#[error("Bad narinfo signature")]
BadSignature,
#[error("Incorrect nar size or hash for {0}")]
BadNar(Url),
#[error("No substituter has path {0}")]
NonexistantNarInfo(String),
#[error("Invalid nix store path {0}")]
InvalidStorePath(PathBuf),
#[error("Url in narinfo could not be parsed \"{0}\"")]
UrlParseError(url::ParseError),
}
impl From<SubstitutionError> for ActionErrorKind {
fn from(val: SubstitutionError) -> Self {
ActionErrorKind::Custom(Box::new(val))
}
}

View file

@ -9,6 +9,7 @@ pub(crate) mod create_or_merge_nix_config;
pub(crate) mod create_user; pub(crate) mod create_user;
pub(crate) mod delete_user; pub(crate) mod delete_user;
pub(crate) mod fetch_and_unpack_nix; pub(crate) mod fetch_and_unpack_nix;
pub(crate) mod fetch_and_unpack_nix_substituter;
pub(crate) mod move_unpacked_nix; pub(crate) mod move_unpacked_nix;
pub(crate) mod remove_directory; pub(crate) mod remove_directory;
pub(crate) mod setup_default_profile; pub(crate) mod setup_default_profile;
@ -22,6 +23,7 @@ pub use create_or_merge_nix_config::CreateOrMergeNixConfig;
pub use create_user::CreateUser; pub use create_user::CreateUser;
pub use delete_user::DeleteUser; pub use delete_user::DeleteUser;
pub use fetch_and_unpack_nix::{FetchAndUnpackNix, FetchUrlError}; pub use fetch_and_unpack_nix::{FetchAndUnpackNix, FetchUrlError};
pub use fetch_and_unpack_nix_substituter::{FetchAndUnpackNixSubstituter, SubstitutionError};
pub use move_unpacked_nix::{MoveUnpackedNix, MoveUnpackedNixError}; pub use move_unpacked_nix::{MoveUnpackedNix, MoveUnpackedNixError};
pub use remove_directory::RemoveDirectory; pub use remove_directory::RemoveDirectory;
pub use setup_default_profile::{SetupDefaultProfile, SetupDefaultProfileError}; pub use setup_default_profile::{SetupDefaultProfile, SetupDefaultProfileError};

View file

@ -6,8 +6,9 @@ use std::{
use tracing::{span, Span}; use tracing::{span, Span};
use walkdir::WalkDir; use walkdir::WalkDir;
use crate::action::{ use crate::{
Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction, action::{Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction},
release_tarball,
}; };
pub(crate) const DEST: &str = "/nix/"; pub(crate) const DEST: &str = "/nix/";
@ -62,15 +63,9 @@ impl Action for MoveUnpackedNix {
let Self { unpacked_path } = self; let Self { unpacked_path } = self;
// This is the `nix-$VERSION` folder which unpacks from the tarball, not a nix derivation // This is the `nix-$VERSION` folder which unpacks from the tarball, not a nix derivation
let found_nix_paths = glob::glob(&format!("{}/nix-*", unpacked_path.display())) let toplevel_path =
.map_err(|e| Self::error(MoveUnpackedNixError::from(e)))? release_tarball::find_toplevel_path(&unpacked_path).map_err(Self::error)?;
.collect::<Result<Vec<_>, _>>() let src_store = toplevel_path.join("store");
.map_err(|e| Self::error(MoveUnpackedNixError::from(e)))?;
if found_nix_paths.len() != 1 {
return Err(Self::error(ActionErrorKind::MalformedBinaryTarball));
}
let found_nix_path = found_nix_paths.into_iter().next().unwrap();
let src_store = found_nix_path.join("store");
let mut src_store_listing = tokio::fs::read_dir(src_store.clone()) let mut src_store_listing = tokio::fs::read_dir(src_store.clone())
.await .await
.map_err(|e| ActionErrorKind::ReadDir(src_store.clone(), e)) .map_err(|e| ActionErrorKind::ReadDir(src_store.clone(), e))

View file

@ -2,7 +2,7 @@ use std::path::PathBuf;
use crate::{ use crate::{
action::{ActionError, ActionErrorKind, ActionTag, StatefulAction}, action::{ActionError, ActionErrorKind, ActionTag, StatefulAction},
execute_command, set_env, execute_command, release_tarball, set_env,
}; };
use glob::glob; use glob::glob;
@ -51,8 +51,10 @@ impl Action for SetupDefaultProfile {
#[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> {
// Find an `nix` package let toplevel_path =
let nix_pkg_glob = format!("{}/nix-*/store/*-nix-*.*.*", self.unpacked_path.display()); release_tarball::find_toplevel_path(&self.unpacked_path).map_err(Self::error)?;
// Find a `nix` package
let nix_pkg_glob = format!("{}/store/*-[nl]ix-*.*.*", toplevel_path.display());
let mut found_nix_pkg = None; let mut found_nix_pkg = None;
for entry in glob(&nix_pkg_glob).map_err(Self::error)? { for entry in glob(&nix_pkg_glob).map_err(Self::error)? {
match entry { match entry {
@ -78,10 +80,7 @@ impl Action for SetupDefaultProfile {
}; };
// Find an `nss-cacert` package, add it too. // Find an `nss-cacert` package, add it too.
let nss_ca_cert_pkg_glob = format!( let nss_ca_cert_pkg_glob = format!("{}/store/*-nss-cacert-*.*", toplevel_path.display());
"{}/nix-*/store/*-nss-cacert-*.*",
self.unpacked_path.display()
);
let mut found_nss_ca_cert_pkg = None; let mut found_nss_ca_cert_pkg = None;
for entry in glob(&nss_ca_cert_pkg_glob).map_err(Self::error)? { for entry in glob(&nss_ca_cert_pkg_glob).map_err(Self::error)? {
match entry { match entry {
@ -108,14 +107,8 @@ impl Action for SetupDefaultProfile {
return Err(Self::error(SetupDefaultProfileError::NoNssCacert)); return Err(Self::error(SetupDefaultProfileError::NoNssCacert));
}; };
let found_nix_paths = glob::glob(&format!("{}/nix-*", self.unpacked_path.display())) let found_nix_path =
.map_err(Self::error)? release_tarball::find_toplevel_path(&self.unpacked_path).map_err(Self::error)?;
.collect::<Result<Vec<_>, _>>()
.map_err(Self::error)?;
if found_nix_paths.len() != 1 {
return Err(Self::error(ActionErrorKind::MalformedBinaryTarball));
}
let found_nix_path = found_nix_paths.into_iter().next().unwrap();
let reginfo_path = found_nix_path.join(".reginfo"); let reginfo_path = found_nix_path.join(".reginfo");
let reginfo = tokio::fs::read(&reginfo_path) let reginfo = tokio::fs::read(&reginfo_path)
.await .await

View file

@ -7,7 +7,7 @@ use crate::action::{
Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction, Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction,
}; };
use crate::parse_ssl_cert; use crate::parse_ssl_cert;
use crate::settings::UrlOrPathOrString; use crate::settings::{UrlOrPathOrString, LIX_DEFAULT_SUBSTITUTERS, LIX_DEFAULT_SUBSTITUTER_KEYS};
use indexmap::map::Entry; use indexmap::map::Entry;
use std::path::PathBuf; use std::path::PathBuf;
@ -136,11 +136,11 @@ impl PlaceNixConfiguration {
// Set up our substituters. // Set up our substituters.
settings.insert( settings.insert(
"substituters".to_string(), "substituters".to_string(),
"https://cache.nixos.org https://cache.lix.systems".to_string(), LIX_DEFAULT_SUBSTITUTERS.join(" "),
); );
settings.insert( settings.insert(
"trusted-public-keys".to_string(), "trusted-public-keys".to_string(),
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o=".to_string() LIX_DEFAULT_SUBSTITUTER_KEYS.join(" "),
); );
if enable_flakes { if enable_flakes {

View file

@ -3,19 +3,52 @@ use tracing::{span, Span};
use super::CreateNixTree; use super::CreateNixTree;
use crate::{ use crate::{
action::{ action::{
base::{FetchAndUnpackNix, MoveUnpackedNix}, base::{FetchAndUnpackNix, FetchAndUnpackNixSubstituter, MoveUnpackedNix},
Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction, Action, ActionDescription, ActionError, ActionErrorKind, ActionTag, StatefulAction,
}, },
settings::{CommonSettings, SCRATCH_DIR}, settings::{CommonSettings, SCRATCH_DIR},
}; };
use std::path::PathBuf; use std::path::PathBuf;
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub enum FetchNix {
FromTarball(StatefulAction<FetchAndUnpackNix>),
FromSubstituter(StatefulAction<FetchAndUnpackNixSubstituter>),
}
impl FetchNix {
pub async fn try_execute(&mut self) -> Result<(), ActionError> {
match self {
FetchNix::FromTarball(action) => action.try_execute().await,
FetchNix::FromSubstituter(action) => action.try_execute().await,
}
}
pub fn describe_execute(&self) -> Vec<ActionDescription> {
match self {
FetchNix::FromTarball(action) => action.describe_execute(),
FetchNix::FromSubstituter(action) => action.describe_execute(),
}
}
pub async fn try_revert(&mut self) -> Result<(), ActionError> {
match self {
FetchNix::FromTarball(action) => action.try_revert().await,
FetchNix::FromSubstituter(action) => action.try_revert().await,
}
}
pub fn describe_revert(&self) -> Vec<ActionDescription> {
match self {
FetchNix::FromTarball(action) => action.describe_revert(),
FetchNix::FromSubstituter(action) => action.describe_revert(),
}
}
}
/** /**
Place Nix and it's requirements onto the target Place Nix and it's requirements onto the target
*/ */
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct ProvisionNix { pub struct ProvisionNix {
fetch_nix: StatefulAction<FetchAndUnpackNix>, fetch_nix: FetchNix,
create_nix_tree: StatefulAction<CreateNixTree>, create_nix_tree: StatefulAction<CreateNixTree>,
move_unpacked_nix: StatefulAction<MoveUnpackedNix>, move_unpacked_nix: StatefulAction<MoveUnpackedNix>,
} }
@ -23,13 +56,30 @@ pub struct ProvisionNix {
impl ProvisionNix { impl ProvisionNix {
#[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 fetch_nix = FetchAndUnpackNix::plan( let fetch_nix = if settings.use_substituters {
FetchNix::FromSubstituter(
FetchAndUnpackNixSubstituter::plan(
settings.substitution_targets.clone(),
PathBuf::from(SCRATCH_DIR),
settings.substituter_trusted_keys.clone(),
settings.substituter_require_sigs,
settings.substituters.clone(),
settings.proxy.clone(),
settings.ssl_cert_file.clone(),
)
.await?,
)
} else {
FetchNix::FromTarball(
FetchAndUnpackNix::plan(
settings.nix_package_url.clone(), settings.nix_package_url.clone(),
PathBuf::from(SCRATCH_DIR), PathBuf::from(SCRATCH_DIR),
settings.proxy.clone(), settings.proxy.clone(),
settings.ssl_cert_file.clone(), settings.ssl_cert_file.clone(),
) )
.await?; .await?,
)
};
let create_nix_tree = CreateNixTree::plan().await.map_err(Self::error)?; let create_nix_tree = CreateNixTree::plan().await.map_err(Self::error)?;
let move_unpacked_nix = MoveUnpackedNix::plan(PathBuf::from(SCRATCH_DIR)) let move_unpacked_nix = MoveUnpackedNix::plan(PathBuf::from(SCRATCH_DIR))

View file

@ -68,7 +68,7 @@ impl MyAction {
#[async_trait::async_trait] #[async_trait::async_trait]
#[typetag::serde(name = "my_action")] #[typetag::serde(name = "my_action")]
impl Action for MyAction { impl Action for MyAction {
fn action_tag() -> nix_installer::action::ActionTag { fn action_tag() -> lix_installer::action::ActionTag {
"my_action".into() "my_action".into()
} }
fn tracing_synopsis(&self) -> String { fn tracing_synopsis(&self) -> String {
@ -488,10 +488,7 @@ pub enum ActionErrorKind {
"".to_string() "".to_string()
} }
)] )]
CommandOutput { CommandOutput { command: String, output: Output },
command: String,
output: Output,
},
#[error("Joining spawned async task")] #[error("Joining spawned async task")]
Join( Join(
#[source] #[source]
@ -509,7 +506,7 @@ pub enum ActionErrorKind {
/// A MacOS (Darwin) plist related error /// A MacOS (Darwin) plist related error
#[error(transparent)] #[error(transparent)]
Plist(#[from] plist::Error), Plist(#[from] plist::Error),
#[error("Unexpected binary tarball contents found, the build result from `https://releases.nixos.org/?prefix=nix/` or `nix build nix#hydraJobs.binaryTarball.$SYSTEM` is expected")] #[error("Unexpected binary tarball contents found, the build result from `https://releases.lix.systems/?prefix=nix/` or `nix build lix#hydraJobs.binaryTarball.$SYSTEM` is expected")]
MalformedBinaryTarball, MalformedBinaryTarball,
#[error("Could not find `{0}` in PATH; This action only works on SteamOS, which should have this present in PATH.")] #[error("Could not find `{0}` in PATH; This action only works on SteamOS, which should have this present in PATH.")]
MissingSteamosBinary(String), MissingSteamosBinary(String),

View file

@ -20,9 +20,9 @@ pub trait CommandExecute {
} }
/** /**
The Determinate Nix installer (lix variant) The Lix installer.
A fast, friendly, and reliable tool to help you use Nix with Flakes everywhere. A fast, friendly, and reliable tool to help you install CppNix or Lix on your system.
*/ */
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
#[clap(version)] #[clap(version)]

View file

@ -42,9 +42,9 @@ use lix_installer::{InstallPlan, planner::Planner};
# async fn chosen_planner_install() -> color_eyre::Result<()> { # async fn chosen_planner_install() -> color_eyre::Result<()> {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
let planner = nix_installer::planner::steam_deck::SteamDeck::default().await?; let planner = lix_installer::planner::steam_deck::SteamDeck::default().await?;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
let planner = nix_installer::planner::macos::Macos::default().await?; let planner = lix_installer::planner::macos::Macos::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.
@ -76,6 +76,7 @@ mod error;
mod os; mod os;
mod plan; mod plan;
pub mod planner; pub mod planner;
mod release_tarball;
pub mod self_test; pub mod self_test;
pub mod settings; pub mod settings;

17
src/release_tarball.rs Normal file
View file

@ -0,0 +1,17 @@
use std::path::{Path, PathBuf};
use crate::action::ActionErrorKind;
/// Finds the top-level path in the tarball, e.g. lix-2.90.0-rc1-x86_64-linux
pub fn find_toplevel_path(unpacked_path: &Path) -> Result<PathBuf, ActionErrorKind> {
let found_nix_paths = glob::glob(&format!("{}/[nl]ix-*", unpacked_path.display()))
.map_err(ActionErrorKind::from)?
.collect::<Result<Vec<_>, _>>()
.map_err(ActionErrorKind::from)?;
if found_nix_paths.len() != 1 {
return Err(ActionErrorKind::MalformedBinaryTarball);
}
let found_nix_path = found_nix_paths.into_iter().next().unwrap();
Ok(found_nix_path)
}

View file

@ -86,7 +86,7 @@ impl Shell {
.as_millis(); .as_millis();
command.arg(format!( command.arg(format!(
r#"nix build --no-link --expr 'derivation {{ name = "self-test-{executable}-{timestamp_millis}"; system = "{SYSTEM}"; builder = "/bin/sh"; args = ["-c" "echo hello > \$out"]; }}'"# r#"nix build --no-substitute --no-link --expr 'derivation {{ name = "self-test-{executable}-{timestamp_millis}"; system = "{SYSTEM}"; builder = "/bin/sh"; args = ["-c" "echo hello > \$out"]; }}'"#
)); ));
let command_str = format!("{:?}", command.as_std()); let command_str = format!("{:?}", command.as_std());

View file

@ -11,21 +11,57 @@ use url::Url;
pub const SCRATCH_DIR: &str = "/nix/temp-install-dir"; pub const SCRATCH_DIR: &str = "/nix/temp-install-dir";
/// Default [`nix_package_url`](CommonSettings::nix_package_url) for Linux x86_64 // See set_version.py
pub const NIX_X64_64_LINUX_URL: &str = // BEGIN GENERATE-URLS
"https://releases.lix.systems/lix/lix-2.90-beta.1/nix-2.90.0-beta.1-x86_64-linux.tar.xz"; /// Default [`nix_package_url`](CommonSettings::nix_package_url) for x86_64-linux.
/// Default [`nix_package_url`](CommonSettings::nix_package_url) for Linux x86 (32 bit) pub const LIX_X86_64_LINUX_URL: &str =
pub const NIX_I686_LINUX_URL: &str = "https://releases.lix.systems/lix/lix-2.90.0/lix-2.90.0-x86_64-linux.tar.xz";
"https://releases.lix.systems/lix/lix-2.90-beta.1/nix-2.90.0-beta.1-i686-linux.tar.xz";
/// Default [`nix_package_url`](CommonSettings::nix_package_url) for Linux aarch64 /// Default [`nix_package_url`](CommonSettings::nix_package_url) for x86_64-darwin.
pub const NIX_AARCH64_LINUX_URL: &str = pub const LIX_X86_64_DARWIN_URL: &str =
"https://releases.lix.systems/lix/lix-2.90-beta.1/nix-2.90.0-beta.1-aarch64-linux.tar.xz"; "https://releases.lix.systems/lix/lix-2.90.0/lix-2.90.0-x86_64-darwin.tar.xz";
/// Default [`nix_package_url`](CommonSettings::nix_package_url) for Darwin x86_64
pub const NIX_X64_64_DARWIN_URL: &str = /// Default [`nix_package_url`](CommonSettings::nix_package_url) for aarch64-linux.
"https://releases.lix.systems/lix/lix-2.90-beta.1/nix-2.90.0-beta.1-x86_64-darwin.tar.xz"; pub const LIX_AARCH64_LINUX_URL: &str =
/// Default [`nix_package_url`](CommonSettings::nix_package_url) for Darwin aarch64 "https://releases.lix.systems/lix/lix-2.90.0/lix-2.90.0-aarch64-linux.tar.xz";
pub const NIX_AARCH64_DARWIN_URL: &str =
"https://releases.lix.systems/lix/lix-2.90-beta.1/nix-2.90.0-beta.1-aarch64-darwin.tar.xz"; /// Default [`nix_package_url`](CommonSettings::nix_package_url) for aarch64-darwin.
pub const LIX_AARCH64_DARWIN_URL: &str =
"https://releases.lix.systems/lix/lix-2.90.0/lix-2.90.0-aarch64-darwin.tar.xz";
/// Default [`substitution_targets`](CommonSettings::substitution_targets) for aarch64-darwin.
pub const LIX_AARCH64_DARWIN_SUBSTITUTION_TARGETS: &[&str; 2] = &[
"/nix/store/7hhkbhcqj9rii306yv83g6k26rcflssh-lix-2.90.0",
"/nix/store/dnzgnky19lq1gnyx4qrzrxi2qs2yvjin-nss-cacert-3.98",
];
/// Default [`substitution_targets`](CommonSettings::substitution_targets) for aarch64-linux.
pub const LIX_AARCH64_LINUX_SUBSTITUTION_TARGETS: &[&str; 2] = &[
"/nix/store/l2ykng7d4pjiwz0791xnxy7br5261dxg-lix-2.90.0",
"/nix/store/k78zmyfjzaas4ryaaigbdsbfqj3myzdr-nss-cacert-3.98",
];
/// Default [`substitution_targets`](CommonSettings::substitution_targets) for x86_64-darwin.
pub const LIX_X86_64_DARWIN_SUBSTITUTION_TARGETS: &[&str; 2] = &[
"/nix/store/ylqvqp34kyvzvwshqs738k8l8saxwy16-lix-2.90.0",
"/nix/store/hc8xagapf38y3mvfarhi7jcwnfa5w3n9-nss-cacert-3.98",
];
/// Default [`substitution_targets`](CommonSettings::substitution_targets) for x86_64-linux.
pub const LIX_X86_64_LINUX_SUBSTITUTION_TARGETS: &[&str; 2] = &[
"/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0",
"/nix/store/26n4d7n6bm3d1kvai6zmvzx929z9q5c9-nss-cacert-3.98",
];
// END GENERATE-URLS
pub const LIX_DEFAULT_SUBSTITUTERS: &[&str; 2] =
&["https://cache.nixos.org", "https://cache.lix.systems"];
pub const LIX_DEFAULT_SUBSTITUTER_KEYS: &[&str; 2] = &[
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=",
"cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o=",
];
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, Copy, PartialEq, Eq)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "cli", derive(clap::ValueEnum))] #[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
@ -142,6 +178,68 @@ pub struct CommonSettings {
)] )]
pub nix_build_user_id_base: u32, pub nix_build_user_id_base: u32,
/// Substituters used to download Lix, when enabled
#[cfg_attr(
feature = "cli",
clap(long, env = "NIX_INSTALLER_SUBSTITUTERS", default_values = LIX_DEFAULT_SUBSTITUTERS)
)]
pub substituters: Vec<Url>,
/// Trusted signing keys for substituters
#[cfg_attr(
feature = "cli",
clap(long, env = "NIX_INSTALLER_TRUSTED_KEYS", default_values = LIX_DEFAULT_SUBSTITUTER_KEYS)
)]
pub substituter_trusted_keys: Vec<String>,
/// Store paths to download when use_substituters is set. Should include lix and cacert
#[cfg_attr(
feature = "cli",
clap(long, env = "NIX_INSTALLER_SUBSTITUTION_TARGETS",)
)]
#[cfg_attr(
all(target_os = "macos", target_arch = "x86_64", feature = "cli"),
clap(
default_values = LIX_X86_64_DARWIN_SUBSTITUTION_TARGETS,
)
)]
#[cfg_attr(
all(target_os = "macos", target_arch = "aarch64", feature = "cli"),
clap(
default_values = LIX_AARCH64_DARWIN_SUBSTITUTION_TARGETS,
)
)]
#[cfg_attr(
all(target_os = "linux", target_arch = "x86_64", feature = "cli"),
clap(
default_values = LIX_X86_64_LINUX_SUBSTITUTION_TARGETS,
)
)]
#[cfg_attr(
all(target_os = "linux", target_arch = "aarch64", feature = "cli"),
clap(
default_values = LIX_AARCH64_LINUX_SUBSTITUTION_TARGETS,
)
)]
pub substitution_targets: Vec<PathBuf>,
/// Require trusted signatures when downloading from substituters
#[cfg_attr(
feature = "cli",
clap(
action(ArgAction::SetFalse),
default_value = "true",
global = true,
env = "NIX_INSTALLER_REQUIRE_SIGS",
long = "no-require-sigs"
)
)]
pub substituter_require_sigs: bool,
/// Download Lix from a substituter instead of an install tarball
#[cfg_attr(feature = "cli", clap(long, env = "NIX_INSTALLER_USE_SUBSTITUTER"))]
pub use_substituters: bool,
/// The Nix package URL /// The Nix package URL
#[cfg_attr( #[cfg_attr(
feature = "cli", feature = "cli",
@ -150,31 +248,34 @@ pub struct CommonSettings {
#[cfg_attr( #[cfg_attr(
all(target_os = "macos", target_arch = "x86_64", feature = "cli"), all(target_os = "macos", target_arch = "x86_64", feature = "cli"),
clap( clap(
default_value = NIX_X64_64_DARWIN_URL, default_value = LIX_X86_64_DARWIN_URL,
) )
)] )]
#[cfg_attr( #[cfg_attr(
all(target_os = "macos", target_arch = "aarch64", feature = "cli"), all(target_os = "macos", target_arch = "aarch64", feature = "cli"),
clap( clap(
default_value = NIX_AARCH64_DARWIN_URL, default_value = LIX_AARCH64_DARWIN_URL,
) )
)] )]
#[cfg_attr( #[cfg_attr(
all(target_os = "linux", target_arch = "x86_64", feature = "cli"), all(target_os = "linux", target_arch = "x86_64", feature = "cli"),
clap( clap(
default_value = NIX_X64_64_LINUX_URL, default_value = LIX_X86_64_LINUX_URL,
) )
)] )]
// FIXME(i686): release i686 binaries again
/*
#[cfg_attr( #[cfg_attr(
all(target_os = "linux", target_arch = "x86", feature = "cli"), all(target_os = "linux", target_arch = "x86", feature = "cli"),
clap( clap(
default_value = NIX_I686_LINUX_URL, default_value = LIX_I686_LINUX_URL,
) )
)] )]
*/
#[cfg_attr( #[cfg_attr(
all(target_os = "linux", target_arch = "aarch64", feature = "cli"), all(target_os = "linux", target_arch = "aarch64", feature = "cli"),
clap( clap(
default_value = NIX_AARCH64_LINUX_URL, default_value = LIX_AARCH64_LINUX_URL,
) )
)] )]
pub nix_package_url: UrlOrPath, pub nix_package_url: UrlOrPath,
@ -216,12 +317,12 @@ pub struct CommonSettings {
) )
)] )]
pub enable_flakes: bool, pub enable_flakes: bool,
} }
impl CommonSettings { impl CommonSettings {
/// The default settings for the given Architecture & Operating System /// The default settings for the given Architecture & Operating System
pub async fn default() -> Result<Self, InstallSettingsError> { pub async fn default() -> Result<Self, InstallSettingsError> {
let substitution_targets;
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;
@ -231,21 +332,26 @@ impl CommonSettings {
match (Architecture::host(), OperatingSystem::host()) { match (Architecture::host(), OperatingSystem::host()) {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
(Architecture::X86_64, OperatingSystem::Linux) => { (Architecture::X86_64, OperatingSystem::Linux) => {
url = NIX_X64_64_LINUX_URL; substitution_targets = LIX_X86_64_LINUX_SUBSTITUTION_TARGETS;
url = LIX_X86_64_LINUX_URL;
nix_build_user_prefix = "nixbld"; nix_build_user_prefix = "nixbld";
nix_build_user_id_base = 30000; nix_build_user_id_base = 30000;
nix_build_user_count = 32; nix_build_user_count = 32;
}, },
// FIXME(i686): support i686-linux again
/*
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
(Architecture::X86_32(_), OperatingSystem::Linux) => { (Architecture::X86_32(_), OperatingSystem::Linux) => {
url = NIX_I686_LINUX_URL; url = LIX_I686_LINUX_URL;
nix_build_user_prefix = "nixbld"; nix_build_user_prefix = "nixbld";
nix_build_user_id_base = 30000; nix_build_user_id_base = 30000;
nix_build_user_count = 32; nix_build_user_count = 32;
}, },
*/
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
(Architecture::Aarch64(_), OperatingSystem::Linux) => { (Architecture::Aarch64(_), OperatingSystem::Linux) => {
url = NIX_AARCH64_LINUX_URL; substitution_targets = LIX_AARCH64_LINUX_SUBSTITUTION_TARGETS;
url = LIX_AARCH64_LINUX_URL;
nix_build_user_prefix = "nixbld"; nix_build_user_prefix = "nixbld";
nix_build_user_id_base = 30000; nix_build_user_id_base = 30000;
nix_build_user_count = 32; nix_build_user_count = 32;
@ -253,7 +359,8 @@ impl CommonSettings {
#[cfg(target_os = "macos")] #[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; substitution_targets = LIX_X86_64_DARWIN_SUBSTITUTION_TARGETS;
url = LIX_X86_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;
nix_build_user_count = 32; nix_build_user_count = 32;
@ -261,7 +368,8 @@ impl CommonSettings {
#[cfg(target_os = "macos")] #[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; substitution_targets = LIX_AARCH64_DARWIN_SUBSTITUTION_TARGETS;
url = LIX_AARCH64_DARWIN_URL;
nix_build_user_prefix = "_nixbld"; nix_build_user_prefix = "_nixbld";
nix_build_user_id_base = 300; nix_build_user_id_base = 300;
nix_build_user_count = 32; nix_build_user_count = 32;
@ -280,6 +388,20 @@ impl CommonSettings {
nix_build_user_id_base, nix_build_user_id_base,
nix_build_user_count, nix_build_user_count,
nix_build_user_prefix: nix_build_user_prefix.to_string(), nix_build_user_prefix: nix_build_user_prefix.to_string(),
substituters: LIX_DEFAULT_SUBSTITUTERS
.iter()
.map(|s| s.parse())
.collect::<Result<Vec<_>, _>>()?,
substituter_trusted_keys: LIX_DEFAULT_SUBSTITUTER_KEYS
.iter()
.map(|s| s.to_string())
.collect(),
substitution_targets: substitution_targets
.iter()
.map(|s| PathBuf::from(*s))
.collect(),
substituter_require_sigs: true,
use_substituters: false,
nix_package_url: url.parse()?, nix_package_url: url.parse()?,
proxy: Default::default(), proxy: Default::default(),
extra_conf: Default::default(), extra_conf: Default::default(),
@ -298,6 +420,11 @@ impl CommonSettings {
nix_build_user_prefix, nix_build_user_prefix,
nix_build_user_id_base, nix_build_user_id_base,
nix_build_user_count, nix_build_user_count,
substituters,
substituter_trusted_keys,
substitution_targets,
substituter_require_sigs,
use_substituters,
nix_package_url, nix_package_url,
proxy, proxy,
extra_conf, extra_conf,
@ -331,10 +458,27 @@ impl CommonSettings {
"nix_build_user_count".into(), "nix_build_user_count".into(),
serde_json::to_value(nix_build_user_count)?, serde_json::to_value(nix_build_user_count)?,
); );
map.insert(
"substituter_trusted_keys".into(),
serde_json::to_value(substituter_trusted_keys)?,
);
map.insert(
"substitution_targets".into(),
serde_json::to_value(substitution_targets)?,
);
map.insert(
"substituter_require_sigs".into(),
serde_json::to_value(substituter_require_sigs)?,
);
map.insert(
"use_substituters".into(),
serde_json::to_value(use_substituters)?,
);
map.insert( map.insert(
"nix_package_url".into(), "nix_package_url".into(),
serde_json::to_value(nix_package_url)?, serde_json::to_value(nix_package_url)?,
); );
map.insert("substituters".into(), serde_json::to_value(substituters)?);
map.insert("proxy".into(), serde_json::to_value(proxy)?); map.insert("proxy".into(), serde_json::to_value(proxy)?);
map.insert("ssl_cert_file".into(), serde_json::to_value(ssl_cert_file)?); map.insert("ssl_cert_file".into(), serde_json::to_value(ssl_cert_file)?);
map.insert("extra_conf".into(), serde_json::to_value(extra_conf)?); map.insert("extra_conf".into(), serde_json::to_value(extra_conf)?);

View file

@ -17,6 +17,7 @@
"action": { "action": {
"action": "provision_nix", "action": "provision_nix",
"fetch_nix": { "fetch_nix": {
"FromTarball": {
"action": { "action": {
"url_or_path": { "url_or_path": {
"Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz" "Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz"
@ -26,6 +27,7 @@
"ssl_cert_file": null "ssl_cert_file": null
}, },
"state": "Uncompleted" "state": "Uncompleted"
}
}, },
"delete_users": [], "delete_users": [],
"create_group": { "create_group": {
@ -409,6 +411,19 @@
"nix_build_user_count": 0, "nix_build_user_count": 0,
"nix_build_user_prefix": "nixbld", "nix_build_user_prefix": "nixbld",
"nix_build_user_id_base": 30000, "nix_build_user_id_base": 30000,
"substituters": [
"https://cache.nixos.org/",
"https://cache.lix.systems/"
],
"substituter_trusted_keys": [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=",
"cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o="
],
"substitution_targets": [
"/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0"
],
"substituter_require_sigs": true,
"use_substituters": false,
"nix_package_url": { "nix_package_url": {
"Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz" "Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz"
}, },
@ -416,6 +431,7 @@
"ssl_cert_file": null, "ssl_cert_file": null,
"extra_conf": [], "extra_conf": [],
"force": false, "force": false,
"enable_flakes": true
}, },
"init": { "init": {
"init": "Systemd", "init": "Systemd",

View file

@ -61,6 +61,7 @@
"action": { "action": {
"action": "provision_nix", "action": "provision_nix",
"fetch_nix": { "fetch_nix": {
"FromTarball": {
"action": { "action": {
"url_or_path": { "url_or_path": {
"Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz" "Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz"
@ -70,6 +71,7 @@
"ssl_cert_file": null "ssl_cert_file": null
}, },
"state": "Uncompleted" "state": "Uncompleted"
}
}, },
"delete_users": [], "delete_users": [],
"create_group": { "create_group": {
@ -393,6 +395,19 @@
"nix_build_user_count": 0, "nix_build_user_count": 0,
"nix_build_user_prefix": "nixbld", "nix_build_user_prefix": "nixbld",
"nix_build_user_id_base": 30000, "nix_build_user_id_base": 30000,
"substituters": [
"https://cache.nixos.org/",
"https://cache.lix.systems/"
],
"substituter_trusted_keys": [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=",
"cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o="
],
"substitution_targets": [
"/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0"
],
"substituter_require_sigs": true,
"use_substituters": false,
"nix_package_url": { "nix_package_url": {
"Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz" "Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-linux.tar.xz"
}, },
@ -400,6 +415,7 @@
"ssl_cert_file": null, "ssl_cert_file": null,
"extra_conf": [], "extra_conf": [],
"force": false, "force": false,
"enable_flakes": true
} }
}, },
"diagnostic_data": { "diagnostic_data": {

View file

@ -87,6 +87,7 @@
"action": { "action": {
"action": "provision_nix", "action": "provision_nix",
"fetch_nix": { "fetch_nix": {
"FromTarball": {
"action": { "action": {
"url_or_path": { "url_or_path": {
"Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-darwin.tar.xz" "Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-darwin.tar.xz"
@ -96,6 +97,7 @@
"ssl_cert_file": null "ssl_cert_file": null
}, },
"state": "Uncompleted" "state": "Uncompleted"
}
}, },
"delete_users_in_group": null, "delete_users_in_group": null,
"create_group": { "create_group": {
@ -420,6 +422,19 @@
"nix_build_user_count": 32, "nix_build_user_count": 32,
"nix_build_user_prefix": "_nixbld", "nix_build_user_prefix": "_nixbld",
"nix_build_user_id_base": 300, "nix_build_user_id_base": 300,
"substituters": [
"https://cache.nixos.org/",
"https://cache.lix.systems/"
],
"substituter_trusted_keys": [
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=",
"cache.lix.systems:aBnZUw8zA7H35Cz2RyKFVs3H4PlGTLawyY5KRbvJR8o="
],
"substitution_target": [
"/nix/store/rp7y16q2py2n9y19jvxkjr83lp77bh7y-lix-2.90.0"
],
"substituter_require_sigs": true,
"use_substituters": false,
"nix_package_url": { "nix_package_url": {
"Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-darwin.tar.xz" "Url": "https://releases.nixos.org/nix/nix-2.17.0/nix-2.17.0-x86_64-darwin.tar.xz"
}, },
@ -427,6 +442,7 @@
"ssl_cert_file": null, "ssl_cert_file": null,
"extra_conf": [], "extra_conf": [],
"force": false, "force": false,
"enable_flakes": true
}, },
"encrypt": null, "encrypt": null,
"case_sensitive": false, "case_sensitive": false,

View file

@ -103,7 +103,7 @@ if args.make_default:
aws s3 @(aws_args) cp @(folder)/lix-installer-@(in_filename) @(default_path)/lix-installer-@(out_filename) --acl public-read aws s3 @(aws_args) cp @(folder)/lix-installer-@(in_filename) @(default_path)/lix-installer-@(out_filename) --acl public-read
printerr(f"\n>> Updating base install script...") printerr(f"\n>> Updating base install script...")
aws s3 @(aws_args) cp nix-installer.sh @(default_path) --acl public-read aws s3 @(aws_args) cp lix-installer.sh @(default_path) --acl public-read
# Make sure all of our lines are out. # Make sure all of our lines are out.
sys.stderr.flush() sys.stderr.flush()