Having read all the material I could find on the topic of flakes, I find that I cannot discern (in a reasonable amount of time) between what is essential to the functioning of some flake-based solution and what is over-engineering or irrelevant to my needs or one person’s vision of how something might be implemented or …
Many of the examples I have found, seem to attempt to provide complete personal-devops solutions. While this is, undoubtedly, a very valuable and compelling use-case, I don’t think it helps at all in trying to persuade Joe User that Nix is something relevant and immediately valuable. I’m after gateway drugs into Nix, ones that are affordable for those who have not yet fully bought into Nix, and even those who have never heard of Nix before.
In this context I would like to solicit your help in coming up with some self-contained flake-based solutions to a couple of relatively simple problems of limited scope, the hope being that these might
-
give me some insight into the essential elements of flake-based solutions and a foundation on which I will be able to build more complex structures of my own;
-
be shown to non-Nix-users as tractable recipes that they can realistically apply in their own environments, rather than complex horror stories that will make them run screaming away from Nix.
I also suspect that there are others in an a similar situation to mine, who fall in the gap between the very sparse flakes documentation, and the overly complex examples one can find on GitHub and elsewhere; who might also benefit from seeing simpler, more focused solutions.
Problem 1: Developer and user environments for a software project
I am used to writing a shell.nix
which declares all the dependencies required to build my project, and using this with direnv
to automatically enable (complete, self-contained, isolated) development environments for a bazillion different projects that I’m working on.
I am aware that, with some fiddling, one can write a derivation.nix
suitable for inclusion in nixpgks
, which can be used from the shell.nix
What is the simplest flake-based structure which needs to be built around a nixpkgs
-compatible derivation.nix
, that would make
nix run
nix develop
nix shell
nix build
nix flake check
work sensibly?
Prerequisites
- Nix >= 2.4(?) is enabled in the user’s environment
Problem 2: Bootstrapping home-manager
Home manager is wonderful. It brings the benefits of declarative, reproducible and portable configurations to managing personal environments. I want to give my colleagues the gift of home-manager.
[Aside: It irks me that most introductory Nix material encourages the use of nix-env -i
. Yes, it’s is much better than apt
, yum
, pacman
, etc. in many ways, but it fails to take advantage of some of the greatest benefits of Nix by being imperative rather than declarative: it misses the point!]
To this end I want it to be possible to say
nix --experimental-features = 'nix-command flakes' run github:username/my-config-files
with the following prerequisites and results.
Prerequisites
- Nix >= 2.4(?) is installed on the machine
- Somehow
nix
must have been enabled in the user’s account. Not sure what this would look like for a user who has never used Nix before, on a non-NixOS machine with a pre-existing multi-user install.
Results
- A clone of
github:username/my-config-files
is present in the home directory of the user who ran the command. -
home-manager
has activated the environment declared inmy-config-files
. -
home-manager switch
works, using the environment declared inmy-config-files
. - The new nix CLI should work for this user without the need of
--experimental-features = 'nix-command flakes'
.
Hopes
This single command gives someone who is new to Nix
- a working home-manager installation.
- a simple route for reusing this environment on different machines, by making a personal clone of
my-config-files
.
I hope that the bang-for-the-buck ratio will be a compelling reason to start using Nix.
Problems
Enabling flakes on NixOS vs non-NixOS seems to require completely different mechanisms. Can a one-fits-all solution be provided?
More generally speaking, I’m experiencing problems and inconsistencies with getting flakes to work reliably: e.g.:
vagrant@debian10:~$ nix --experimental-features 'nix-command flakes' flake new flake-new
warning: ignoring the user-specified setting 'experimental-features', because it is a restricted setting and you are not a trusted user
… but now I see that, in spite of the warning to the contrary, the command appears to succeed. [This spurious warning has wasted at least 30 minutes of my life today, and probably a lot more in the past: I recall banging my head against it on other occasions, but only now realize that it is spurious!]
Obvious enhancements
If the environment is to be reusable, it should be easily adaptable to different types of machines: personal laptop, development machine, production machine, etc. Therefore it would be useful to split the environment declaration into composable components which describe what is needed in different roles.
Start simple
While modularisation is valuable, I think that the initial example needs to be simple and un-overwhelming, so I’d like to start of with something as simple as:
{ config
, pkgs
, ... }:
let
link = config.lib.file.mkOutOfStoreSymlink;
in
{
home.file.".something-read-only" .source = ../something-read-only;
home.file.".something-read-write".source = link ../something-read-write; # Note 1
home.packages = with pkgs;
[
home-manager # Note 2
cowsay
];
# Note 3
programs.direnv.enable = true;
programs.direnv.enableNixDirenvIntegration = true;
}
Notes
-
Having to re-run (the all-too-often excruciatingly slow
home-manager switch
) on every experimental tweak of some utility’s configuration file, is hugely painful. I consider the ability to get immediate feedback on config file changes to be crucial. Thislink
alias formkOutOfStoreSymlink
allows for easy switching into ‘experimental mode’ and thus makes the experience tolerable. -
In my (horrible, convoluted)
nix-shell
-based approach to bootstrapping home-manager, I had home-manager install itself. Maybe this isn’t the best way to go. -
direnv
+nix-shell
/nix develop
is a killer feature!