Dynamic flake input url source section switching

Hi,
I need some ideas how to quick cycle the complete flake input url section at build-time.
Are there any cools solutions already out there?

Depending on location and connectivy I need different git (replicated) flake input source urls:

  • corp: “git+https://git-mirror.my.corp/nixpkgs”
  • home: “git+https://git-mirror.home.lan/nixpkgs”
  • road (offline): “git+file:///nix/persist/cache/git-mirror/nixpkgs”
  • hash verification (online): “github:nixpkgs/nixos”
  • […]

manual mode:

{
  description = "nixos infra global config flake";
  inputs = {
    ### github
    # nixpkgs.url      = "github:nixos/nixpkgs?ref=nixos-unstable";
    # agenix.url       = "github:ryantm/agenix?ref=main";
    # disko.url        = "github:nix-community/disko?ref=master";
    # home-manager.url = "github:nix-community/home-manager?ref=master";
    ### git-mirror
    nixpkgs.url      = "git+https://git-mirror.home.corp/nixos/nixpkgs?ref=nixos-unstable";
    agenix.url       = "git+https://git-mirror.home.corp/ryantm/agenix?ref=main";
    disko.url        = "git+https://git-mirror.home.corp/nix-community/disko?ref=master";
    home-manager.url = "git+https://git-mirror.home.corp/nix-community/home-manager?ref=master";
    ### git-files
    # nixpkgs.url = "git+file:///nix/persist/cache/git-mirror/nixos/nixpkgs?ref=nixos-unstable";
    # agenix.url = "git+file:///nix/persist/cache/git-mirror/ryantm/agenix?ref=main";
    # disko.url = "git+file:///nix/persist/cache/git-mirror/nix-community/disko?ref=master";
    # home-manager.url = "git+file:///nix/persist/cache/git-mirror/nix-community/home-manager?ref=master";
    ### shared
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
  };
  outputs = {
    self,
    agenix,
    disko,
    home-manager,
    nixpkgs,
  }: {
    nixosConfigurations = {...};
};

Something like … but clean code, cool and actually working.

{
  description = "nixos infra global config flake";
  sources = {
    prefix = sources.git-mirror;
    github = "github:";
    git-mirror = "git+https://git-mirror.home.corp/";
    git-files = "git+file:///nix/persist/cache/git-mirror/";
    repos = {
      agenix.url = "${sources.prefix}ryan/agenix.git?ref=main";
      disko.url = "${sources.prefix}nix-community/disko.git?ref=master";
      nixpkgs.url = "${sources.prefix}nixos/nixpkgs.git?ref=nixos-unstable";
      home-manager.url = "${sources.prefix}nix-community/home-manager.git?ref=master";
      home-manager.inputs.nixpkgs.follows = "nixpkgs";
    };
  };
  inputs = sources.repos;
  outputs = {
    self,
    agenix,
    disko,
    home-manager,
    nixpkgs,
  }: {
    nixosConfigurations = {};
};

Any Ideas are welcome.

Flake inputs have to be statically and literally be known at file read time. There is no way to build them dynamically or change them.“after the fact”.

Yes, thats clear. No intention to use something like impure mode.
The idea is to have one simple (fixed) attribute to quickly switch the complete section at build time.

I didn’t say anything about “impure”, I said, “you can’t change inputs at any time”.

If you still want to do that, use the toggle comment feature of your editor.

Which again will cause constant churn on your lockfile

Have you played around with --override-input and -–inputs-from?

This will still lead to different lock files due to different URLs.

1 Like

Maybe flake-file can be of help, give it a go, the following will create your flake.nix (since flake.nix is static Nix subset):

mv flake.nix flake-file.nix # <- your current flake but now you can use interpolations at inputs, etc.
nix-shell https://github.com/vic/flake-file/archive/main.zip -A flake-file.sh --run bootstrap

See With a traditional flake | flake-file

Have you considered using DNS to change the hosts? If the contents are the same, the lockfile won’t differ. You could even use a local proxy webserver to terminate TLS.

If you’re not ok with that, flakes and input pinning aren’t what you want.

I think a mirroring feature would be very nice, but alas, nix doesn’t have one - as I’ve argued before, probably because there’s commercial interest in it and at least one vendor has managed to capture that with a proprietary service.

If this is about mirror handling, I learned about nixtamal when listening back to my pod casts.

I have not looked deeply into it, though it seems to be a mirror aware source pinning tool. Maybe you can integrate that into your setup?

flake-compatish supports overriding inputs using Nix expressions so you can achieve essentially whatever you want while still being flake compatible for external users (they won’t get your overrides unless they also use flake-compatish ofc)

Thanks for all the input!

Seems there are a lot ways around - but no real clean nix core support.

Having a single dependency to exactly one [microsoft|azure|github] repo beeing live and reachable exactly at your build/reconfig time may become a issue!? A git clone is easy and cheap to host everywhere. Git Tree SHA1/SHA256 and Commit/Tag ed25519 signatures will ensure content correctness.

I will go now the local (fake-) dns and reverse-proxy route and let the caddy reverse proxy upstream backend health logic figure out the current enviroment.

Not perfect for resource constrained desktops or mobile devices - but will do the job.

Having git > 2.49 already in nix core, the modification for flakes to mange resource saving local git partial bare clones of the upstream repos instead of a full new complete checkout in store everytime only a single bit changes should be possible?

Does Nix read your Git config files? If it does, you can add insteadOf rules to your Git config and change them depending on the connection. That might be simpler that running a proxy.