crane icon indicating copy to clipboard operation
crane copied to clipboard

Replacing default cargo registry results in failed build

Open basbebe opened this issue 2 months ago • 3 comments

Describe the bug

I'm trying to use a local cache as a replacement for the default crates-io registry.
Local builds using cargo work (see config below).
However, building with crane fails with an error (see below) as soon as I add replace-with = "cargo-proxy" to my project's config.toml.

Reproduction

Using c6b4d5308293d0d04fcfeee92705017537cad02f

./.cargo/config.toml

[registries]
cargo-proxy = { index = "sparse+https://myproxy.tld/repository/cargo/" }

[registry]
default = "cargo-proxy"

[source]

[source.crates-io]
replace-with = "cargo-proxy"

in flake.nix

          craneLibOrig = (crane.mkLib pkgs).overrideToolchain rustToolchain;
          craneLib = craneLibOrig.appendCrateRegistries [
            (craneLibOrig.registryFromSparse {
              indexUrl = "https://myproxy.tld/repository/cargo/";
              # where the sha256 is the sha256 of https://myproxy.tld/repository/cargo/config.json.
              configSha256 = "6589c57754423705767e15585a958332bfa859a6ca63d8fd99586e5837774b62";
              fetchurlExtraArgs = { };
            })
          ];

log:

building '/nix/store/3hvyk4hadvd8c64lmbjdm31djwhii79f-mycrate-deps-0.1.0.drv'...
mycrate-deps> cargoArtifacts not set, will not reuse any cargo artifacts
mycrate-deps> Running phase: unpackPhase
mycrate-deps> unpacking source archive /nix/store/hr4y6kql2pcfnakna14nan2dzrz70xgk-source
mycrate-deps> source root is source
mycrate-deps> Running phase: patchPhase
mycrate-deps> Executing configureCargoCommonVars
mycrate-deps> Running phase: updateAutotoolsGnuConfigScriptsPhase
mycrate-deps> Running phase: configurePhase
mycrate-deps> will append /build/source/.cargo-home/config.toml with contents of /nix/store/wdzfws3yg4qzk929xgp4pc2389lib03r-vendor-cargo-deps/config.toml
mycrate-deps> default configurePhase, nothing to do
mycrate-deps> Running phase: buildPhase
mycrate-deps> +++ command cargo --version
mycrate-deps> cargo 1.90.0 (840b83a10 2025-07-30)
mycrate-deps> +++ command cargo check --profile dev --locked --all-targets
mycrate-deps>     Updating `cargo-proxy` index
mycrate-deps> warning: spurious network error (3 tries remaining): [6] Could not resolve hostname (Could not resolve host: myproxy.tld)
mycrate-deps> warning: spurious network error (2 tries remaining): [6] Could not resolve hostname (Could not resolve host: myproxy.tld)
mycrate-deps> warning: spurious network error (1 try remaining): [6] Could not resolve hostname (Could not resolve host: myproxy.tld)
mycrate-deps> error: failed to get `[…]` as a dependency of package `[…]`
mycrate-deps>
mycrate-deps> Caused by:
mycrate-deps>   failed to query replaced source registry `crates-io`
mycrate-deps>
mycrate-deps> Caused by:
mycrate-deps>   download of config.json failed
mycrate-deps>
mycrate-deps> Caused by:
mycrate-deps>   failed to download from `https://myproxy.tld/repository/cargo/config.json`
mycrate-deps>
mycrate-deps> Caused by:
mycrate-deps>   [6] Could not resolve hostname (Could not resolve host: myproxy.tld)

Anything I'm missing / I could try?

basbebe avatar Oct 27 '25 14:10 basbebe

Hi @basbebe thanks for the report!

What does your Cargo.lock file look like? Do the entries for crates reference crates.io or your own registry?

The way vendoring works is we add a source replacement stanza in $HOME/.cargo/config.toml (or the analogue to $HOME inside of the derivation sandbox, but worth noting that this file is outside of your project directory) which points cargo to all the sources we vendor. However, this file is of lower precedence than your project's .cargo/config.toml so I suspect your override (to your proxy registry) ends up overriding the ones crane injects, and so cargo tries to fetch the sources from the network and fails inside of the sandbox.

One thing you can try doing is adding your own postUnpack or postPatch hooks to delete the proxy source replacement stanza in your .cargo/config.toml file (just for Nix builds) and seeing if that helps

ipetkov avatar Nov 01 '25 01:11 ipetkov

Thanks for detailing the vendoring steps!

Yes, the Cargo.lock file references crates.io.

The replace-with statement brings the convenience of not having to replace all dependencies' "registry".

Where would I put the postUnpack step?
Into a buildDepsOnly step or as an argument to all crane derivations?

The registry cache should be used also when crane/nix fetches those dependency crates…

basbebe avatar Nov 01 '25 10:11 basbebe

Where would I put the postUnpack step? Into a buildDepsOnly step or as an argument to all crane derivations?

You'd want it to run as part of all derivations (since they all need the vendored dependencies). You can stick it in commonArgs, or wherever it ends up in both buildDepsOnly and other derivations

The registry cache should be used also when crane/nix fetches those dependency crates…

If you really want this to be the case then the easiest thing would be to update your Cargo.lock file to be using the proxy registry and not crates.io and then things will just work out of the box.

There are ways to achieve this without updating the Cargo.lock itself (like parsing with Nix during evaluation, effectively rewriting the registry of the package, and then passing that into vendorCargoDeps), but it will be up to you to [read the API docs] and decide what level of effort is worth it!

ipetkov avatar Nov 07 '25 18:11 ipetkov