Skip to content

Commit

Permalink
Merge pull request #1610 from cachix/detect-caches
Browse files Browse the repository at this point in the history
devenv: skip the cache warning if the requested substituters are already configured
  • Loading branch information
domenkozar authored Nov 28, 2024
2 parents a520f05 + 8056ceb commit 7a105e8
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 50 deletions.
26 changes: 21 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
resolver = "2"
members = ["devenv", "devenv-eval-cache", "devenv-run-tests", "devenv-tasks", "xtask"]
members = ["devenv", "devenv-eval-cache", "devenv-run-tests", "devenv-tasks", "nix-conf-parser", "xtask"]

[workspace.package]
edition = "2021"
Expand All @@ -13,6 +13,7 @@ devenv = { path = "devenv" }
devenv-eval-cache = { path = "devenv-eval-cache" }
devenv-run-tests = { path = "devenv-run-tests" }
devenv-tasks = { path = "devenv-tasks" }
nix-conf-parser = { path = "nix-conf-parser" }
xtask = { path = "xtask" }

ansiterm = "0.12.2"
Expand All @@ -24,6 +25,7 @@ dotlock = "0.5.0"
futures = "0.3.30"
hex = "0.4.3"
include_dir = "0.7.3"
indexmap = "2.6.0"
indoc = "2.0.4"
lazy_static = "1.5.0"
miette = { version = "7.1.0", features = ["fancy"] }
Expand Down
1 change: 1 addition & 0 deletions devenv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ default-run = "devenv"
[dependencies]
devenv-eval-cache.workspace = true
devenv-tasks.workspace = true
nix-conf-parser.workspace = true

clap.workspace = true
cli-table.workspace = true
Expand Down
154 changes: 110 additions & 44 deletions devenv/src/cnix.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{cli, config, log};
use miette::{bail, IntoDiagnostic, Result, WrapErr};
use nix_conf_parser::NixConf;
use serde::Deserialize;
use sqlx::SqlitePool;
use std::cell::{Ref, RefCell};
Expand Down Expand Up @@ -588,6 +589,16 @@ impl<'a> Nix<'a> {
Ok(cmd)
}

async fn get_nix_config(&self) -> Result<NixConf> {
let options = Options {
logging: false,
..self.options
};
let raw_conf = self.run_nix("nix", &["config", "show"], &options).await?;
let nix_conf = NixConf::parse_stdout(&raw_conf.stdout)?;
Ok(nix_conf)
}

async fn get_cachix_caches(&self) -> Result<Ref<CachixCaches>> {
if self.cachix_caches.borrow().is_none() {
let no_logging = Options {
Expand Down Expand Up @@ -646,7 +657,7 @@ impl<'a> Nix<'a> {
.trusted;
if trusted.is_none() {
self.logger.warn(
"You're using very old version of Nix, please upgrade and restart nix-daemon.",
"You're using an outdated version of Nix. Please upgrade and restart the nix-daemon.",
);
}
let restart_command = if cfg!(target_os = "linux") {
Expand All @@ -673,68 +684,123 @@ impl<'a> Nix<'a> {
)
.expect("Failed to write cachix caches to file");

// If the user is not a trusted user, we can't set up the caches for them.
// Check if all of the requested caches and their public keys are in the substituters and trusted-public-keys lists.
// If not, suggest actions to remedy the issue.
if trusted == Some(0) {
if !Path::new("/etc/NIXOS").exists() {
self.logger.error(&indoc::formatdoc!(
"You're not a trusted user of the Nix store. You have the following options:
let mut missing_caches = Vec::new();
let mut missing_public_keys = Vec::new();

if let Ok(nix_conf) = self.get_nix_config().await {
let substituters = nix_conf
.get("substituters")
.map(|s| s.split_whitespace().collect::<Vec<_>>());

if let Some(substituters) = substituters {
for cache in caches.caches.pull.iter() {
let cache_url = format!("https://{}.cachix.org", cache);
if !substituters.iter().any(|s| s == &cache_url) {
missing_caches.push(cache_url);
}
}
}

let trusted_public_keys = nix_conf
.get("trusted-public-keys")
.map(|s| s.split_whitespace().collect::<Vec<_>>());

if let Some(trusted_public_keys) = trusted_public_keys {
for (_name, key) in caches.known_keys.iter() {
if !trusted_public_keys.iter().any(|p| p == key) {
missing_public_keys.push(key.clone());
}
}
}
}

if !missing_caches.is_empty() || !missing_public_keys.is_empty() {
if !Path::new("/etc/NIXOS").exists() {
self.logger.error(&indoc::formatdoc!(
"Failed to set up binary caches:
{}
devenv is configured to automatically manage binary caches with `cachix.enable = true`, but cannot do so because you are not a trusted user of the Nix store.
a) Add yourself to the trusted-users list in /etc/nix/nix.conf for devenv to manage caches for you.
You have several options:
trusted-users = root {}
a) To let devenv set up the caches for you, add yourself to the trusted-users list in /etc/nix/nix.conf:
Restart nix-daemon with:
trusted-users = root {}
$ {restart_command}
Then restart the nix-daemon:
b) Add binary caches to /etc/nix/nix.conf yourself:
$ {restart_command}
extra-substituters = {}
extra-trusted-public-keys = {}
b) Add the missing binary caches to /etc/nix/nix.conf yourself:
And disable automatic cache configuration in `devenv.nix`:
extra-substituters = {}
extra-trusted-public-keys = {}
{{
cachix.enable = false;
}}
", whoami::username()
, caches.caches.pull.iter().map(|cache| format!("https://{}.cachix.org", cache)).collect::<Vec<String>>().join(" ")
, caches.known_keys.values().cloned().collect::<Vec<String>>().join(" ")
c) Disable automatic cache management in your devenv configuration:
{{
cachix.enable = false;
}}
"
, missing_caches.join(" ")
, whoami::username()
, missing_caches.join(" ")
, missing_public_keys.join(" ")
));
} else {
self.logger.error(&indoc::formatdoc!(
"You're not a trusted user of the Nix store. You have the following options:
} else {
self.logger.error(&indoc::formatdoc!(
"Failed to set up binary caches:
{}
devenv is configured to automatically manage binary caches with `cachix.enable = true`, but cannot do so because you are not a trusted user of the Nix store.
You have several options:
a) Add yourself to the trusted-users list in /etc/nix/nix.conf by editing configuration.nix for devenv to manage caches for you.
a) To let devenv set up the caches for you, add yourself to the trusted-users list in /etc/nix/nix.conf by editing configuration.nix.
{{
nix.extraOptions = ''
trusted-users = root {}
'';
}}
{{
nix.settings.trusted-users = [ \"root\" \"{}\" ];
}}
b) Add binary caches to /etc/nix/nix.conf yourself by editing configuration.nix:
{{
nix.extraOptions = ''
extra-substituters = {}
extra-trusted-public-keys = {}
'';
}}
Rebuild your system:
Disable automatic cache configuration in `devenv.nix`:
$ sudo nixos-rebuild switch
{{
cachix.enable = false;
}}
b) Add the missing binary caches to /etc/nix/nix.conf yourself by editing configuration.nix:
Lastly, rebuild your system:
{{
nix.extraOptions = ''
extra-substituters = {}
extra-trusted-public-keys = {}
'';
}}
$ sudo nixos-rebuild switch
", whoami::username()
, caches.caches.pull.iter().map(|cache| format!("https://{}.cachix.org", cache)).collect::<Vec<String>>().join(" ")
, caches.known_keys.values().cloned().collect::<Vec<String>>().join(" ")
Rebuild your system:
$ sudo nixos-rebuild switch
c) Disable automatic cache management in your devenv configuration:
{{
cachix.enable = false;
}}
"
, missing_caches.join(" ")
, whoami::username()
, missing_caches.join(" ")
, missing_public_keys.join(" ")
));
}

bail!("You're not a trusted user of the Nix store.")
}
bail!("You're not a trusted user of the Nix store.")
}
}

Expand Down
10 changes: 10 additions & 0 deletions nix-conf-parser/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "nix-conf-parser"
version = "0.0.1"
edition.workspace = true
license.workspace = true

[dependencies]
indexmap.workspace = true
miette.workspace = true
thiserror.workspace = true
Loading

0 comments on commit 7a105e8

Please sign in to comment.