Install Nix

  1. Install Nix (Single-user installation)

    sh <(curl -L https://nixos.org/nix/install) --no-daemon
    
  2. Enable flakes

  3. Set show-trace = true (doc) to see more complete error messages.

Community

Nix messages

Sometimes, when you enter a devshell (e.g., nix develop) or run a default package of a flake, you may see:

  • warnings - not a problem, just read them and google if you're interested;
  • errors - the same story;
  • prompts - answer y (the simplest way).

direnv

This is a tool for running scripts when you cd to a directory containing a .envrc file. direnv automatically builds, caches, and starts a devshell when you enter a flake directory containing the .envrc file (e.g., the root directory of this repository). See Direnv integration.

  1. Install direnv - src

    1. Install the binary

      nix profile install nixpkgs#direnv
      
    2. Hook into your devshell

  2. Allow direnv to work in a directory.

    direnv allow
    

    When you see direnv errors, run the suggested commands.

Further reading

See Nix prerequisites.

Nix Prerequisites

Install Nix

  • Complete all steps from here

Community

Resources

References

I added bookmarks for search engines in my browser, like described here.

Docs

Nix repl

Docs are usually left as comments in Nix code. You can find an attribute in nix-repl and look up its comments in a file at a given position.

nix repl
nix-repl> :lf nixpkgs
nix-repl> legacyPackages.x86_64-linux.lib.lists.singleton
«lambda @ /nix/store/24akvz6idhp4lxxvhbfxxq84py30v6bw-source/lib/lists.nix:23:15»

Sometimes, you may evaluate a description or a longDescription of a derivation:

nix-repl> legacyPackages.x86_64-linux.coreutils.meta.longDescription
"The GNU Core Utilities are the basic file, shell and text manipulation\nutilities of the GNU operating system. These are the core utilities which\nare expected to exist on every operating system.\n"

nix commands

Learn about a command:

nix help command

Search for a package description:

nix edit nixpkgs#coreutils

Flake templates

List templates

If a flake.nix contains a valid output templates, these templates can be listed. List flake outputs and search for templates in this (flakes) repository:

nix flake show | grep template
└───templates
evaluating ''    ├───codium-generic: template: `VSCodium` with extensions and executables
    ├───codium-haskell: template: `VSCodium` with extensions and executables for `Haskell`. Shows 5 ways to run a `Haskell` app.
evaluating ''    ├───codium-haskell-simple: template: `VSCodium` with extensions and executables for `Haskell`.
evaluating ''    ├───codium-python: template: `VSCodium` with extensions and executables for `Python`.
    └───haskell-minimal: template: Minimal flake for a `Haskell` package development.

Use a template

Two ways of copying from templates:

Update a cached template

If you notice that nix flake init, nix flake new, etc. give you an old version of a template, run nix flake lock on that template. This action will force nix to update the cached version of the template somewhere in ~/.cache/nix. - src

Explore a template

Templates can be accessed in Nix store via nix repl:

nix repl
nix-repl> :lf .
nix-repl> templates.<TAB>
nix-repl> templates.codium-generic.path
/nix/store/j3kx4dk567y483pvszr2w8ghnkxich3d-source/templates/codium/generic

Assemble

Templates may contain arbitrary files. This feature enables the following assembly:

nix flake new flake-1 -t flake1
nix flake new flake-2 -t flake2
nix flake new flake-3 -t flake3
cp flake-1/file1 flake-3
cp flake-2/file{2,3} flake-3

Template repositories

  • Templates for many programming languages - src
  • Some more - src
  • Some templates are in this repo

Flakes

  1. What are flakes? How to enable flakes? - wiki

  2. Nix manual answers the following questions:

    • Glossary
      • What does this term mean?
    • Derivations
      • What are derivations?
        • Something that describes how to create a particular Nix store path
        • A derivation can become an executable, and that executable can be used in build scripts of other derivations
    • Description
      • What are flakes?
        • A flake is a function from inputs into outputs. To take this function at a point, a flake.lock is used
        • Don't confuse 'inputs' and 'outputs' with the terms inputs and outputs.
        • I use 'inputs' and 'outputs' to describe the high-level idea of what a flake is.
        • On the other hand, inputs and outputs have specifications described in Nix manual.
    • Flake inputs:
      • How to use old-style packages as flake inputs?
      • How to declare an input? == How to use a flake in another flake?
      • How to follow an input?
      • How to pin an input?
    • Flake format
      • What can go into outputs?
      • How to access the outputs? (described at the bottom)
      • How can I override nix.conf? - via nixConfig
    • Experimental commands
      • How to explore a flake?
        • nix flake show
        • nix flake metadata
        • nix repl
          • nix-repl> :lf nixpkgs - load flake nixpkgs
      • How to see all derivations used to build a specific derivation?
        • nix show-derivation
      • How can I temporarily make an executable available in my terminal?
        • nix shell
      • How can I install a Nix package on my OS?
        • nix profile
      • How can I pin my global nixpkgs to a specific commit SHA?
        • nix registry
    • And many more questions!
  3. How to add a flake to a project?

    • Nix uses git to track flake files. So, adding a flake.nix to a project requires the following steps:
      1. git init - initialize a git repository
      2. Add flake.nix in some way (copy the existing flake.nix, nix flake init, etc.)
      3. git add flake.nix
      4. Add flake.lock in some way (copy the relevant existing flake.lock, generate a new one via nix flake update, etc.)
      5. git add flake.lock
      6. git commit these files
  4. Flake tutorials: 1, 2, 3, 4, 5

  5. How to use the same flake inputs in all projects?

    • Store your flake inputs in a repo - example
    • Use them in your projects with follows - example
    • Now, all your projects have the same dependencies since they come from the same source
  6. How to bring any files into a flake?

    1. Hack git
      1. List expected files.
      2. Commit corresponding blank files.
      3. Run git update-index --assume-unchanged <file> for each <file>.
      4. Now, it's possible to import them into flake.
    2. Use Fixed-output derivations (FOD)
  7. How to enable a specific version of nix on my system? Approximately so:

    nix registry remove nix
    nix registry add nix github:NixOS/nix/4bf70b74a78bf10f3f19ed122ae7377963e14003
    nix profile install nix --priority 4
    
  8. How to pin nixpkgs?

  9. When should I use overlays over nixpkgs? - You shouldn't

  10. How to convert an exising project to flakes? - tutorial

  11. How to use a .gitignored file inside a flake?

    • build with --impure

      zxcTest = prev.writeText "zxcTest" (builtins.readFile /home/name_snrl/nixos-configuration/<fileFromIgnore>);
      
    • Provide it in inputs. Inputs accept arbitrary files. Make links follow the format of flake inputs

  12. How to disable querying remote binary caches?

    • nix run <installable> --no-substitute

devShells

  1. How to set up a development environment? 2. pkgs.mkShell 3. devshell 4. Add environment variables if necessary. E.g., using Nix store paths post 5. Symlink a path from Nix store to make files available to NodeJS - NixOS: The Ultimate Dev Environment?

Nix

Nix store caching

Q&A

  1. Run a binary from nixpkgs:

    nix run nixpkgs#nixpkgs-fmt -- hello-flake/flake.nix
    

Fixed-output derivation

Making derivations and executables

  1. What is expression, closure, derivation?

  2. How to get a path of a derivation in store in a .nix file?: ${drv}

  3. There are phases

  4. When derivations are built, they may produce executables. Locations of these executables are determined by bash scripts. If you make a derivation you can use buildInputs to specify the derivations you'd like to be accessible during in scripts during phases or in a shellHook

  5. How to access a $out folder of a derivation drv?

    • First of all, you should create such folder, e.g. via a builder
    • Next, you can use it in a script like ${drv.out};
  6. Programs can be specified in buildInputs or called by name {pkgs.hello}/bin/hello

    • This helped me when configuring tasks for VSCodium here
  7. How to wrap an executable to run it with flags?

  8. How to rename an executable and supply runtime dependencies?

    hello =
    pkgs.symlinkJoin {
      name = "hello";
      paths = [ hello ];
      buildInputs = [ pkgs.makeWrapper ];
      postBuild = ''
        wrapProgram $out/bin/hello \
          --set PATH ${
            pkgs.lib.makeBinPath [
              pkgs.cowsay
            ]
          }
      '';
    };
    
  9. How to escape a shell/bash command? 2. pkgs.lib.escapeShellArg

  10. How to see binaries that a package provides? 2. find $(nix build nixpkgs#hello --no-link --print-out-paths)/bin -mindepth 1

  11. It's possible to use nix commands inside scripts

    • E.g. nix-instantiate --eval --strict -E "import ./settings.nix" - print contents of a nix file
    • Moreover, one can use pinned nixpkgs: nix run ${pkgs}#nixpkgs-fmt $nix_path
  12. How to package a script? 2. pkgs.writeScriptBin

  13. How to remove build deps from runtime deps?

  14. How to use parallel builds? - docs

  15. cross-compilation

Helper function libs

  1. flake-compat.

    1. Whenever possible, add a flake into a repo, and then use flake-compat to create default.nix and shell.nix
    2. Use it to access scripts from a flake in a child directory - example
  2. flake-utils

  3. nixpkgs.lib

    $ nix repl
    nix-repl> :lf nixpkgs
    nix-repl> lib.or true false
    
  4. Symlinked things cannot be written or opened. They should first be removed - src

  5. pkgs.dockerTools.buildLayeredImage - build a docker image

    1. Pass static executables
    2. Set entrypoint: config.Entrypoint = [ command ]. No need for bash
    3. docker inspect the image

Package code

Haskell

See Haskell

Python

  1. poetry2nix

    • example
    • It might be necessary to
      • activate an environment for any app in a project - src
      • create envs - src
  2. pkgs.writers.writePython3Bin - SO

dream2nix

TypeScript

PureScript

  1. spago.nix
    • TODO try

Conventions

READMEs

In this repo, each flake's README.md assumes that the directory of its flake.nix is your current working directory in a terminal.

Prerequisites

To de-duplicate the docs, one of the top sections of each README.md here contains a Prerequisites section. This section provides the links to other sections that possibly contain the relevant docs. Sometimes, you'll need to traverse multiple Prerequisites before you achieve the relevant docs.

nixConfig

I inserted a number of binary caches into nixConfig attribute of each flake.nix. These caches should accelerate builds. You can add an accept-flake-config to your nix.conf.

Dev tools

Sometimes, I put dev tools into a nix-dev directory. Then, I enter a devshell as follows.

nix develop nix-dev/

Pushing to a remote repo

All flakes in this repo access some other flakes from this repo via GitHub URLs. Let's consider two flakes from this repo, A and B, where A is in inputs of B. If I change the flake A, I:

  • push A changes to GitHub.
  • update flake.lock of B.

Whenever there's a push to the remote GitHub repo, B's flake.lock is updated by a GitHub Action. That's why, if that action works, there's no need to commit and push flake.lock changes. After an update is complete, it's necessary to rebase local changes onto remote changes. However, sometimes, there are local uncommitted changes already. These changes should be git stashed before doing git rebase. After rebasing, they can be git stash popped to continue the work.

Thus, the process is as follows:

# can be omitted in case of automatic fetches
git fetch
git rebase --autostash
git push

Docs

Each derivation that evaluates to an executable should have these attributes:

  • meta.description
    • string written in CommonMark
    • This description will be rendered in devshells
    • It should be a single-line brief description of this executable
  • meta.longDescription
    • string written in CommonMark
    • This description is used to generate man pages for executables
    • The format of a longDescription should be recognizable by pandoc

Troubleshooting

Prerequisites

See Nix Prerequisites

Red text in the output

This is not a problem. Just read the text and answer. When asked like:

do you want to allow configuration setting 'extra-trusted-substituters' to be set to 'https://haskell-language-server.cachix.org https://nix-community.cachix.org https://cache.iog.io https://deemp.cachix.org' (y/N)?

answer y.

And then, when asked

do you want to permanently mark this value as trusted (y/N)? 

answer y again. This is to let you use the binary caches listed by the flake.

VSCodium troubleshooting

See VSCodium troubleshooting

Substituters and keys

To provide binary caches, flake.nix files specify nixConfig.extra-trusted-substituters. If you try, e.g., nix develop, and Nix unsuccessfully tries to download from a cache several times, this cache has probably failed. Comment out the lines containing its URL address in extra-trusted-substituters.

Repair a derivation

Repair a derivation - manual

Alternative steps:

  1. Assumptions:
    • current working directory contains flake.nix
    • your corrupt derivation is available inside this flake.nix by . name your-corrupt-derivation
  2. Set packages.default = your-corrupt-derivation in this flake.nix
  3. Run nix store repair .#

Locales

See Locales

Haskell

Templates

Templates provide extensive information about setting up development environment and packaging Haskell apps.

Tools

ghcid

ghcid is a Very low feature GHCi based IDE. It can be used to re-run a function in a given file on changes in a given directory. This template provides a sample configuration for this tool in the .ghcid file.

hpack

hpack translates package.yaml into .cabal.

Nix

haskell4nix

haskell.nix

Stack

Uses haskell4nix.

Stack support Nix integration.

Stack uses nix-shell.

The name of the file providing a Nix shell can be customized in stack.yaml.

Here's the format of that file - docs.

The shell file can import the contents of flake.nix via flake-compat.

flake.nix provides an output stack-shell.${system} = {version}: ....

stack.nix imports flake.nix and provides a shell.

devShells

Completions for CLI apps

devShells.default = pkgs.mkShell {
    buildInputs = [ packageExe ];
    shellHook = ''
      source ${packageExe}/share/bash-completion/completions/${packageExecutableName}
    '';
  };

Troubleshooting

Haskell Language Server

Clear cache

Sometimes, HLS finds errors in code despite cabal build running successfully. If you use VS Code, find Outputs of Haskell Language Server and determine the cache directory for a project.

It should have approximately this form: /home/<user name>/.cache/hie-bios/dist-<project-name>-<something>. Remove it and restart HLS.