nix.mkd 24.6 KB
Newer Older
doshitan's avatar
doshitan committed
1
2
3
---
title: Nix Tips
toc: true
doshitan's avatar
doshitan committed
4
toc-margin: true
5
6
published: 2019-08-21T08:25:45-04:00
modified: 2019-09-05T22:54:28-04:00
doshitan's avatar
doshitan committed
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
---

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`.

doshitan's avatar
doshitan committed
136
[fetch-nixpkgs]: https://nixos.wiki/wiki/How_to_fetch_Nixpkgs_with_an_empty_NIX_PATH
doshitan's avatar
doshitan committed
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

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

doshitan's avatar
doshitan committed
179
# do script things as normal, guaranteed the specified tools are available
doshitan's avatar
doshitan committed
180
181
182
```

Run Haskell as a script:
doshitan's avatar
doshitan committed
183
```haskell
doshitan's avatar
doshitan committed
184
185
186
187
188
189
190
#! /usr/bin/env nix-shell
#! nix-shell -i runghc -p "haskellPackages.ghcWithPackages (ps: with ps; [])"

main :: IO ()
main = putStrLn "Hello World!"
```

doshitan's avatar
doshitan committed
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
Pairs well with something like
[turtle](https://hackage.haskell.org/package/turtle), e.g.,

```haskell
#! /usr/bin/env nix-shell
#! nix-shell -i runghc -p "haskellPackages.ghcWithPackages (ps: with ps; [turtle])"

{-# LANGUAGE OverloadedStrings #-}

import Turtle

data Command = IncreaseVolume Int | DecreaseVolume Int deriving (Show)

parser :: Parser Command
parser
    =   fmap IncreaseVolume
            (subcommand "up" "Turn the volume up"
                (argInt "amount" "How much to increase the volume") )
    <|> fmap DecreaseVolume
            (subcommand "down" "Turn the volume down"
                (argInt "amount" "How much to decrease the volume") )

main = do
    x <- options "Volume adjuster" parser
    case x of
        IncreaseVolume n -> printf ("Increasing the volume by "%d%"\n") n
        DecreaseVolume n -> printf ("Decreasing the volume by "%d%"\n") n
```

Write your bash scripts...in Haskell!

Example taken from the end of the last section of the [Turtle
tutorial](https://hackage.haskell.org/package/turtle-1.5.14/docs/Turtle-Tutorial.html#g:18).
doshitan's avatar
doshitan committed
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

# 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.

doshitan's avatar
doshitan committed
250
251
252
If you're feeling adventurous, look into <https://github.com/target/lorri>
instead of using the `nix-shell` direnv stuff directly.

doshitan's avatar
doshitan committed
253

doshitan's avatar
doshitan committed
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# Language-specific things

Many languages have to tooling to automate packaging with nix, e.g.,
`cabal2nix`, `pypi2nix`, etc. For a more complete list see [the wiki
page](https://nixos.wiki/wiki/Language-specific_package_helpers).

This support is uneven across languages, largely dependent on how many nix users
there are who give their time to improve and maintain that languages
infrastructure. Some languages are also more or less hostile to packaging in the
nix way, some have more non-determinism or poor dependency
tracking/specification, which complicate making easy tooling for it.

[Chapter 9 of the nixpkgs
manual](https://nixos.org/nixpkgs/manual/#chap-language-support) has more
details on a numbers of different languages, development tips, troubleshooting,
etc.


doshitan's avatar
doshitan committed
272
273
274
275
276
277
278
279
280
281
# 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
doshitan's avatar
doshitan committed
282
[haskellPackages.developPackage](https://github.com/NixOS/nixpkgs/blob/f3282c8d1e0ce6ba5d9f6aeddcfad51d879c7a4a/pkgs/development/haskell-modules/make-package-set.nix#L215):
doshitan's avatar
doshitan committed
283
284
285
286
287
288
289
290
291
292
293

Have a cabal file for your project, then your `default.nix` can just be:

```nix
{ pkgs ? import <nixpkgs> {} }:

pkgs.haskellPackages.developPackage {
  root = ./.;
}
```

doshitan's avatar
doshitan committed
294
295
296
This automatically calls `cabal2nix`, makes it easy to specify overrides, and
will drop you into a development shell when `nix-shell` is used (no need for a
separate `shell.nix`).
doshitan's avatar
doshitan committed
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313

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.

doshitan's avatar
doshitan committed
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
A more complete (and complicated) example:

```nix
{ pkgs ? import <nixpkgs> {}
, ghcVersion ? "ghc842"
}:

pkgs.haskell.packages."${ghcVersion}".developPackage {
  root = ./.;

  # `source-overrides` are overrides on which source code to fetch for a
  # package, here we can specify *what* to build for a dependency
  source-overrides = {
    # if you need to use a different version from Hackage than what is in
    # the current package set, can just specify the version and it will be
    # fetched automatically (gets turned into a call to the `callHackage`
    # function)
    HUnit = "1.5.0.0";

    # if you need a Haskell package that is not on Hackage, say either an
    # unpublished version or a fork, just fetch the repo
    servant-swagger = pkgs.fetchFromGitHub {
      owner = "haskell-servant";
      repo = "servant-swagger";
      rev = "9c0ceb9f5cd00a47e922ba5de4be5ad591d99a0a";
      sha256 = "1qkpj40sgy0nidd9av4rvd8754lh6zhakdqa05jgkzizf37wfz10";
    };

    # if you have a local checkout of a package, you can specify the path to it,
    # this might commonly be a submoduled package, but you can specify paths
    # outside the current project, though this of course only works for you personal
    # local setup, but sometimes that's all you need
    my-local-package = ../my-local-package;
  };

  # `overrides` are overrides to the package derivations themselves, so it's
  # here we can can specify changes to *how* dependencies are built, generally
  # using helper functions from the nix haskell library, see all the options:
  # https://github.com/NixOS/nixpkgs/blob/f3282c8d1e0ce6ba5d9f6aeddcfad51d879c7a4a/pkgs/development/haskell-modules/lib.nix
  #
  # "overriding" a set of things is a common pattern in nix, for clarity here
  # I've used a more verbose style, but:
  #
  # `newHaskellPkgs` is conventionally called `self` and is the overridden set
  # after it's been resolved, which you sometimes need
  #
  # `oldHaskellPkgs` is conventionally called `super`, it's basically the set of
  # things you are overriding
  overrides = newHaskellPkgs: oldHaskellPkgs: {
    # sometimes you need to use a package that has a broken test suite for
    # whatever reason, here in overrides you can use the helper `dontCheck` to
    # skip the test suite when building the package
    hasktags = pkgs.haskell.lib.dontCheck oldHaskellPkgs.hasktags;

    # sometimes packages have overly restrictive version bounds, the
    # `doJailbreak` helper can tell the build to ignore them so it can be built
    # against the versions you have in your package set
    async = pkgs.haskell.lib.doJailbreak oldHaskellPkgs.async;

    # sometimes you need to patch a package to build or work right with you
    # package set
    some-package = pkgs.haskell.lib.appendPatch oldHaskellPkgs.some-package ./fix-some-package.patch;
  };
doshitan's avatar
doshitan committed
377
378
379
380

  # this is a spot you can modify the derivation for the package itself,
  # usually will be applying one haskell lib function like in `overrides`
  modifier = pkgs.haskell.lib.buildStrictly;
doshitan's avatar
doshitan committed
381
382
383
}
```

doshitan's avatar
doshitan committed
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
If you want to add some development tools to the `nix-shell` environment, one
way you could do it is with a `shell.nix` containing:

```{.nix caption="shell.nix"}
{ pkgs ? import <nixpkgs> {} }:
let
  package = import ./default.nix { inherit pkgs; };
in
  package.overrideAttrs (oldAttrs: {
    buildInputs = oldAttrs.buildInputs ++ [
      pkgs.haskellPackages.cabal-install
      pkgs.haskellPackages.ghcid
      # ...
    ];
  })
```

Though keeping the right compiler version/package set in sync between the dev
tools and the package environment from `developPackage` could be challenging
since the package set from `developPackage` isn't exposed. I'm not sure as I
don't use this setup.

For this and other reasons I generally recommend the next development setup, but
`developPackage` is quick when you need it.


doshitan's avatar
doshitan committed
410
411
## Improved setup

doshitan's avatar
doshitan committed
412
413
414
While `haskellPackages.developPackage` is pretty easy, for projects with more
than one package, or if you just want more flexibility, or explicitness, you can
break apart what `developPackage` is doing.
doshitan's avatar
doshitan committed
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490

In your `default.nix`, extend the Haskell package set to include the project packages:

```{.nix caption="default.nix"}
{ pkgs ? import <nixpkgs> {} }:

let
  haskellPackages = pkgs.haskellPackages.extend (pkgs.haskell.lib.packageSourceOverrides {
    # your Haskell packages for the project
    foo = ./foo;
    bar = ./bar;
    # for a simple project with only one package at the top-level, this might be
    # baz = ./.;
  });
in {
  inherit pkgs haskellPackages;
  # same as if we'd written:
  # pkgs = pkgs;
  # haskellPackages = haskellPackages;

  # make the project package a top level attributes for easier building, e.g.,
  # nix-build -A foo
  #
  # instead of
  #
  # nix-build -A haskellPackages.foo
  foo = haskellPackages.foo;
  bar = haskellPackages.bar;
}
```

Then utilize the `haskellPackages.shellFor` function to build a more
configurable development environment in your `shell.nix`:

```{.nix caption="shell.nix"}
let
  project = import ./. {};
in
  project.haskellPackages.shellFor {
    # dependencies for the listed packages will all be available in the shell
    packages = p: [p.foo p.bar];

    # build a local hoogle database for all the dependencies of the given
    # packages, the hoogle executable in the shell environment will be set to
    # use it automatically
    # withHoogle = true;

    # list any other things you want available in the shell
    buildInputs = [
      project.haskellPackages.cabal-install
      # project.haskellPackages.ghcid
      # ...whatever other Haskell dev tools you need

      # project.pkgs.niv
      # project.pkgs.gnumake
      # project.pkgs.terraform
      # ...whatever other general dev tools you need
    ];
  }
```

Adapted from [this
comment](https://www.reddit.com/r/haskell/comments/8fnlhq/little_tool_for_haskell_environment_with_nix/dy58z4a/).
This is a simplified example, just trying to get the basic idea across.

You can get fancier, automatically pickup the project packages from the
`cabal.project`, and such, see [this
gist](https://gist.github.com/codebje/000df013a2a4b7c10d6014d8bf7bccf3) for an
example.

See the documentation on
[haskellPackages.shellFor](https://github.com/NixOS/nixpkgs/blob/713a45ecf79a4b4c632819f1c898d3e66c77bdd2/pkgs/development/haskell-modules/make-package-set.nix#L253)
and
[haskell.lib.packageSourceOverrides](https://github.com/NixOS/nixpkgs/blob/713a45ecf79a4b4c632819f1c898d3e66c77bdd2/pkgs/development/haskell-modules/lib.nix#L43)
for more on what is actually going on.

doshitan's avatar
doshitan committed
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
A more complete (and complicated) example equivalent to the `developPackage` one:

```{.nix caption="default.nix"}
{ pkgs ? import <nixpkgs> {} }:

let
  haskellPackages = pkgs.haskellPackages.extend (pkgs.lib.composeExtensions
    # these are "source overrides", that is, overrides on which source code to
    # fetch for a package, here we can specify *what* to build
    (pkgs.haskell.lib.packageSourceOverrides ({
      # your Haskell packages for the project
      foo = ./foo;
      bar = ./bar;

      # if you need to use a different version from Hackage than what is in
      # the current package set, can just specify the version and it will be
      # fetched automatically (gets turned into a call to the `callHackage`
      # function)
      HUnit = "1.5.0.0";

      # if you need a Haskell package that is not on Hackage, say either an
      # unpublished version or a fork, just fetch the repo
      servant-swagger = pkgs.fetchFromGitHub {
        owner = "haskell-servant";
        repo = "servant-swagger";
        rev = "9c0ceb9f5cd00a47e922ba5de4be5ad591d99a0a";
        sha256 = "1qkpj40sgy0nidd9av4rvd8754lh6zhakdqa05jgkzizf37wfz10";
      };

      # if you have a local checkout of a package, you can specify the path to it,
      # this might commonly be a submoduled package, but you can specify paths
      # outside the current project, though this of course only works for you personal
      # local setup, but sometimes that's all you need
      my-local-package = ../my-local-package;
    }))

    # these are overrides to the package derivations themselves, so it's here we
    # can specify changes to *how* things are built, generally using helper
    # functions from the nix haskell library, see all the options:
    # https://github.com/NixOS/nixpkgs/blob/f3282c8d1e0ce6ba5d9f6aeddcfad51d879c7a4a/pkgs/development/haskell-modules/lib.nix
    #
    # "overriding" a set of things is a common pattern in nix, for clarity here
    # I've used a more verbose style, but:
    #
    # `newHaskellPkgs` is conventionally called `self` and is the overridden set
    # after it's been resolved, which you sometimes need
    #
    # `oldHaskellPkgs` is conventionally called `super`, it's basically the set of
    # things you are overriding
    (newHaskellPkgs: oldHaskellPkgs: {
      # you can tweak the build flags for you packages here if needed
      foo = pkgs.haskell.lib.buildStrictly oldHaskellPkgs.foo
      bar = pkgs.haskell.lib.buildStrictly oldHaskellPkgs.bar

      # sometimes you need to use a package that has a broken test suite for
      # whatever reason, here in overrides you can use the helper `dontCheck` to
      # skip the test suite when building the package
      hasktags = pkgs.haskell.lib.dontCheck oldHaskellPkgs.hasktags;

      # sometimes packages have overly restrictive version bounds, the
      # `doJailbreak` helper can tell the build to ignore them so it can be built
      # against the versions you have in your package set
      async = pkgs.haskell.lib.doJailbreak oldHaskellPkgs.async;

      # sometimes you need to patch a package to build or work right with you
      # package set
      some-package = pkgs.haskell.lib.appendPatch oldHaskellPkgs.some-package ./fix-some-package.patch;
    })
  );

in {
  inherit pkgs haskellPackages;
  # same as if we'd written:
  # pkgs = pkgs;
  # haskellPackages = haskellPackages;

  # make the project package a top level attributes for easier building, e.g.,
  # nix-build -A foo
  #
  # instead of
  #
  # nix-build -A haskellPackages.foo
  foo = haskellPackages.foo;
  bar = haskellPackages.bar;

  # say foo is an executable, statically linking it to it's Haskell libs can
  # reduce the closure size and simplify some things, e.g., non-nix deploys,
  # though fully  static Haskell executables take some more work, see:
  # https://github.com/NixOS/nixpkgs/issues/43795
  foo-static = pkgs.haskell.lib.justStaticExecutables haskellPackages.foo;
}
```


## haskell.nix

[haskell.nix](https://input-output-hk.github.io/haskell.nix/) is an alternate
Haskell infrastructure for nixpkgs. It's own [motivation
section](https://input-output-hk.github.io/haskell.nix/#motivation) details why
it exists, but generally, the goal is to have nix doing more of the work
natively (instead of relying on things like `cabal2nix`), which increases
flexibility, control, and simplicity.

I've not used it personally, but it's neat and seems a worthwhile endeavor to
experiment with what else is possible.


## Other nix-haskell stuff

- <https://notes.srid.ca/haskell-nix>
- <https://github.com/cdepillabout/post-about-nix-and-haskell>
doshitan's avatar
doshitan committed
602
603
- <https://github.com/Gabriel439/haskell-nix>
- <https://github.com/shajra/example-nix>
doshitan's avatar
doshitan committed
604

doshitan's avatar
doshitan committed
605
606
607
608
609
610
611
612
613

# Learning Nix

<https://learnxinyminutes.com/docs/nix/>

<https://github.com/tazjin/nix-1p/blob/master/README.md>

<https://nixos.org/nixos/nix-pills/>

doshitan's avatar
doshitan committed
614
615
616
617
618
619
620
621
622
623
624
625
626
627

# Nix: Under the hood

Good talk covering the basics of how nix works, simply.

<https://youtu.be/GMQPzv3Sx58>


# Test your NixOS config

```
nix repl '<nixpkgs/nixos>'
```

doshitan's avatar
doshitan committed
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
You can poke at your config without having to `nixos-rebuild`, with TAB
complete.

The `config` attribute holds your system config. `pkgs` allows you to look at
the packages in that version of the system.

<https://twitter.com/IotaSamurai/status/1045220406792048640>

<https://nixos.wiki/wiki/Nix-repl>


# NixOS options

There are a lot of configuration options supported by NixOS. The [options search
page on the website](https://nixos.org/nixos/options.html) is useful to find a)
if the thing you want to configure has been packaged as a service in NixOS and
b) what knobs you can turn for it.

One nice thing about the search tool is that it links directly to the source
file for the service, so you can inspect what is actually happening with the
option if you want to.

Note that currently, the website search tool only shows options for the latest
stable release, if you are living on the edge, you'll have to search nixpkgs
yourself, either grep a local copy of the repo, search GitHub, or use
`nixos-option`.

`nixos-option` evaluates your NixOS config and will display all the attributes
in a given attribute set available for it. For example:

```
nixos-option services.postgresql
```

Will show all the attributes you can set to configure the postgres service. It
unfortunately does not display the description when listing the attributes
(though hopefully is at least broadly clear in the name itself), but if you
specify a specific one, like:

```
nixos-option services.postgresql.dataDir
```

Then it will display more complete documentation for it, including the current
value in your configuration, the default, a description of what the option is
for, and a file path for module it's declared in.

The website search is nicer, but `nixos-option` works offline and can be helpful
as it does display the currently set value for *your* configuration. The repl is
usually better to explore your evaluated configuration, given it has TAB
complete, but sometimes `nixos-option` is more useful.


# Finding Nix packages

`nix search <name>` or <https://nixos.org/nixos/packages.html>


# Cheatsheet

The [NixOS
cheatsheet](https://nixos.wiki/index.php?title=Cheatsheet&useskin=vector) has a
bunch of stuff that is useful to look over, including a table comparing how you
would do something in Ubuntu and the equivalent command on NixOS.

It also has a bunch of short little snippets about how to do various things,
cross-compile a package, and other similar tasks.
doshitan's avatar
doshitan committed
695

doshitan's avatar
doshitan committed
696

doshitan's avatar
doshitan committed
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
# Get source hash

So anytime something is fetched in a nix expression, we want the hash of the
result (the `sha256` attribute) for reproduciblity and security; to know it
hasn't been changed from what we expect (either from a malicious attack or
simple error) and to make checking if we even need to go fetch anything in the
first place (i.e., we've already fetched this version so the source so can just
use the local copy).

There are some `nix-prefetch-*` tools to help with getting that hash, the most
commonly used one is probably `nix-prefetch-url`.

Just give it a URL (usually to a tarball), it will fetch it, add it to the nix
store and print the hash for your expression.

For the hash to use in a `fetchTarball` call, you can just the tool directly.

For the hash to use in a `fetchFromGitHub` call, you will want to add the
`--unpack` flag, as this will check against the hash of the *content* of the
archive, not the hash of the tarball itself.

For example:
```nix
nix-prefetch-url --unpack https://github.com/NixOS/nix/archive/1f795f9f44607cc5bec70d1300150bfefcef2aae.tar.gz
```

There are other tools, `nix-prefetch-git` and `nix-prefetch-github`, equivalent
to above would be:
```nix
nix run -f '<nixpkgs>' nix-prefetch-github -c nix-prefetch-github --rev 1f795f9f44607cc5bec70d1300150bfefcef2aae NixOS nix
```

You can also just take another hash^[Or use `lib.fakeSha256` or generate a
random hash to use, e.g., `uuidgen | sha256sum`.], change one character, then
try to build the thing, nix will error telling you the hash it expected, which
you can then use and build again. This is hacky, and best to be avoided.

See the [relevant sections in the
manual](https://nixos.org/nixpkgs/manual/#how-to-specify-source-overrides-for-your-haskell-package).
doshitan's avatar
doshitan committed
736

doshitan's avatar
doshitan committed
737

doshitan's avatar
doshitan committed
738
739
740
741
# LaTeX

Arbitrary, one-off environments:
`nix-shell -E 'with import <nixpkgs> {}; mkShell { buildInputs = [(texlive.combine { inherit (pkgs.texlive) scheme-small standalone latexmk cm-super; })]; }'`
doshitan's avatar
doshitan committed
742
743
744
745


# Misc.

doshitan's avatar
doshitan committed
746
- <https://weekly.nixos.org/>
doshitan's avatar
doshitan committed
747
748
- <https://cachix.org/>
- <https://hercules-ci.com/>
doshitan's avatar
doshitan committed
749
750
- <https://github.com/hercules-ci/arion>
- <https://github.com/hercules-ci/gitignore>
doshitan's avatar
doshitan committed
751
752
- <https://nixery.dev/>
- <https://r13y.com/>
doshitan's avatar
doshitan committed
753
- <https://nixos.org/nixpkgs/manual/#chap-conventions>