Repository navigation
Description
What problem are you trying to solve?
Summary
Devbox hard-codes https://cache.nixos.org as its binary cache. Nix itself can be pointed at a mirror (substituters in nix.conf), but devbox still contacts cache.nixos.org directly. As a result, devbox can't install packages where only an internal mirror is reachable (air-gapped CI runners, corporate networks), even when the project has a complete devbox.lock and every package is available from the mirror.
Please add an environment variable, for example DEVBOX_BINARY_CACHE, that overrides this URL. That would match how DEVBOX_SEARCH_HOST and DEVBOX_CACHE work today.
Environment
- Devbox 0.18.4 (official
devbox_0.18.4_linux_amd64release binary); also reproduced with 0.17.2 - Nix 2.35.2
- Linux x86_64 (container)
nix.conf:substituters = https://artifactory.example.com/artifactory/api/nix/cache.nixos.org-nix-remote(a pull-through mirror ofcache.nixos.org)DEVBOX_CACHE=https://artifactory.example.com/artifactory/github.com(a mirror ofgithub.com)
Steps to reproduce
- On a machine with internet access, create a project and commit its
devbox.jsonanddevbox.lock:devbox init && devbox add hello - In an environment where only the mirror is reachable (outbound traffic to
cache.nixos.org,github.cometc. is blocked) and Nix'ssubstituterspoints at the mirror, run:devbox install
Actual behavior
Devbox sends HEAD https://cache.nixos.org/<hash>.narinfo. That request fails, so devbox treats the package as not cached and builds it from nixpkgs sources on GitHub:
Info: Installing the following packages to the nix store: hello@latest
unpacking 'github:NixOS/nixpkgs/c27cdad491a991b11ed731760aa2ef8db0cb0410' into the Git cache...
error:
… while fetching the input 'github:NixOS/nixpkgs/c27cdad491a991b11ed731760aa2ef8db0cb0410'
error: Failed to open archive (Source threw exception: error: unable to download 'https://github.com/NixOS/nixpkgs/archive/c27cdad491a991b11ed731760aa2ef8db0cb0410.tar.gz': Could not connect to server (7) CONNECT tunnel failed, response 403)
Error: nix: command error: nix ... build --impure --no-link 'github:NixOS/nixpkgs/c27cdad491a991b11ed731760aa2ef8db0cb0410#hello': exit code 1
The locked store path (/nix/store/wzr035k31pmpn2caabq8qwv1npg571z9-hello-2.12.3) is available from the configured substituter. If devbox knew the package was cached, Nix could substitute it directly. This fallback also ignores DEVBOX_CACHE.
In 0.17.2 the failed request was a hard error instead:
Error: Head "https://cache.nixos.org/wzr035k31pmpn2caabq8qwv1npg571z9.narinfo": Filtered
Expected behavior
Devbox either uses a binary cache URL I can configure, or follows Nix's configured substituters, so that installing a locked project needs only the mirror.
Where the URL is hard-coded (v0.18.4)
| Location | Purpose |
|---|---|
internal/devpkg/narinfo_cache.go:19: const binaryCache = "https://cache.nixos.org" |
HEAD request for <hash>.narinfo to decide whether a package is cached; a miss triggers the GitHub fallback above |
internal/shellgen/tmpl/flake.nix.tmpl:51: fromStore = "https://cache.nixos.org"; |
builtins.fetchClosure in the generated flake |
internal/lock/resolve.go:185 (nix.StorePathFromHashPart(ctx, sysInfo.StoreHash, "https://cache.nixos.org")) also hard-codes the URL. It's only used by the /v1/resolve path (DEVBOX_FEATURE_RESOLVE_V2=0), which is not the default.
Related: the stdenv nixpkgs input ignores DEVBOX_CACHE
DEVBOX_CACHE rewrites nixpkgs flake inputs for packages to <DEVBOX_CACHE>/nixos/nixpkgs/archive/<rev>.tar.gz (internal/shellgen/nixpkgs.go). The stdenv input is still written verbatim (nixpkgs.url = "{{ .Stdenv }}"; in flake.nix.tmpl:5), so nix print-dev-env downloads https://github.com/NixOS/nixpkgs/archive/<rev>.tar.gz directly. Applying the same mirror logic to the stdenv input would let a locked project work with only the mirror reachable. I can open this as a separate issue if you prefer.
What solution would you like?
Proposal
- Add
DEVBOX_BINARY_CACHE(the name is only a suggestion). It defaults tohttps://cache.nixos.organd is used in all places above. - Alternative: read the first HTTP(S) entry of Nix's
substituterssetting (nix config show substituters), falling back tohttps://cache.nixos.org.
Alternatives you've considered
Workaround
We currently patch the source at build time: substituteInPlace swaps https://cache.nixos.org for our mirror URL, and the stdenv template line is changed to use the mirror. With both patches, devbox install, devbox run and devbox shell work for locked projects with only the mirror reachable. We'd like to drop this patch.
Activity
anunayasri commentedon Oct 27, 2026
Hey @mikeland73 . I would love to give this one a try. Could you assign it to me.
anunayasri commentedon Oct 28, 2026
Hey Team. I want to get consensus on implementation strategy before writing(and testing) the fix.
I understand that
cache.nixos.orgis used in two places. Both needs to point to the new mirror url.internal/devpkg/narinfo_cache.go > fetchNarInfoStatusFromHTTP(ctx, binaryCache, hash)internal/nix/build.go > Build(). Note that the cache url is not an arg here.Config needs to specified in two places -
DEVBOX_NIX_CACHE_URLinternal/nix/build.go > Build()) using--option substitutersnix.conffile.Separation of concerns: The fix is not responsible for updating
nix.conf. Devbox and nix configs must not be coupled. Users might use devbox with an existing nix installation.Out of scope: Support for multiple cache servers.
🛟 I haven't used nix before. Would appreciate if someone can guide me - How to test end to end after the fix—including a reachable mirror, any required authentication, substituter authorization, and signing keys.
cc: @mikeland73, if you have context or could route the query to the relevant eng.
mikeland73 commentedon Nov 2, 2026
Thanks for writing this up! A couple of adjustments:
--option substitutersonnix build. When a package is cached, devbox builds the store path directly, and Nix already uses the substituters andtrusted-public-keysfromnix.conf. Overriding substituters from the client is also ignored for non-trusted users on multi-user installs.substitutersvianix.CurrentConfig()(internal/nix/config.go), falling back tohttps://cache.nixos.org. Then users configure the mirror once, innix.conf.cache.nixos.orgis hardcoded: the narinfo probe (internal/devpkg/narinfo_cache.go),fromStoreininternal/shellgen/tmpl/flake.nix.tmplandinternal/shellgen/flake_plan.go, andinternal/lock/resolve.go.fetchClosuredownloads<fromStore>/nix-cache-infoeven when the path is already local, so it has to be reachable.To test without a real mirror: set
substituters = https://nix-community.cachix.org(any reachable cache other than cache.nixos.org) and blockcache.nixos.org, for example with an/etc/hostsentry.devbox installanddevbox shellon a locked project should then send no requests to cache.nixos.org (check withDEVBOX_DEBUG=1).Written by Claude on behalf of / prompted by @mikeland73.
logan-egbert commentedon Nov 13, 2026
I'm getting the
Error: Head "https://cache.nixos.org/zslkhz79mpnk945p5xhrixqch693b0k1.narinfo": context deadline exceededwhen trying to update my packages globally. Is this fix related to that issue @anunayasri ?anunayasri commentedon Nov 14, 2026
Hey @logan-egbert . If you are working behind a firewall that blocks
cache.nixos.orgor your company uses a nix cache mirror, then yes.