How to setup a pure environment offline

I’ve been trying for some time to setup a workflow for creating pure (in the sense of having all the required tools provided by an isolated flake) environment for new projects. That is, so far, when I wanted to create a new project, I just created a new directory with git and everything, and just installed globally the required tools (although, most of the time, they are already installed), mainly including the compiler(s) and Make (or equivalents). Then, as the project grows, I start “converting” it to a more nix-maintained project, that is, I add a flake, with all the dependencies, a dev shell, and, in the end, I can simply enter the shell and I’m ready to go to develop.

Now, I’d like to automate this process to start right away with a flake based structure, and the appropriate dev shell, so that I don’t have to install anything globally: every project has its own tool dependencies, including versions and specific configuration (for the linter, for instance). To do so, I’ve basically wrapped the templating system of nix in a bash script to enhance it a little: now, every instance of the text !NAME! in certain files is replaced with the actual project of the name, or similar features. This works well, I just have to run inst rust my-project to create a my-project-named project with the appropriate rust toolchain, direnv integration, etc. .

There are two issues though:

  1. This requires an internet connection, both to fetch the actual template (that I’ve stored in a git repo somewhere), to init the flake (that is, to create the flake.lock) and to download everything needed (the rust toolchain, …).
  2. This is slow and redundant, because instead of always using the same version of nixpkgs, and thus fetching everything that is needed only once, it will actually create the flake.lock at the moment of the installation, seeing that there is a newer nixpkgs input version (or any other input) and so it won’t reuse what’s in the store. I update my system about once per week (or once per month if I’m being lazy), but some of the inputs I use are updated daily, sometimes even several times in one day!

I could just bundle the flake.lock with the templates, however that would be a burden because I’d have to update every template I have regularly enough (ideally, whenever I update the flake of my system, so that I really use the same store entry over and over again). This could be scripted, and that’s probably the solution I’ll dive into if nothing else comes up. But this only solves 2.

So, I was wondering if the following workflow was possible:

  • My bash script also brings the required templates as a dependency, so that when I install it, I don’t have to fetch templates over the internet. (NB. I do have a local copy of the template repo on my computer, otherwise I couldn’t even edit them, however this is not the case on every computer I use, and it doesn’t feel very elegant to use the dev repo as the production dependency).
  • The templates (which are all valid flakes) bring as dependencies the actual dependencies of the flake (both the dev shell and the packaging dependencies), so that when I init a new project, everything is already present in the store.
  • All that can be updated alongside my system, that is, when I update my system(‘s flake), it will also update the templates’ flake.
  • Creating a new project and the actual development must be possible offline (as far as I don’t need dependencies that where not included in the flake).

I know that my bash script’s flake could also provide template outputs, however this is not what I am looking for; doing so would only produce available templates for others to consume, to actually “installing” them somewhere in the store.

If you have a suggestion about a different workflow (may it be slightly different or completely different) that allows me to fulfill my objective (that is, creating working environments offline), I am fully open to these too.