Verified Commit 7ce160cc authored by doshitan's avatar doshitan

Add nix page

parent 760dbf25
---
title: Nix Tips
toc: true
---
Just a random collection of things to reference about
[nix](https://nixos.org/nix/).
# Minimal nix derivation
```nix
with import <nixpkgs> {};
stdenv.mkDerivation {
name = "env";
buildInputs = [
bashInteractive
];
}
```
This is useful for writing a quick and dirty, non-language specific
`default.nix` as a starting point to potentially packaging something.
If you need some tooling for a project, drop the tools in `buildInputs`, then
when you `nix-shell`, you'll have them available. Like:
```nix
with import <nixpkgs> {};
stdenv.mkDerivation {
name = "env";
buildInputs = [
awscli python36 nodejs-8_x
];
}
```
# mkShell
If you only want a shell environment, you can use `mkShell` in a `shell.nix`,
which is slightly shorter:
```nix
with import <nixpkgs> {};
mkShell {
buildInputs = [
awscli python36 nodejs-8_x
];
}
```
And also supports the `inputsFrom` parameter, if you want to pull build inputs
from other packages
```nix
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
# this will make all the build inputs from hello and gnutar
# available to the shell environment
inputsFrom = with pkgs; [ hello gnutar ];
buildInputs = [ pkgs.gnumake ];
}
```
<https://nixos.org/nixpkgs/manual/#sec-pkgs-mkShell>
# Pin nixpkgs
You'll likely want to do this for any non-trivial project, as it insulates the
project from any changes (or breakages) from the global nixpkgs and ensures the
same version of nixpkgs for the project is used by every one.
## niv
You should probably just use niv to do this.
<https://github.com/nmattia/niv>
See the [bootstrapping
section](https://github.com/nmattia/niv#bootstrapping-a-nix-project) to start.
## nix >= 2.0
If you don't want to use niv and you only need to support nix > 2.0, you can use
`builtins.fetchTarball`^[The builtin function supports the a `sha256` param on
the function, so it doesn't have to constantly refetch the tarball to check for
updates.]. If you need to support < 2.0 nix versions (or a mix), see the next
section.
```nix
{ rev ? "92f0d31b949bcf018262252408b8a69376a6cb68"
, sha256 ? "08ir579xsh7414i9y7jaislr2d56q716ayv2jlrrbpsx38gly453"
}:
let
nixpkgsPath = builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
inherit sha256;
};
pkgs = import nixpkgsPath {
config = {
# do whatever you want
# packageOverrides = oldPkgs: let newPkgs = oldPkgs.pkgs; in {...}
};
};
in
# do stuff with pkgs
```
You could also make nixpkgs a parameter and import the source inline, which is
more compact.
```nix
{ rev ? "92f0d31b949bcf018262252408b8a69376a6cb68"
, sha256 ? "08ir579xsh7414i9y7jaislr2d56q716ayv2jlrrbpsx38gly453"
, nixpkgs ? import (builtins.fetchTarball {
url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz";
inherit sha256;
}) { config = {} }
}:
# do stuff with nixpkgs
```
## nix < 2.0
For pre-2.0 nix support, you could use [this fetch-nixpkgs
helper][fetch-nixpkgs] or use `fetchFromGitHub`.
[fetch-nixpkgs]: https://nixos.wiki/wiki/How_to_fetch_Nixpkgs_with_an_empty_NIX_PATH or
With `fetchFromGitHub`:
```nix
{ hostPkgs ? import <nixpkgs> {}
, rev ? "92f0d31b949bcf018262252408b8a69376a6cb68"
, sha256 ? "08ir579xsh7414i9y7jaislr2d56q716ayv2jlrrbpsx38gly453"
, nixpkgs ? import (hostPkgs.fetchFromGitHub {
owner = "NixOS"; repo = "nixpkgs"; inherit rev sha256;
}) { config = {} }
}:
# do stuff with nixpkgs
```
## In environment
You can also set `NIX_PATH` to a location to use for `<nixpkgs>`, which if set
in some file sourced by the project (say a `.env` or `.envrc`), pins the version.
Either a specific commit:
```bash
export NIX_PATH=nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/628ba24e77b2c6f82f4c2d9e8a31d93fa06f2743.tar.gz:.
```
Or a channel:
```bash
export NIX_PATH=nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/nixos-19.03-small.tar.gz:.
```
# nix-shell as an interpreter
The nix manual has a [nice section on
this](https://nixos.org/nix/manual/#use-as-a-interpreter).
Older, but longer [tutorial on
this](http://iam.travishartwell.net/2015/06/17/nix-shell-shebang/).
Package script dependencies:
```bash
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p opusTools -p graphicsmagick -p file -p parallel -p flac
# do script things as normal
```
Run Haskell as a script:
```bash
#! /usr/bin/env nix-shell
#! nix-shell -i runghc -p "haskellPackages.ghcWithPackages (ps: with ps; [])"
main :: IO ()
main = putStrLn "Hello World!"
```
Pairs well with something like [turtle](https://hackage.haskell.org/package/turtle).
# nix + direnv
<https://github.com/direnv/direnv/wiki/Nix>
Just have a `default.nix` or `shell.nix` setup for you project. And an `.envrc`
containing:
```{.bash}
use nix
```
After a `direnv allow` in the directory, every time you move into the directory
you'll have a `nix-shell` environment setup for you automatically, in your own
familiar shell.
Combine this with an editor plugin for `direnv` and as you move around in your
editor, your project dependencies will be setup for you automatically. Very
convenient.
The upstream nix function in direnv is pretty simple. You'll probably want to
use a modified one to speed up direnv, particularly if you have it integrated
with you editor. See the [section on a persistent and cached
shell](https://github.com/direnv/direnv/wiki/Nix#persistent-shell-for-speeding-things-up)
for nix with direnv.
# Haskell
The Haskell infrastructure in nix is extensive, the [section in the
manual](https://nixos.org/nixpkgs/manual/#users-guide-to-the-haskell-infrastructure)
is a useful read.
## Basic dev environment
Probably the quickest way to get going developing a Haskell package is with
[haskellPackges.developPackage](https://github.com/NixOS/nixpkgs/blob/f3282c8d1e0ce6ba5d9f6aeddcfad51d879c7a4a/pkgs/development/haskell-modules/make-package-set.nix#L215):
Have a cabal file for your project, then your `default.nix` can just be:
```nix
{ pkgs ? import <nixpkgs> {} }:
pkgs.haskellPackages.developPackage {
root = ./.;
}
```
This automatically calls `cabal2nix`, makes it easy to specify overrides and such.
If you want to fix a compiler version, say the default is too new for you:
```nix
{ pkgs ? import <nixpkgs> {}
, ghcVersion ? "ghc842"
}:
pkgs.haskell.packages."${ghcVersion}".developPackage {
root = ./.;
}
```
There's a little more on this in [the
manual](https://nixos.org/nixpkgs/manual/#how-to-specify-source-overrides-for-your-haskell-package),
particularly for when you need to override a dependencies packaged version.
# Nix: Under the hood
Good talk covering the basics of how nix works, simply.
<https://youtu.be/GMQPzv3Sx58>
# Test your NixOS config
https://twitter.com/IotaSamurai/status/1045220406792048640
```
nix repl '<nixpkgs/nixos>'
```
You can poke at your config without having to `nixos-rebuild`.
# LaTeX
Arbitrary, one-off environments:
`nix-shell -E 'with import <nixpkgs> {}; mkShell { buildInputs = [(texlive.combine { inherit (pkgs.texlive) scheme-small standalone latexmk cm-super; })]; }'`
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment