<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel>
        <title>Daniel Duan's Articles About home-manager</title>
        <link>https://duan.ca/tag/home-manager/</link>
        <atom:link href="https://duan.ca/tag/home-manager/feed.xml" rel="self" type="application/rss+xml" />
            <item>
                <title>Flake For Non-Nix Projects</title>
                <description>&#60;p&#62;The ideal outcome of using Nix or home-manager is to have as many things as possible under their control.
Among these things are developer tools for coding. You may need &#60;code&#62;cargo&#60;/code&#62;, and &#60;code&#62;rust-analyzer&#60;/code&#62; for Rust projects;
&#60;code&#62;ipython&#60;/code&#62;, and &#60;code&#62;python-lsp-server&#60;/code&#62; for Python projects, etc.&#60;/p&#62;
&#60;p&#62;Of course, the simplest solution is to have them all installed and configured in home-manager or the OS level.
But, over time, you&#39;ll end up with a ton of stuff.&#60;/p&#62;
&#60;p&#62;Maybe that won&#39;t bother you. Fine, but this approach is at odds with some convention of the Nix community. You
see, there&#39;s this command called &#60;code&#62;nix-shell&#60;/code&#62;, or &#60;code&#62;nix develop&#60;/code&#62;, which sets up a environment with certain
packages, with the expectation that you only need them sometimes, usually within the context of developing
a certain software project.&#60;/p&#62;
&#60;p&#62;So, arguably, a better alternative to installing everything you possibly need is to keep only the essential
tools you always need, regardless of what you are working on. Things like &#60;code&#62;neovim&#60;/code&#62;, &#60;code&#62;git&#60;/code&#62;, &#60;code&#62;ripgrep&#60;/code&#62;, etc.
When a project demands things such as &#60;code&#62;rust-analyzer&#60;/code&#62;, running &#60;code&#62;nix develop&#60;/code&#62; should set it up for you.&#60;/p&#62;
&#60;p&#62;How do we implement that? In a imaginary world where every single software project is built with a flake.nix,
the &#60;code&#62;devShell&#60;/code&#62; property should provide everything the software project owner expect you to need. And you just
&#60;code&#62;cd&#60;/code&#62; into the root of the project, run &#60;code&#62;nix develop&#60;/code&#62;, and you are off to the races.&#60;/p&#62;
&#60;p&#62;Several problems:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;running &#60;code&#62;nix develop&#60;/code&#62; is repetitive, and therefore, annoying.&#60;/li&#62;
&#60;li&#62;the owner of a flake.nix may have drastically different taste for the best dev tools for their project
(bet!).&#60;/li&#62;
&#60;li&#62;we don&#39;t live in a world built with Nix flakes.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;Yikes.&#60;/p&#62;
&#60;p&#62;To solve &#60;code&#62;1&#60;/code&#62;, enter &#60;a href=&#34;https://github.com/nix-community/nix-direnv&#34;&#62;direnv&#60;/a&#62;. It&#39;s a piece of software that let you create a environment for a directory,
and automatically switch to it when you enter said directory. The &#38;quot;environment&#38;quot; could contain envvars, and,
you guessed it: a Nix developer shell. If you have a flake.nix, add &#60;code&#62;use flake&#60;/code&#62; in your project directory&#39;s
&#60;code&#62;.envrc&#60;/code&#62; file, direnv will automatically call &#60;code&#62;nix develop&#60;/code&#62; the next time you &#60;code&#62;cd&#60;/code&#62; in. Neat!&#60;/p&#62;
&#60;p&#62;To make this work in practice, you&#39;ll want to add &#60;code&#62;.envrc&#60;/code&#62; and &#60;code&#62;.direnv/&#60;/code&#62; to your global git ignore list, as
they are personal preferences that probably shouldn&#39;t end up in git history.&#60;/p&#62;
&#60;p&#62;Ok, we are so close to solve problem &#60;code&#62;2&#60;/code&#62;, and &#60;code&#62;3&#60;/code&#62; now. In short, &#60;code&#62;nix develop&#60;/code&#62; may set up &#60;strong&#62;a&#60;/strong&#62; environment,
but it may not be &#60;strong&#62;the&#60;/strong&#62; environment that suits you the best. &#60;a href=&#34;https://github.com/nix-community/nix-direnv&#34;&#62;nix-direnv&#60;/a&#62; extends direnv to save us:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;use flake path/to/flake#target
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;... with this in &#60;code&#62;.envrc&#60;/code&#62;, direnv will set up the Nix environment according to &#60;code&#62;path/to/flake#target&#60;/code&#62;. That
could point to any location on your hard drive! You can have a flake.nix whose &#60;code&#62;devShell&#60;/code&#62; has &#60;code&#62;cargo&#60;/code&#62;, and
&#60;code&#62;rust-analyzer&#60;/code&#62;. You can have another with &#60;code&#62;ipython&#60;/code&#62;, and &#60;code&#62;python-lsp-server&#60;/code&#62;. Mix and match to your liking to
the infinite degree...&#60;/p&#62;
&#60;p&#62;For now, I&#39;ve decided to give nix-direnv a try. Alongside my home-manager configuration, I&#39;ve also included
extra flakes for generic Python/Rust projects, and specific projects that may require a mix of tools. A lot of
the project I work on don&#39;t use flake as their package manager. With this approach, I get to customize my
setup for them each, and stay in the comfort of Nix and home-manager.&#60;/p&#62;
&#60;p&#62;direnv and nix-direnv can be configured together with home-manager. To achieve everything mentioned in this
article, including direnv&#39;s shell integration (Fish, for me), it&#39;s as simple as&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-Nix&#34;&#62;# In home manager config...
programs.direnv = {
  enable = true;
  nix-direnv = {
    enable = true;
    enableFlakes = true;
  };
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;To recap, having the snippet above in my home-manager setup, I now can enter any project&#39;s root directory and
add a &#60;code&#62;.envrc&#60;/code&#62; file with the content &#60;code&#62;use flake ~/src/dotfiles/direnvs/python&#60;/code&#62;.
&#60;code&#62;~/src/dotfiles/direnvs/python&#60;/code&#62; contains a &#60;code&#62;flake.nix&#60;/code&#62; (and a &#60;code&#62;flake.lock&#60;/code&#62;) that has the &#60;code&#62;devShell&#60;/code&#62; value
I like for all Python projects. When I &#60;code&#62;cd&#60;/code&#62; into this project, &#60;code&#62;(nix-)direnv&#60;/code&#62; will read from that &#60;code&#62;devShell&#60;/code&#62;
and set every tool listed under there. The tools are cached in a &#60;code&#62;.direnv&#60;/code&#62; directory so when I return here,
the setup is basically instantaneous. Since I make &#60;code&#62;git&#60;/code&#62; to ignore &#60;code&#62;.envrc&#60;/code&#62;, and &#60;code&#62;.direnv&#60;/code&#62; no matter where
they are, this project I&#39;m working on is unaffected by all this.&#60;/p&#62;
</description>
                <pubDate>Sat, 19 Mar 2022 00:37:01 -0700</pubDate>
                <link>https://duan.ca/2022/03/19/nix-dirnev/</link>
                <guid isPermaLink="true">https://duan.ca/2022/03/19/nix-dirnev/</guid>
            </item>
            <item>
                <title>Flake, Home Manager, and Extra Packages</title>
                <description>&#60;p&#62;So, you use a standalone home-manager, it&#39;s set up with flake, tracking a particular nixpkgs channel. How do
you use a package from another channel? This seemingly simple task took me, a Nix noob, quite a bit of
research to solve. Here&#39;s how I did it.&#60;/p&#62;
&#60;p&#62;A simple flake.nix for home-manager might look like this:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-nix&#34;&#62;{
  inputs = {
    nixpkgs.url = &#38;quot;github:nixos/nixpkgs/nixos-21.11&#38;quot;;
    home-manager.url = &#38;quot;github:nix-community/home-manager/release-21.11&#38;quot;;
    home-manager.inputs.nixpkgs.follows = &#38;quot;nixpkgs&#38;quot;;
  };
  outputs = { self, nixpkgs, home-manager }: {
    &#38;quot;dan@some-mac&#38;quot; = home-manager.lib.homeManagerConfiguration {
      username = &#38;quot;dan&#38;quot;;
      system = &#38;quot;x86_64-darwin&#38;quot;;
      homeDirectory = &#38;quot;/home/dan&#38;quot;;
      configuration = { config, pkgs ... }: {
          home.packages = [
            pkgs.hello
          ];
      };
    };
  };
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;A few things of note:&#60;/p&#62;
&#60;ol&#62;
&#60;li&#62;home manager is set to follow &#60;code&#62;nixpkgs&#60;/code&#62;, which tracks &#60;code&#62;nixos-21.11&#60;/code&#62;.&#60;/li&#62;
&#60;li&#62;&#60;code&#62;pkgs.hello&#60;/code&#62; refers to the package in &#60;code&#62;nixos-21.11&#60;/code&#62; as well.&#60;/li&#62;
&#60;/ol&#62;
&#60;p&#62;To put things in concrete terms, our goal is to put a package from a channel other than &#60;code&#62;nixos-21.11&#60;/code&#62;
alongside &#60;code&#62;pkgs.hello&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;The key to my solution is the &#60;code&#62;extraModules&#60;/code&#62; in &#60;code&#62;home-manager.lib.homeManagerConfiguration&#60;/code&#62;&#39;s argument set.
We&#39;ll leverage it to modify the environment made available to its sibling, &#60;code&#62;configuration&#60;/code&#62;.&#60;/p&#62;
&#60;p&#62;First, add the new channel as input &#60;code&#62;nixpkgs-unstable&#60;/code&#62;:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-nix&#34;&#62;{
  inputs = {
    # ...
    nixpkgs-unstable.url = &#38;quot;github:nixos/nixpkgs&#38;quot;;
  };
  ...
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Then, add a small module to &#60;code&#62;extraModules&#60;/code&#62;. In it we make &#60;code&#62;nixpkgs-unstable&#60;/code&#62; an argument to &#60;code&#62;_module&#60;/code&#62;.&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-nix&#34;&#62;{
  input = { ... };
  outputs = { self, nixpkgs, nixpkgs-unstable, home-manager }: { # Note we also pass in nixpkgs-unstable here
    &#38;quot;dan@some-mac&#38;quot; = home-manager.lib.homeManagerConfiguration {
      extraModules = [
        ({ pkgs, ... }: rec {
          _module.args.nixpkgs-unstable = import nixpkgs-unstable { inherit system; };
        })
      ];
      # ...
    };
  };
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;... now that we added &#60;code&#62;args.nixpkgs-unstable&#60;/code&#62;, it becomes available in the configuration:&#60;/p&#62;
&#60;pre&#62;&#60;code class=&#34;language-nix&#34;&#62;{
  input = { ... };
  outputs = { self, nixpkgs, nixpkgs-unstable, home-manager }: { # Note we also pass in nixpkgs-unstable here
    &#38;quot;dan@some-mac&#38;quot; = home-manager.lib.homeManagerConfiguration {
      # ...
      configuration = { config, pkgs, nixpkgs-unstable, ... }:
          home.packages = [
            pkgs.hello
            nixpkgs-unstable.python39Packages.python-lsp-server
          ];
      };
    };
  };
}
&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;There, we made &#60;code&#62;python39Packages.python-lsp-server&#60;/code&#62; from nixpkgs&#39;s master branch appear alongside our
standard, default channel.&#60;/p&#62;
&#60;p&#62;And that&#39;s how you add packages from a different channel in a flake setup for standalone home-manager.&#60;/p&#62;
</description>
                <pubDate>Tue, 15 Mar 2022 18:53:59 -0700</pubDate>
                <link>https://duan.ca/2022/03/15/standalone-home-manager-flake-channels/</link>
                <guid isPermaLink="true">https://duan.ca/2022/03/15/standalone-home-manager-flake-channels/</guid>
            </item>
    </channel>
</rss>