Need configuration feedback and tips (and question about managing shell scripts)

Hi, I need some feedback and tips for my first config:

I do have plans to make a few modules, for packages, home-manager and credentials - like my real e-mail or ssh keys, but I haven’t been able to find any simple examples, so if anyone has one, please share it.

Currently I chowned /etc/nixos/ to my user and made it a git repo because I want to avoid symlinking configs as much as possible, that’s also why I’m not using a standalone installation of home-manager, I have seen that this can be done better with flakes, but I want to avoid them right now until I understand Nix and NixOS a bit better.

Also, how do you guys deal with shell scripts? On Arch I had them in $HOME/.local/bin which was in my path. Is there a way to have the scrips in a directory in /etc/nixos and make them available to the user with home-manager?

There’s some info in the wiki:

If you don’t want it inline, here’s what I do. Create my-script.nix:

{ stdenv }:

stdenv.mkDerivation rec {
  name = "my-script";
  version = "0.1.0";
  src = ./my-script;
  phases = "installPhase fixupPhase";
  installPhase = ''
    mkdir -p $out/bin
    cp ${src}/ $out/bin/my-script

The src points to a folder that has my script in it.

Then in my configuration.nix:

  nixpkgs.overlays = [
      self: super: {
        my-script = pkgs.callPackage ./my-script.nix { };

As far as how you get those files into place, I’m sure there are better ways to do it (and hopefully someone chimes in), but I just have a ZSH alias that copies the necessary files from my Git repo into /etc/nixos. :man_shrugging:

Here’s an example of how I do it. (With my own library functions templateScriptBin and readTemplate) But you don’t need to do anything that fancy. If you don’t want to include any package paths into the script like I’m doing, you can just put a (pkgs.writeScriptBin "cmdname" (builtins.readfile ./file)) into your home.packages list. The cleanest solution that doesn’t need much nix programming is probably to write the script inline as a '' string and pass it to pkgs.writeScriptBin. You can still use nix antiquotes to reference packages that way, but your editor won’t have useful highlighting for the shell script.

Also, general commentary: I tend to prefer using home-manager.useUserPackages = true; because it allows the home-manager setup to activate properly inside a nixos-rebuild build-vm, and also because I just avoid nix-env like the plague.

resholve can ~generally meet the need of doing this without having to inline it all (i.e., retain editor highlighting, ability to run the script outside of a Nix-managed system, etc.–at least if you aren’t building the script conditionally based on the Nix eval). Here’s an example from @utdemir dotfiles/default.nix at 212a19b4e822d079bb021bc7f09c656c2896b9be · utdemir/dotfiles · GitHub


Thanks! I was hoping that it would be something simple like this.

If I understand it correctly, home-manager.useUserPackages affects the installation path of packages installed with home.packages right? I do not use nixos-rebuild build-vm or plan on using home.packages to install anything other than my shell scripts, should I care about it?

If you don’t plan on using nix-env (or nix profile) directly, there’s not much difference. If you do use nix-env directly, note that rolling back your profile will also rollback home-manager’s generation directory without actually running the activation script. Could get you some oddities.

If you wanted to use the new nix profile commands, the profile used would also be incompatible with home-manager, forcing use of home-manager.useUserPackages = true;

Got it, thanks for the explanation!

@tejing @broccoli I didn’t unpack this very well last night, but resholve can help leave the source files intact by taking something like:

  cowsay -n < <(command neofetch --stdout)

and rewriting it (at build time) to something like:

# !/nix/store/bh237kq8sdsgp8l7m9c846fc9klpi4jn-bash-5.1-p4/bin/sh
  /nix/store/f7yvzpilpymw8356xm477fz35kmrkhhr-cowsay-3.03+dfsg2/bin/cowsay -n < <(command /nix/store/rbvydki2qkfp4v0qxs0nqiniqwh3cxwq-neofetch-7.1.0/bin/neofetch --stdout)

### resholve directives (auto-generated) ## format_version: 2
# resholve: keep /nix/store/f7yvzpilpymw8356xm477fz35kmrkhhr-cowsay-3.03+dfsg2/bin/cowsay
# resholve: keep /nix/store/rbvydki2qkfp4v0qxs0nqiniqwh3cxwq-neofetch-7.1.0/bin/neofetch

The examples above are from a blog post on writing a simple shell package, so they focus on the full resholvePackage function. The link I shared before from @utdemir’s dotfiles illustrates how to use the resholveScriptBin function instead, but the basic concepts are the same.