1. 73
  1. 10

    Thanks for another great post! Just wanted to mention that most folks probably don’t wan to use nix-env, since it is a form of imperative package management. It’s sometimes nice to quickly test out some package (if nix run or nix-shell don’t suffice), but in the spirit of NixOS’ declarative configuration, the better options are:

    • Define global packages in environment.systemPackages in configuration.nix.
    • Define user-specific packages in users.users.<name?>.packages.
    • Use home-manager, which doesn’t only allow you to specify the packages in your user profile declaratively, but to specify the configuration of many programs declaratively (similar to configuration.nix). See the extensive list of configuration options, which ranges from Emacs to isync.
    • home-manager can be used separately from the system’s NixOS configuration, so you run home-manager switch to update the user profile. However, you can also integrate home-manager configurations into the NixOS configuration, so that if you run nixos-rebuild it will also rebuild home-manager configurations.

    The really awesome thing about home-manager is that you can also use it on other distributions and macOS. So, you can even your fully declarative home environment outside NixOS (e.g. I use it to have the same environment on work server).

    1. 9

      I use nix-env in a declarative way:

      nix-env -rif packages.nix

      Which means “remove everything and install everything from this file” - works great.

      1. 2

        Fair enough! But I was referring to the installation of separate packages using nix-env -i as described in the blog post, which is the closest to imperative package management. Once you start describing your environments in a Nix file and produce it from that, it becomes declarative.

        This thread is a nice discussion of various ways to manager user environments declaratively:


      2. 8

        Christine, in case you are reading this… From the emacs configuration:

        pkgs.writeTextFile {
              name = "cadey-emacs.desktop";

        There is also a handy makeDesktopItem, which validates the file as well:


        E.g. from one of my derivations:

        makeDesktopItem {
            name = "softmaker-office-planmaker";
            desktopName = "SoftMaker Office PlanMaker";
            icon = "softmaker-office-pml";
            categories = "Office;";
            exec = "softmaker-office-planmaker %F";
            mimeType = "application/x-pmd;application/x-pmdx;application/x-pmv;application/excel;application/x-excel;application/x-ms-excel;application/x-msexcel;application/x-sylk;application/x-xls;application/xls;application/vnd.ms-excel;application/vnd.stardivision.calc;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.spreadsheetml.template;application/vnd.ms-excel.sheet.macroenabled.12;application/vnd.ms-excel.template.macroEnabled.12;application/x-dif;text/spreadsheet;text/csv;application/x-prn;application/vnd.ms-excel.sheet.binary.macroenabled.12;";
            extraEntries = ''
        1. 4

          TIL! I’ll probably change my stuff to use that, but my current dwm setup doesn’t use .desktop entries.

        2. 3

          I’m new to NixOS and didn’t know about home-manager, thanks! Do you think there’s a benefit of migrating my current dotfiles setup (a Git repository and stow) to it?

          1. 4

            Besides what @chrispickard said, using home-manager to manage dotfiles has the nice benefit that you can use the full Nix language to create configurations. Besides being able to factor out boring and repetitive stuff using Nix functions (and home-manager already provides a lot of functionality to generate cruft for you), you can also directly reference packages or files in packages.

            Just a random example from my e-mail configuration, where I use pass as the password command.

            passwordCommand = "${pkgs.pass}/bin/pass Mail/magnolia";

            In the generated configuration, this will have the full path to the pass command. No need to rely on the command to be available in the user-global PATH or directly through my user profile.

            1. 2

              I hadn’t thought about that kind of use case. Thanks to you both!

            2. 2

              I migrated most of my own dotfiles to home manager from stow and it’s honestly so much nicer. I always had issues with stow not wanting to overwrite files and it was difficult to stow anything that needed to end up in .config

          2. 2

            Have any of you successfully set up something that enables PXE boot with persistent NFS storage? I have a gaming rig with Windows installed and occupying the hard drives with games, etc. I’d like to boot Linux on the metal every now and then without necessarily using any of the connected hard drive space. I have PXE set up on my home network (using https://netboot.xyz for the most part), so booting a live distro is stupid easy. Persisting that, not so much.

            I’d love something that I can set up that pulls down a base image, installs additional packages listed in a configuration file (e.g. packages in a nix config) downloaded from a local proxy, and then mounts my home directory over NFS. I feel like this could give me a productive environment that’s not my aging Macbook Pro with lots of distractions on it without me needing to purchase more hard drives for the Windows machine and maintain an always-rickety dual bootloader config.

            1. 1

              Did you see the wiki page about how to build a netboot image? https://nixos.wiki/wiki/Netboot

              I don’t know if you can “[pull] down a base image, [install] additional packages” while booting the pxe image but I guess you can build the image with everything you need (including the nfs mount probably). Maybe check https://nixos.wiki/wiki/NFS

              Now that pixiecore is included in nixpkgs-unstable we can simply use the following to have a working pxe server serving https://netboot.xyz:

              services.pixiecore = {
                enable = true;
                openFirewall = true;
                kernel = "https://boot.netboot.xyz/ipxe/netboot.xyz.lkrn";

              To serve a NixOS image (thanks to mic92):

              services.pixiecore = let
                nixos = import <nixpkgs/nixos> {
                  configuration = { config, pkgs, lib, ... }: with lib; {
                    imports = [
                    # Some useful options for setting up a new system
                    services.mingetty.autologinUser = mkForce "root";
                    # Enable sshd which gets disabled by netboot-minimal.nix
                    systemd.services.sshd.wantedBy = mkOverride 0 [ "multi-user.target" ];
                    # users.users.root.openssh.authorizedKeys.keys = [ ... ];
                    # i18n.consoleKeyMap = "de";
                build = nixos.config.system.build;
              in {
                enable = true;
                openFirewall = true;
                kernel = "${build.kernel}/bzImage";
                initrd = "${toString build.netbootRamdisk}/initrd";
                cmdLine = "init=${build.netbootIpxeScript} ${lib.concatStringsSep " " nixos.config.boot.kernelParams} debug";
                dhcpNoBind = true;
            2. 1

              I love blogposts like this about NixOS, it’s always an incentive to pick it up again. I also didn’t know Nix could create lxc containers. I don’t really see an explanation on how this works, unfortunately. I’d like it if I could run a lxc container on my existing ubuntu install. Now whenever I want to experiment with it, I use a Virtualbox machine but it’s just not very handy. If I could create lxc containers and provision them, that would make things a lot easier.

              Maybe I’ll give it another go next weekend…

              1. 5

                Take a look at https://github.com/nix-community/nixos-generators, it’s how I make simple isos and other virtual machine images.

                1. 1

                  Thanks, that’s very helpful. It’s definitely on the list now!

              2. 1

                Sorry to keep asking but, what’s the Nix way to keep system configuration separate from user configuration.

                For example, if I install the nginx package and then uninstall it on Ubuntu, lots of configuration files just linger and can’t be removed. Likewise, if I do some user configuration for nginx, where is that suppose to live so if I uninstall nginx in Nix all the system configuration files go but my user configuration isn’t lost?

                Is the Nix-way that I make a Nix package for my nginx configuration that depends on the nginx package? This feels fairly tedious if I have to do so for every package.

                1. 2

                  Is the Nix-way that I make a Nix package for my nginx configuration that depends on the nginx package? This feels fairly tedious if I have to do so for every package.

                  No, you configure nginx in your configuration.nix (or some file that you import from there). E.g. by adding something like:

                    services.nginx = {
                      enable = true;
                      virtualHosts = {
                        "foo.bar.eu" = {
                          serverName = "foo.bar.eu";
                          root = "/storage/www/foo.bar.eu";

                  And running nixos-rebuild switch. If you want to remove the nginx configuration, remove those lines and run nixos-rebuild switch again. After that, the nginx configuration will not be visible in /etc anymore.

                  The way it works is that when you run nixos-rebuild, a /nix store path will be created with your system configuration (at a superficial level you could see it as just another package). Most paths in the root filesystem are just symlinks into this store path. In fact, you can remove most of the / filesystem during boot and NixOS will be fine. This is also why you can roll-back to older versions of the system, they are just different paths in the Nix store. When you switch to an older generation, the symlinks in / are just updated to point to this generation.

                  1. 2

                    I was looking at configuration.nix and other such files of the author and worried I was signing myself up to edit a lot of nix files. As a followup, does this mean in practice I have to port all my config files across different services to whatever format nix likes for my package?

                    1. 3

                      Yes. Though for many programs/services there is an extraConfig option which takes a string that will be added as-is to the configuration. So, in many cases, you can take your existing configuration file and use the readFile build-in to read an existing configuration file. This is what I initially did for some applications and slowly migrated things over.

                      1. 2

                        You can also manage “regular” files via Nix. So partially you will need to migrate to Nix, but not everything will be needed to be written in Nix as you can always just use regular text files, just these will be put in place via Nix instead of manually editing /etc or whatever directory these go.

                  2. 1

                    Thanks for another article!

                    Any reason why’d I get a cp: cannot stat error on the first example? I’m baffled. I’m using Markhor if that matters. Also, a NixOS novice.

                    1. 1

                      clone https://github.com/Xe/gruvbox-css locally and run the command in there

                      1. 1

                        Whoops, feel like a bonehead - thanks

                    2. 0

                      I might give NixOs a try but now after using manjaro with i3 i feel like configuring things is too much work. I would prefer something readymade out of the box such as ubuntu or fedora.