Skip to content

Instantly share code, notes, and snippets.

@PardusEidolon
Last active April 11, 2022 04:24
Show Gist options
  • Save PardusEidolon/af8af334ac52a64804d2e0374f91d3c4 to your computer and use it in GitHub Desktop.
Save PardusEidolon/af8af334ac52a64804d2e0374f91d3c4 to your computer and use it in GitHub Desktop.
A Nix Cookbook with all things nix.

Nix Cookbook

Nix Commands

nix-env — manipulate or query Nix user environments
nix-build — build a Nix expression
nix-shell — start an interactive shell based on a Nix expression
nix-store — manipulate or query the Nix store

Nix and VS Code

Development Tools

direnv is an extension for your shell. It augments existing shells with a new feature that can load and unload environment variables depending on the current directory.

lorri is a nix-shell replacement for project development. lorri is based around fast direnv integration for robust CLI and editor integration.

Cachix - Nix Cache service. If your project build takes 15 minutes, why build it three times and waste your time? With Cachix you can share the binaries once it’s built.

Nix Ops. NixOps is a tool for deploying to NixOS machines in a network or the cloud.

Disnix. Disnix is a distributed service deployment extension for the Nix package manager.

Setting up Cachix

Sometimes it might be useful to ship the dependencies to a service like Cachix to help speed up builds.

Nix builds a package in isolation from your system. This ensures that build process is reproducible and doesn’t have undeclared dependencies, so if a package is built on one machine, it will build identically on another machine. Nix also hashes the inputs before building a package. By querying Cachix with the hash, it’s possible to download the binary identified by the hash as a replacement for the build process.

You can install the cachix tool like this:

nix-env -iA cachix -f https://cachix.org/api/v1/install

And then follow the steps at cachix.org to create a new binary cache. Let’s assume you made a cache named teddybear. When you’ve created a new cache, logged in with an API token and created a signing key, you can pipe nix-build to the Cachix client like so:

nix-build | cachix push teddybear

And other people using that cache will benefit from your premade dependency and binary downloads.

To use the cache somewhere, install the Cachix client and then run the following:

hix use teddybear

I’ve been able to use my Go, Elm, Rust and Haskell dependencies on other machines using this. It’s saved so much extra download time.

Setting up Nix on a new Multipass Ubuntu Instance.

To install a single-user Nix for any Linux distribution, use the following two commands.

sudo install -d -m755 -o $(id -u) -g $(id -g) /nix
sh <(curl -L https://nixos.org/nix/install) --darwin-use-unencrypted-nix-store-volume --daemon
Note
This assumes you have the permission to use sudo, and you are logged in as the user you want to install Nix for.

Then don’t forget to run the command provided at the end of the installation script to make nix available in your system:

source $HOME/.nix-profile/etc/profile.d/nix.sh

You may want to put this file directly in your ~/.bashrc or similar, so Nix would be available in any newly created shell.

How to set up the IOHK binary caches

Adding the IOHK binary cache to your Nix configuration will speed up builds a lot, since many things will have been built already by our CI.

If you find you are building packages that are not defined in this repository, or if the build seems to take a very long time then you may not have this set up properly.

  • The system-wide configuration file sysconfdir/nix/nix.conf (i.e. /etc/nix/nix.conf on most systems), or $NIX_CONF_DIR/nix.conf if NIX_CONF_DIR is set.

  • The user configuration file $XDG_CONFIG_HOME/nix/nix.conf, or ~/.config/nix/nix.conf if XDG_CONFIG_HOME is not set.

To set up the cache on non-NixOS, edit sudo nano /etc/nix/nix.conf and add the following lines:

substituters        = https://hydra.iohk.io https://iohk.cachix.org https://cache.nixos.org/
trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= iohk.cachix.org-1:DpRUyj7h7V830dp/i6Nti+NEO2/nhblbov/8MW7Rqoo= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=

If the directory does not exist then create it sudo mkdir /etc/nix. Then you can use nix show-config | grep iohk to see if it has found it.

Note
If you are a trusted user you will need add the nix.conf lines to ~/.config/nix/nix.conf instead.

This issue may also be help, but I’ve found no use: Adding trusted binary cache on Mac OS X requires restarting nix-daemon

Note
To test that the caches are being used nix show-config | grep substituters.

Nix on macOS

Nix on macOS can be a bit tricky. In particular, sandboxing is disabled by default, which can lead to strange failures.

These days it is still unsafe to turn on sandboxing on macOS with a few exceptions. Consider setting the following Nix settings, in the same way as in previous section:

sandbox = true
extra-sandbox-paths = /System/Library/Frameworks /System/Library/PrivateFrameworks /usr/lib /private/tmp /private/var/tmp /usr/bin/env

Problems with building nix-shell on OSX Big Sur

I managed to have this issue sorted out. It’s probably going to go away as the new stable version of Nix will be released working with this version of Big Sur. But for the sake of people who may encounter it, here is one solution.

  • The first problem was, that I’ve set up Sandboxing for Nix on Mac according this 2. I shouldn’t have had. It doesn’t work on Big Sur 11.2.2

  • After this if you try to run nix-shell it fails with another problem. It tries to build ghc 8.10.2, but it fails as it won’t find the libcache.dylib and cannot link the respective symbols. It is also a side-effect of Big Sur 11.2.2 and this version of nixpkgs (20.09). To resolve this you need to use a newer (unstable) build of nixpkgs where this has been fixed. To do that here is one way to do it (I’m definitely not a Nix pro, so probably there are better ways to do this. This at least worked for me):

  • Add an unstable nix channel by following this 4

  • Update shell.nix for the example contract to use that and do not fetch 20.09. I couldn’t find a tarball for the unstable version, so I went with this solution for shell.nix:

{ nixpkgs ? import <unstable> {} }:
let runtimeGhc = nixpkgs.haskell.packages.ghc8102.ghcWithPackages (ps: with ps; [ zlib ]);
in
with nixpkgs; mkShell {
  buildInputs = [
    runtimeGhc
    cabal-install
    stack
    wget
    curl
    binutils
    git
    vim
    openssl.dev
  ];
}

Setting up direnv and lorri for Nix

For unbuntu

Use nix-env: nix-env -i lorri Otherwise see the instructions in [lorri’s git repository](https://github.com/nix-community/lorri) and [How to start the lorri daemon as a service](https://github.com/nix-community/lorri/blob/canon/contrib/daemon.md).

For setting up direnv nix-env -i direnv and hook in the [bash shell](https://direnv.net/docs/hook.html)

Add the following to the .envrc file.

use_nix
eval "$(lorri direnv)"

The use_nix will export paths and built commands to the shell. If you want a pure shell that does not interact with the local system then:

use_nix
eval "$(lorri direnv)"
nix-shell --run bash --pure

For OSX

Note
I can’t get the nix-daemon to load at start-up time. Use launchctl load -w /Library/LaunchDaemons/org.nixos.nix-daemon.plist to start it. However I have NO idea what this daemon does or what it is needed for.

LaunchAgents are only invoked when the user logs into a graphical session.

LaunchDaemons are typically launched when the system boots and are run outside of a specific user session.

The launchd manual page lists these folders with short descriptions:

  • ~/Library/LaunchAgents Per-user agents provided by the user.

  • /Library/LaunchAgents Per-user agents provided by the administrator.

  • /Library/LaunchDaemons System-wide daemons provided by the administrator.

  • /System/Library/LaunchAgents Per-user agents provided by Mac OS X.

  • /System/Library/LaunchDaemons System-wide daemons provided by Mac OS X.

Lorri plist file com.github.target.lorri.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.github.target.lorri</string>
    <key>ProgramArguments</key>
    <array>
        <string>/bin/zsh</string>
        <string>-i</string>
        <string>-c</string>
        <string>lorri daemon</string>
    </array>
    <key>StandardOutPath</key>
    <string>/var/tmp/lorri.log</string>
    <key>StandardErrorPath</key>
    <string>/var/tmp/lorri.log</string>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
	<true/>
</dict>
</plist>
nix-shell -p nix-info --run "nix-info -m"

launchctl load -w /Library/LaunchDaemons/org.nixos.nix-daemon.plist
launchctl load -w ~/Library/LaunchAgents/com.github.target.lorri.plist

ls /Library/LaunchAgents/
ls ~/Library/LaunchAgents/
mv com.github.target.lorri.plist ~/Library/LaunchAgents/

launchctl load ~/Library/LaunchAgents/com.github.target.lorri.plist
launchctl unload ~/Library/LaunchAgents/com.github.target.lorri.plist

launchctl list | rg "nix"
launchctl list | rg "lorri"

Pinning dependencies with Niv

niv simplifies adding and updating dependencies in Nix projects. It uses a single file, nix/sources.json, where it stores the data necessary for fetching and updating the packages.

Nodejs and NPM setup

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment