• Stars
    star
    231
  • Rank 173,434 (Top 4 %)
  • Language
  • License
    MIT License
  • Created over 7 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

nix-shell recipes

Nix for devs

This is collection of recipes focused on nix-shell to make setting up project environments easy. Pragmatism and low project impact are prioritized: it's not a goal to change a nodejs project to use nix instead of npm, but it is a goal to run npm projects without having to install any OS dependencies (including nodejs itself!). nix-ops and other super-cool nix tech are completely out of scope.

Every solution should work today. If something is broken, open an issue!. If there is a better solution that will be supported by nix soon, we wait until it's released before mentioning it here (but don't hesitate to open a tracking issue!).

Maybe in the best case, this document can be a kind of gateway to nix and nixos. I keep telling my developer friends about the cool things I do with nix, but I have to add huge warnings about how much time it's taken me to get to my current level of productivity. I'm annoyingly aware of the amount of trivia I'm carying in my head (though I still feel like a beginner!), and I constantly go back to old projects to look up what I did last time to fix problems. I frequently find myself running into hard-to-google issues. So, I'm finally writing it all down, for myself as much as for my friends :)

Work-in-progress

Current state: rough sketches and todos. Pull requests welcome!

nix-shell

TODO

Run stuff without installing anything

Stuff I used to do with docker. TODO :)

Node.js

shell.nix

with import <nixpkgs> {};

stdenv.mkDerivation {
    name = "node";
    buildInputs = [
        nodejs
    ];
    shellHook = ''
        export PATH="$PWD/node_modules/.bin/:$PATH"
    '';
}

The nodejs build input sets up node and npm in the shell. The shell hook adds the .bin/ folder to your PATH, so you can install node command-line tools like grunt with npm without the -g flag. Finally, it automatically installs any dependencies found in package.json, if one exists. If you prefer to run npm install manually inside the shell, just delete that line from shellHook.

npm run <...> shortcut

It's handy to have an alias run for npm run, which makes the following two commands equivalent:

$ npm run watch:test
$ run watch:test

You can add this to shellHook:

    alias run='npm run'

Newer nodejs

shell.nix

with import <nixpkgs> {};

stdenv.mkDerivation {
    name = "node";
    buildInputs = [
        nodejs-8_x
    ];
    shellHook = ''
        export PATH="$PWD/node_modules/.bin/:$PATH"
    '';
}

Node versions are published as -_x, so etg., nodejs-7_x and nodejs-6_x are also valid.

View available npm scripts

I use jq to quickly get a summary of all scripts defined in a package's package.json file:

shell.nix

with import <nixpkgs> {};

stdenv.mkDerivation {
    name = "node";
    buildInputs = [
        jq
        nodejs
    ];
    shellHook = ''
        export PATH="$PWD/node_modules/.bin/:$PATH"
        alias scripts='jq ".scripts" package.json'
    '';
}

This sets up an alias called scripts. Example output:

$ scripts
{
  "build": "babel --ignore __tests__,story.js -d lib/ src/",
  "lint": "eslint *.js src/ storybook/",
  "start": "start-storybook -p 9001 -c ./storybook/web",
  "test": "jest --roots src --silent",
  "test:watch": "jest --roots src --watch"
}

React native

shell.nix

with import <nixpkgs> {};

let
  jdk = openjdk;
  node = nodejs-8_x;
  sdk = androidenv.androidsdk {
    platformVersions = [ "23" ];
    abiVersions = [ "x86" ];
    useGoogleAPIs = true;
    useExtraSupportLibs = false;
    useGooglePlayServices = false;
  };
  unpatched-sdk =
    let version = "3859397";
    in stdenv.mkDerivation {
      name = "unpatched-sdk";
      src = fetchzip {
        url = "https://dl.google.com/android/repository/sdk-tools-linux-${version}.zip";
        sha256 = "03vh2w1i7sjgsh91bpw40ryhwmz46rv8b9mp7xzg89zs18021plr";
      };
      installPhase = ''
        mkdir -p $out
        cp -r * $out/
      '';
      dontPatchELF = true;
    };
  run-android = pkgs.buildFHSUserEnv {
    name = "run-android";
    targetPkgs = (pkgs: [
      node
    ]);
    profile = ''
      export JAVA_HOME=${jdk.home}
      export ANDROID_HOME=$PWD/.android
      export PATH=$PWD/node_modules/.bin:$PATH
    '';
    runScript = "react-native run-android";
  };
in
  stdenv.mkDerivation {
    name = "react-native-android";
    nativeBuildInputs = [
      run-android
    ];
    buildInputs = [
      coreutils
      node
      sdk
      unpatched-sdk
    ];
    shellHook = ''
      export JAVA_HOME=${jdk}
      export ANDROID_HOME=$PWD/.android/sdk
      export PATH="$ANDROID_HOME/bin:$PWD/node_modules/.bin:$PATH"

      if ! test -d .android ; then
        echo doing hacky setup stuff:

        echo "=> pull the sdk out of the nix store and into a writeable directory"
        mkdir -p .android/sdk
        cp -r ${unpatched-sdk}/* .android/sdk/

        echo "=> don't track the sdk directory"
        echo .android/ >> .gitignore

        echo "=> get react-native-cli in here"
        npm install --no-save react-native-cli

        echo "=> set up react-native plugins... need an FHS env for... reasons."
        cd .android/sdk
          $PWD/bin/sdkmanager --update
          echo "=> installing platform stuff (you'll need to accept a license in a second)..."
          $PWD/bin/sdkmanager "platforms;android-23" "build-tools;23.0.1" "add-ons;addon-google_apis-google-23"
        cd ../../
      fi;
    '';
  }

This one is super-hacky and requires usage instructions :( also probably only works on linux :/

1. Enter the environment

$ nix-shell
[...lots of console spam the first time]
[nix-shell:]$

2. If you don't have an avd set up, make one

[nix-shell:]$ android create avd -t android-23 -b x86 -d "Nexus 5" -n nexus

That command seeme to create slightly screwy avds. I ran $ android avd and then hit edit and save without any changes on mine, which seems to fix it :/

3. Start the JS server and emulator

Both commands block: either background then (add & at the end) to run in the same terminal, or open a terminal for each

[nix-shell:]$ npm start
[nix-shell:]$ emulator -avd nexus

4. Run it!

[nix-shell:]$ run-android

Note that this run-android is provided by shell.nix, and wraps the call to react-native-cli's react-native run-android command in the FHS environment so that the build works.

Python

shell.nix

with import <nixpkgs> {};
with pkgs.python27Packages;

stdenv.mkDerivation {
  name = "python";

  buildInputs = [
    pip
    python27Full
    virtualenv
  ];

  shellHook = ''
    SOURCE_DATE_EPOCH=$(date +%s)  # so that we can use python wheels
    YELLOW='\033[1;33m'
    NC="$(printf '\033[0m')"

    echo -e "''${YELLOW}Creating python environment...''${NC}"
    virtualenv --no-setuptools venv > /dev/null
    export PATH=$PWD/venv/bin:$PATH > /dev/null
    pip install -r requirements.txt > /dev/null
  '';
}

This expression sets up a python 2 environment, and installs any dependencies from requirements.txt with pip in a virtualenv.

OS library dependencies

There is a LD_LIBRARY_PATH attribute for nix packages that can help python dependencies find the libraries they may need to complete installation. You generally need to format two pieces of information together: the path to the dependency in the nix store, and /lib.

Usually this means you just need LD_LIBRARY_PATH=${<NAME>}/lib. However, sometimes nix packages divide up their outputs, with the /lib folder and its contents at their own path in the nix store. Usually, the output with lib// is called out, and can be used like LD_LIBRARY_PATH=${<NAME>.out}/lib.

If you need to put more than on dependency into LD_LIBRARY_PATH, separate them with a colon :, like for $PATH.

geos and gdal

shell.nix

with import <nixpkgs> {};
with pkgs.python27Packages;

stdenv.mkDerivation {
  name = "python";

  buildInputs = [
    gdal
    geos
    pip
    python27Full
    virtualenv
  ];
  
  LD_LIBRARY_PATH="${geos}/lib:${gdal}/lib";

  shellHook = ''
    SOURCE_DATE_EPOCH=$(date +%s)  # so that we can use python wheels
    YELLOW='\033[1;33m'
    NC="$(printf '\033[0m')"

    echo -e "''${YELLOW}Creating python environment...''${NC}"
    virtualenv --no-setuptools venv > /dev/null
    export PATH=$PWD/venv/bin:$PATH > /dev/null
    pip install -r requirements.txt > /dev/null
  '';
}

zlib

TODO

sqlite3

TODO


also, http://nixos.org/nixpkgs/manual/#using-python

Rust

TODO: mozilla nix overlay for nightly

shell.nix

with import <nixpkgs> {};

stdenv.mkDerivation {
    name = "rust";
    buildInputs = [
        rustChannels.nightly.cargo
        rustChannels.nightly.rust
    ];
}

OpenSSL

shell.nix

with import <nixpkgs> {};

stdenv.mkDerivation {
    name = "rust";
    buildInputs = [
        openssl
        rustChannels.nightly.cargo
        rustChannels.nightly.rust
    ];
    shellHook = ''
        export OPENSSL_DIR="${openssl.dev}"
        export OPENSSL_LIB_DIR="${openssl.out}/lib"
    '';
}

diesel

shell.nix

with import <nixpkgs> {};

stdenv.mkDerivation {
    name = "rust";
    buildInputs = [
        postgresql
        rustChannels.nightly.cargo
        rustChannels.nightly.rust
    ];
    shellHook = ''
        export OPENSSL_DIR="${openssl.dev}"
        export OPENSSL_LIB_DIR="${openssl.out}/lib"
        export PATH="$PWD/bin:$PATH"
        export DATABASE_URL="postgres://postgres@localhost/db"
        if ! type diesel > /dev/null 2> /dev/null; then
          cargo install diesel_cli --no-default-features --features postgres --root $PWD
        fi
        diesel setup
    '';
}

TODO: talk about running postgres in a nix-shell, and don't hard-code DATABASE_URL in such an ugly way

cargo.toml

[dependencies.diesel]
version = "0.11"
features = ["postgres"]

[dependencies.diesel_codegen]
version = "0.11"
features = ["postgres"]

.gitignore

bin/

More Repositories

1

patch-rs

Rust
38
star
2

results

Discriminated Unions including Maybe (an option type) and Result for javascript with fewer bugs
JavaScript
33
star
3

expression-parser

parse math expressions into a syntax tree
JavaScript
19
star
4

integrate

Some numerical integrators for ordinary differential equations
JavaScript
11
star
5

dom-destroyer

Remove stuff from websites like say an annoying sticky header, with two clicks.
JavaScript
11
star
6

venvgit2

Easily install libgit2 and pygit2 in a virtualenv
Python
9
star
7

feedwerk

atom feed code from werkzeug
Python
9
star
8

xxs

sort of like react or elm but worse and extra-extra-small
JavaScript
8
star
9

Django-Block-Render

Render just one block from a template, useful for AJAX (originally from django snippets 769 and 942)
Python
8
star
10

nyt-finally-said

Python
7
star
11

nix-react-native-base

some things set up to actually do work
Objective-C
6
star
12

SuperHash

Hash Anything
Python
5
star
13

route-rs

Route URL paths with safe parameter extraction
Rust
5
star
14

client-csv

No-flash client-side helper for downloading CSVs that Just Work.
JavaScript
4
star
15

ones-and-zeros

HTML
4
star
16

trc-plaintext

Text extraction project for the TRC's Honouring the Truth, Reconciling for the Future document ("The Report")
HTML
3
star
17

sfpc-py101

Python
3
star
18

commit--blog

Curate a blog of your commit messages
Python
3
star
19

partylights

R, G, B, Space, Up Down http://uniphil.github.io/partylights/
HTML
3
star
20

merge-rss-php

merge rss feeds with php
PHP
3
star
21

define

a live reference of terms, making edits super-easy and quick.
3
star
22

principle-of-the-sewing-machine

C++
2
star
23

canada-2015

Commitments made by Canada's Liberal party in the 2015 General Election
2
star
24

throwie-zine

Python
2
star
25

colour-range

test to figure out some parameters for nice ranges of colours
JavaScript
2
star
26

light-organ-method

JavaScript
2
star
27

commit--ops

Shell
2
star
28

nc14-full

full site full full yeah it's all in 100% rockin total all.
CSS
2
star
29

smooth-scroll

Smooth scrolling without jquery
JavaScript
2
star
30

retweeter

Automatically retweet tweets matching a certain word
2
star
31

time

JavaScript
2
star
32

amp-docker

Run a local development copy of AMP in a Docker container with minimal fuss
Shell
2
star
33

food

2
star
34

pyrx

Rx schema and validation system
Python
2
star
35

on-bridges

Bridges in Ontario
JavaScript
1
star
36

uberserver

documentation for the ubership house server and media and stuff
Python
1
star
37

fbattle

try to win
JavaScript
1
star
38

totechzine

website for toronto tech zine fair
HTML
1
star
39

js-tools

A reference repository for setting up some front-end web tools
1
star
40

check-it-out

check out and run arbitrary branches and commits of a web app on your dev server from github.
Python
1
star
41

Breakfast-Mix

what to put on my cereal in the mornings...
Python
1
star
42

fast-circles

Fast Circle Markers for Leaflet
JavaScript
1
star
43

of-experiments

openframeworks sketches
C++
1
star
44

FMM

Forsyth Malcolm Moler collection, currently just zeroin.
Python
1
star
45

parl

government data
Python
1
star
46

Bitter-Robot

holds a grudge
Python
1
star
47

track-time

stupid simple time logger
JavaScript
1
star
48

rtorrent-watch-drop

send .torrent links to a remote rtorrent watch folder.
JavaScript
1
star
49

colour-frequencies

Python
1
star
50

three-little-birds

Website for the Three Little Birds
JavaScript
1
star
51

abc-nix

1
star
52

blocks

ui for solving a neopets game...
JavaScript
1
star
53

gitsub

subway map of your git commits
1
star
54

tweetwars

tweet your program at @tweetwarbot... some day
JavaScript
1
star
55

archconfig

work computer stuff
Shell
1
star
56

uniphil.github.io

blah
JavaScript
1
star
57

gittime

Estimate time spent programming with git metadata.
Python
1
star
58

biscuitsandtea

Blog site in Flask.
Python
1
star
59

Open-Data-Everywhere

Public crowd-sourced Open Data Index + Cleaning Script
1
star
60

static-app-demo

Demo app for my Apps Without Ops presentation
1
star
61

huepanel

Controle lights
Python
1
star
62

anticitweet

1
star
63

trc-plaintext-old

Structured plain text of Honouring the Truth, Reconciling for the Future
Python
1
star
64

HumanFuture

Python utility to write future dates in a human-friendly way.
Python
1
star
65

browse-darker

noise texture stolen from the Mediterranean Dark theme for gnome3.
1
star
66

faker-scraper

JavaScript
1
star
67

avoid-walls

it doesn't fit in a tweet :(
JavaScript
1
star
68

cloud-compass

because dependencies suck
Python
1
star
69

hairgate

it's friday and I'm tracking editing changes to an article that was published, pulled, published elsewhere, and also the original republished
1
star