The dream
The dream of modifying your local machine configuration based on whatever it is
that you are doing is here. No matter if you are changing the Linux Kernel or
just writing a small reminder document, nix has got you covered. The only thing
you need to do is nix develop ENV_NAME and you are ready to go.
Flake first
I will not give a master class on what flakes are and how to use them; because I do not know yet :). But what I will do is to give an explanation on how I am using them to orchestrate the going in and coming out of specific shell environments. Let me try to explain it through specific dummy example
{
# Be sure to have some string that describes your flake
description = "dummy flake";
# This is where you define all the dependencies
inputs = {
# Bring in the packages from nix official source
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
# Also bring in some special personal dependencies of your own
dep0.url = "github:GithubUser/nix_envs?dir=dep0";
};
# This is where you define what the flake will provide
outputs = { self, nixpkgs, dep0, ... }:
let
# Be sure to define it for your system architecture
pkgs = import nixpkgs { system = "x86_64-linux"; };
system = "x86_64-linux";
in {
# This is where you tell it to what you want available in your
# development shell
devShells.${system}.default = pkgs.mkShell {
# Include a list of packages from both nixos and your own dep0
packages = with pkgs [ git ]
++ dep0.devShells.${system}.default.shellPkgs ;
# Execute any special commands. You can even use the dep0 ones
shellHook = '' echo "Entering dummy environment" ''
+ dep0.devShells.${system}.default.shellHook
;
};
};
}
Dependencies
The URL lines in the inputs section point to a source; they don’t necessarily
need to be from github. You have everything that is provided by these
“packages” available in your flake. Two things to note:
1. A flake.nix file is expected to reside on the root path of the pointed
repository.
2. You can point to a directory within the repo (instead of just the root)
with the “?dir=/PATH” suffix.
Shell Environment
I use devShells to do two things
1. Define a set of packages that are available when I enter the environment
2. Define a set of actions that are run when I enter the environment
Worth noting here is that you can actually use elements from the “packages” that
you have in the input section.
Public is best
When you are using github repositories it has only worked for me when they are public.
Run Flake
You usually put your dummy flake.nix under a directory; let us say it is under
“dummy”. Then, to run the flake, you simply do nix develop /path/to/dummy.
Then you packages will be available and your shell script defined in the hook
will be run. Your environment is now personalized!!! And to get out of it, you
simply do an exit and you are back to your base system.
Register Flake
Typing nix develop /PATH/TO/dummy might be a bit too much. Especially when you
want to quickly go in and out of these environments. So I do two things:
1. Use an alias -> "alias nd=“nix develop”
2. Register the flake environments locally. Which requires you to copy a
list of all your beautiful flakes in the form of a registry template [1]
into ~/.config/nix/registry.json.
Self-referencing Nix Env Repo
I like to keep things in one place, so I added everything to one repository [2] and use different directories for different environments. I reference these with the “?dir=PATH” trick.
A word on Locking
A flake.lock file gets generated when I run nix develop. This has the -very
enjoyable- consequence of locking the “version”; its more like a git reference
hash. Which means that no matter how much I change [2], I will always have the
same version of my environment (until I regenerate my register file).
Conclusion
In conclusion, leveraging Nix flakes to manage development environments offers a
powerful and flexible approach to configuring your environments. By structuring
dependencies, defining shell environments, and utilizing registry files, you can
seamlessly switch between customized environments with minimal effort. Whether
you’re modifying the Linux kernel or working on small projects, Nix provides a
consistent and reproducible environment, ensuring that your development process
remains efficient and reliable.
[1] https://raw.githubusercontent.com/Joelgranados/nix_envs/refs/heads/master/registry.tmpl [2] https://github.com/Joelgranados/nix_envs
