Support for transparently substituting git mirrors (mapping between URLs pointing to the same git resource) #444
Labels
No labels
Area/build-packaging
Area/cli
Area/evaluator
Area/fetching
Area/flakes
Area/language
Area/profiles
Area/protocol
Area/releng
Area/remote-builds
Area/repl
Area/store
bug
crash 💥
Cross Compilation
devx
docs
Downstream Dependents
E/easy
E/hard
E/help wanted
E/reproducible
E/requires rearchitecture
imported
Needs Langver
OS/Linux
OS/macOS
performance
regression
release-blocker
RFD
stability
Status
blocked
Status
invalid
Status
postponed
Status
wontfix
testing
testing/flakey
ux
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lix-project/lix#444
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Is your feature request related to a problem? Please describe.
Behind networks with slow internet access, or IP addresses that would be flagged/throttled by services like GitHub, downloading updates for
nixpkgs
and other repos can be surprisingly slow. It's also unfortunate that so much Nix infrastructure relies on unfree services like Github.Describe the solution you'd like
The ability to transparently substitute a git repo, such that it's fetching from a local repo instead. It is possible, in principle, to replace the flake inputs for everything, but the
inputs
of thoseinputs
then seem to still rely on GitHub if upstream is using GitHub.The idea here would be, e.g., if upstream is using
github:NixOS/nixpkgs/326341
, it could be transparently substituted withgit.myserver.com/mirrors/nixpkgs?ref=326341
. Any locked input would behave the same, fetching the same exact hash.Describe alternatives you've considered
I'm currently just forking repos and hard-changing their inputs. There are also mechanisms that can imperatively override inputs such as --override-input flag, but they don't work recursively, and they only map a given input name to the URL, instead of one URL to another URL. The problem with this is that it cannot work recursively, as input names are not constrained and the same resource might be called something else depending on which flake you're working with.
Additional context
Have you tried flake registry abuses? If I understand correctly, although the registry add command now blocks this on
main
, I believe you can make a registry entry forgithub:nixos/nixpkgs/nixos-unstable
. However this doesn't entirely help because I think you'd have to re-lock the inputs or something.Even not accounting for locking issues, some repos have commit-specific stuff in their flake inputs. For example, flake-parts. So I would need an entire extra bit of infrastructure just to track their inputs and adjust my "registry abuse" mapping to get it to pull from the local repo instead.
What's needed to have an actually robust 'sources substitution mechanism', is to have some way of mapping the git repo root e.g.
https://github.com/NixOS/nixpkgs/
->https://git.myserver.com/mirrors/nixpkgs/
. Protocol-specific mappings seem entirely desirable, since different protocols may impose different requirements (e.g., port overrides).This means e.g.
https://github.com/NixOS/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz
transparently becomeshttps://git.myserver.com/mirrors/nixpkgs/archive/5daf0514482af3f97abaefc78a6606365c9108e2.tar.gz
. (I tested this transform, and it works perfectly with a forgejo backend as long as the mirror is sufficiently up-to-date). Or, e.g., you could mapgit+ssh://git.someserver.com/myuser/nixrepo
togit+ssh://some-other-server.com:2222/othernixrepo
. Anything after the fact, e.g., pinning?ref=*
should be kept identical for reproducible results (lest we accidentally substitute one commit with another).I think the ideal solution to this, if implemented, should allow:
A failover mechanism (substituting one git repo source with another) would be excellent too, for robustness (i.e., if
git.server1.com
breaks -- it triesgit.server2.com
) but not strictly necessary.Side notes:
It would be best to resolve the flake registry entry first, and then do the transparent mapping. E.g., a flake like
nixpkgs/nixos-24.05
input would resolve togithub:NixOS/nixpkgs/nixos-24.05
, which then resolves tohttps://github.com/NixOS/nixpkgs/nixos-24.05
, which is then mapped tohttps://git.myserver.com/mirrors/nixpkgs/nixos-24.05
.IDK if anyone would actually want to work on this, but I thought it would be nice to put the idea out there, as I was already frustrated with how much NixOS architecture is entangled with GitHub, on account of upstream development being done there -- and I thought some other people might feel the same way. :)
This throttling issue happens regularly for me in Asia, but why transparent? Why not extend Flake
input.url = string
toinput.urls = string list
& users supply their mirrors explicitly? The precedence would be the fetchers likefetchzip
that take aurl
orurls
which allow multiple mirrors (not sure if it is a race or how the resolution is done, but it does work). This would also then be more generic than Git. I rely on tarballs for my inputs a lot since I like using Darcs & Pijul which are not supported as Flake inputs (unlikefetch*
from Nixpkgs), but you can get a tarball archive.@toastal
Transparent because if it's not transparent and global, the user does not control which mirrors are used -- upstream flakes do. You can in principle fork a flake if where it fetches from is a problem, but a flake dependency of a flake dependency of a flake dependency? What if
flake-parts
does not feel like adding the particular mirror that you need? What if you're working on a corporate or personal intranet and are setting up your own mirror? By making it transparently substitute inputs, the user can actually control where the resources are fetched from in niche cases, without sacrificing reproducibility, and without putting the onus on upstream (which may or may not cooperate with various use cases).That makes sense & it means my request is different.